obs-StreamFX/data/effects/color-grade.effect
2021-04-22 12:12:49 +02:00

145 lines
3.9 KiB
Text

#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);
};
};