#include "shared.effect" //------------------------------------------------------------------------------ // Uniforms //------------------------------------------------------------------------------ // Texture to which the effect is applied to. uniform texture2d image; // Lift: (rgb + lift.rgb) + lift.a uniform float4 pLift; // Gamma: pow(pow(rgb, gamma.rgb), gamma.a) uniform float4 pGamma; // Gain: mul(rgb, gain.rgb) * gain.a uniform float4 pGain; // Offset: (rgb + offset.rgb) + offset.a uniform float4 pOffset; // Tinting uniform int pTintDetection; // 0 = HSV, 1 = HSL, 2 = YUV HD SDR uniform int pTintMode; // 0 = Linear, 1 = Exp, 2 = Exp2, 3 = Log, 4 = Log10 uniform float pTintExponent; uniform float3 pTintLow; uniform float3 pTintMid; uniform float3 pTintHig; // Color Correction uniform float4 pCorrection; //------------------------------------------------------------------------------ // Defines //------------------------------------------------------------------------------ #define TINT_DETECTION_HSV 0 #define TINT_DETECTION_HSL 1 #define TINT_DETECTION_YUV_SDR 2 #define TINT_MODE_LINEAR 0 #define TINT_MODE_EXP 1 #define TINT_MODE_EXP2 2 #define TINT_MODE_LOG 3 #define TINT_MODE_LOG10 4 #define C_e 2,7182818284590452353602874713527 #define C_log2_e 1.4426950408889634073599246810019 // Windows calculator: log(e(1)) / log(2) //------------------------------------------------------------------------------ // Functionality //------------------------------------------------------------------------------ float3 grade_lift(float3 v) { float3 multiplier1 = float3(1., 1., 1.) - pLift.rgb; float3 multiplier2 = float3(1., 1., 1.) - pLift.aaa; return float3(1., 1., 1.) - ((float3(1., 1., 1.) - v) * multiplier1 * multiplier2); }; float3 grade_gamma(float3 v) { return pow(abs(v), pGamma.rgb * pGamma.a) * sign(v); }; float3 grade_gain(float3 v) { return (v.rgb * pGain.rgb) * pGain.a; }; float3 grade_offset(float3 v) { return (v.rgb + pOffset.rgb) + pOffset.a; }; float3 grade_tint(float3 v) { float value = 0.; if (pTintDetection == TINT_DETECTION_HSV) { // HSV value = RGBtoHSV(v).z; } else if (pTintDetection == TINT_DETECTION_HSL) { // HSL value = RGBtoHSL(v).z; } else if (pTintDetection == TINT_DETECTION_YUV_SDR) { // YUV HD SDR const float3x3 mYUV709n = float3x3( // Normalized 0.2126, 0.7152, 0.0722, -0.1145721060573399, -0.3854278939426601, 0.5, 0.5, -0.4541529083058166, -0.0458470916941834 ); value = RGBtoYUV(v, mYUV709n).r; } if (pTintMode == TINT_MODE_LINEAR) { // Linear } else if (pTintMode == TINT_MODE_EXP) { // Exp value = 1.0 - exp2(value * pTintExponent * -C_log2_e); } else if (pTintMode == TINT_MODE_EXP2) { // Exp2 value = 1.0 - exp2(value * value * pTintExponent * pTintExponent * -C_log2_e); } else if (pTintMode == TINT_MODE_LOG) { // Log value = (log2(value) + 2.) / 2.333333; } else if (pTintMode == TINT_MODE_LOG10) { // Log10 value = (m_log10(value) + 1.) / 2.; } float3 tint = float3(0,0,0); if (value > 0.5) { tint = lerp(pTintMid, pTintHig, value * 2.0 - 1.0); } else { tint = lerp(pTintLow, pTintMid, value * 2.0); } v.rgb *= tint; return v; }; float3 grade_colorcorrection(float3 v) { float3 v1 = RGBtoHSV(v); v1.r += pCorrection.r; // Hue Shift v1.g *= pCorrection.g; // Saturation Multiplier v1.b *= pCorrection.b; // Lightness Multiplier float3 v2 = HSVtoRGB(v1); return v2; }; float3 grade_contrast(float3 v) { v -= .5; v *= pCorrection.a; v += .5; return v; } float4 PSDraw(VertexData vtx) : TARGET { float4 vo = image.Sample(PointClampSampler, vtx.uv); float3 v = vo.rgb; v = grade_lift(v); v = grade_gamma(v); v = grade_gain(v); v = grade_offset(v); v = grade_tint(v); v = grade_colorcorrection(v); v = grade_contrast(v); return float4(v, vo.a); }; technique Draw { pass { vertex_shader = DefaultVertexShader(vtx); pixel_shader = PSDraw(vtx); }; };