#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) { // same as grade_offset? return (v.rgb + pLift.rgb) + pLift.a; }; float3 grade_gamma(float3 v) { float3 s = sign(v); // Store sign for later use. float3 u = abs(v); // Remove sign u.rgb = pow(pow(u.rgb, pGamma.rgb), pGamma.a); return u * s; // Restore sign. }; 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 = { // 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 = (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); // Contrast v2.rgb = ((v2.rgb - 0.5) * max(pCorrection.a, 0)) + 0.5; return v2; }; float4 PSDraw(VertexData vtx) : TARGET { float4 v1 = image.Sample(PointClampSampler, vtx.uv); float3 v2 = grade_lift(v1.rgb); float3 v3 = grade_gamma(v2); float3 v4 = grade_gain(v3); float3 v5 = grade_offset(v4); float3 v6 = grade_tint(v5); float3 v7 = grade_colorcorrection(v6); float3 vf = v7; return float4(vf, v1.a); }; technique Draw { pass { vertex_shader = DefaultVertexShader(vtx); pixel_shader = PSDraw(vtx); }; };