200 lines
6.1 KiB
HLSL
200 lines
6.1 KiB
HLSL
/**
|
|
* Curves
|
|
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
|
|
*
|
|
* Curves, uses S-curves to increase contrast, without clipping highlights and shadows.
|
|
*/
|
|
|
|
#include "ReShadeUI.fxh"
|
|
|
|
uniform int Mode <
|
|
ui_type = "combo";
|
|
ui_items = "Luma\0Chroma\0Both Luma and Chroma\0";
|
|
ui_tooltip = "Choose what to apply contrast to.";
|
|
> = 0;
|
|
uniform int Formula <
|
|
ui_type = "combo";
|
|
ui_items = "Sine\0Abs split\0Smoothstep\0Exp formula\0Simplified Catmull-Rom (0,0,1,1)\0Perlins Smootherstep\0Abs add\0Techicolor Cinestyle\0Parabola\0Half-circles\0Polynomial split\0";
|
|
ui_tooltip = "The contrast s-curve you want to use. Note that Technicolor Cinestyle is practically identical to Sine, but runs slower. In fact I think the difference might only be due to rounding errors. I prefer 2 myself, but 3 is a nice alternative with a little more effect (but harsher on the highlight and shadows) and it's the fastest formula.";
|
|
> = 4;
|
|
|
|
uniform float Contrast < __UNIFORM_SLIDER_FLOAT1
|
|
ui_min = -1.0; ui_max = 1.0;
|
|
ui_tooltip = "The amount of contrast you want.";
|
|
> = 0.65;
|
|
|
|
#include "ReShade.fxh"
|
|
|
|
float4 CurvesPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
|
|
{
|
|
float4 colorInput = tex2D(ReShade::BackBuffer, texcoord);
|
|
float3 lumCoeff = float3(0.2126, 0.7152, 0.0722); //Values to calculate luma with
|
|
float Contrast_blend = Contrast;
|
|
const float PI = 3.1415927;
|
|
|
|
/*-----------------------------------------------------------.
|
|
/ Separation of Luma and Chroma /
|
|
'-----------------------------------------------------------*/
|
|
|
|
// -- Calculate Luma and Chroma if needed --
|
|
//calculate luma (grey)
|
|
float luma = dot(lumCoeff, colorInput.rgb);
|
|
//calculate chroma
|
|
float3 chroma = colorInput.rgb - luma;
|
|
|
|
// -- Which value to put through the contrast formula? --
|
|
// I name it x because makes it easier to copy-paste to Graphtoy or Wolfram Alpha or another graphing program
|
|
float3 x;
|
|
if (Mode == 0)
|
|
x = luma; //if the curve should be applied to Luma
|
|
else if (Mode == 1)
|
|
x = chroma, //if the curve should be applied to Chroma
|
|
x = x * 0.5 + 0.5; //adjust range of Chroma from -1 -> 1 to 0 -> 1
|
|
else
|
|
x = colorInput.rgb; //if the curve should be applied to both Luma and Chroma
|
|
|
|
/*-----------------------------------------------------------.
|
|
/ Contrast formulas /
|
|
'-----------------------------------------------------------*/
|
|
|
|
// -- Curve 1 --
|
|
if (Formula == 0)
|
|
{
|
|
x = sin(PI * 0.5 * x); // Sin - 721 amd fps, +vign 536 nv
|
|
x *= x;
|
|
|
|
//x = 0.5 - 0.5*cos(PI*x);
|
|
//x = 0.5 * -sin(PI * -x + (PI*0.5)) + 0.5;
|
|
}
|
|
|
|
// -- Curve 2 --
|
|
if (Formula == 1)
|
|
{
|
|
x = x - 0.5;
|
|
x = (x / (0.5 + abs(x))) + 0.5;
|
|
|
|
//x = ( (x - 0.5) / (0.5 + abs(x-0.5)) ) + 0.5;
|
|
}
|
|
|
|
// -- Curve 3 --
|
|
if (Formula == 2)
|
|
{
|
|
//x = smoothstep(0.0,1.0,x); //smoothstep
|
|
x = x*x*(3.0 - 2.0*x); //faster smoothstep alternative - 776 amd fps, +vign 536 nv
|
|
//x = x - 2.0 * (x - 1.0) * x* (x- 0.5); //2.0 is contrast. Range is 0.0 to 2.0
|
|
}
|
|
|
|
// -- Curve 4 --
|
|
if (Formula == 3)
|
|
{
|
|
x = (1.0524 * exp(6.0 * x) - 1.05248) / (exp(6.0 * x) + 20.0855); //exp formula
|
|
}
|
|
|
|
// -- Curve 5 --
|
|
if (Formula == 4)
|
|
{
|
|
//x = 0.5 * (x + 3.0 * x * x - 2.0 * x * x * x); //a simplified catmull-rom (0,0,1,1) - btw smoothstep can also be expressed as a simplified catmull-rom using (1,0,1,0)
|
|
//x = (0.5 * x) + (1.5 -x) * x*x; //estrin form - faster version
|
|
x = x * (x * (1.5 - x) + 0.5); //horner form - fastest version
|
|
|
|
Contrast_blend = Contrast * 2.0; //I multiply by two to give it a strength closer to the other curves.
|
|
}
|
|
|
|
// -- Curve 6 --
|
|
if (Formula == 5)
|
|
{
|
|
x = x*x*x*(x*(x*6.0 - 15.0) + 10.0); //Perlins smootherstep
|
|
}
|
|
|
|
// -- Curve 7 --
|
|
if (Formula == 6)
|
|
{
|
|
//x = ((x-0.5) / ((0.5/(4.0/3.0)) + abs((x-0.5)*1.25))) + 0.5;
|
|
x = x - 0.5;
|
|
x = x / ((abs(x)*1.25) + 0.375) + 0.5;
|
|
//x = ( (x-0.5) / ((abs(x-0.5)*1.25) + (0.5/(4.0/3.0))) ) + 0.5;
|
|
}
|
|
|
|
// -- Curve 8 --
|
|
if (Formula == 7)
|
|
{
|
|
x = (x * (x * (x * (x * (x * (x * (1.6 * x - 7.2) + 10.8) - 4.2) - 3.6) + 2.7) - 1.8) + 2.7) * x * x; //Techicolor Cinestyle - almost identical to curve 1
|
|
}
|
|
|
|
// -- Curve 9 --
|
|
if (Formula == 8)
|
|
{
|
|
x = -0.5 * (x*2.0 - 1.0) * (abs(x*2.0 - 1.0) - 2.0) + 0.5; //parabola
|
|
}
|
|
|
|
// -- Curve 10 --
|
|
if (Formula == 9)
|
|
{
|
|
float3 xstep = step(x, 0.5); //tenary might be faster here
|
|
float3 xstep_shift = (xstep - 0.5);
|
|
float3 shifted_x = x + xstep_shift;
|
|
|
|
x = abs(xstep - sqrt(-shifted_x * shifted_x + shifted_x)) - xstep_shift;
|
|
|
|
//x = abs(step(x,0.5)-sqrt(-(x+step(x,0.5)-0.5)*(x+step(x,0.5)-0.5)+(x+step(x,0.5)-0.5)))-(step(x,0.5)-0.5); //single line version of the above
|
|
|
|
//x = 0.5 + (sign(x-0.5)) * sqrt(0.25-(x-trunc(x*2))*(x-trunc(x*2))); //worse
|
|
|
|
/* // if/else - even worse
|
|
if (x-0.5)
|
|
x = 0.5-sqrt(0.25-x*x);
|
|
else
|
|
x = 0.5+sqrt(0.25-(x-1)*(x-1));
|
|
*/
|
|
|
|
//x = (abs(step(0.5,x)-clamp( 1-sqrt(1-abs(step(0.5,x)- frac(x*2%1)) * abs(step(0.5,x)- frac(x*2%1))),0 ,1))+ step(0.5,x) )*0.5; //worst so far
|
|
|
|
//TODO: Check if I could use an abs split instead of step. It might be more efficient
|
|
|
|
Contrast_blend = Contrast * 0.5; //I divide by two to give it a strength closer to the other curves.
|
|
}
|
|
|
|
// -- Curve 11 --
|
|
if (Formula == 10)
|
|
{
|
|
float3 a = float3(0.0, 0.0, 0.0);
|
|
float3 b = float3(0.0, 0.0, 0.0);
|
|
|
|
a = x * x * 2.0;
|
|
b = (2.0 * -x + 4.0) * x - 1.0;
|
|
x = (x < 0.5) ? a : b;
|
|
}
|
|
|
|
/*-----------------------------------------------------------.
|
|
/ Joining of Luma and Chroma /
|
|
'-----------------------------------------------------------*/
|
|
|
|
if (Mode == 0) // Only Luma
|
|
{
|
|
x = lerp(luma, x, Contrast_blend); //Blend by Contrast
|
|
colorInput.rgb = x + chroma; //Luma + Chroma
|
|
}
|
|
else if (Mode == 1) // Only Chroma
|
|
{
|
|
x = x * 2.0 - 1.0; //adjust the Chroma range back to -1 -> 1
|
|
float3 color = luma + x; //Luma + Chroma
|
|
colorInput.rgb = lerp(colorInput.rgb, color, Contrast_blend); //Blend by Contrast
|
|
}
|
|
else // Both Luma and Chroma
|
|
{
|
|
float3 color = x; //if the curve should be applied to both Luma and Chroma
|
|
colorInput.rgb = lerp(colorInput.rgb, color, Contrast_blend); //Blend by Contrast
|
|
}
|
|
|
|
return colorInput;
|
|
}
|
|
|
|
technique Curves
|
|
{
|
|
pass
|
|
{
|
|
VertexShader = PostProcessVS;
|
|
PixelShader = CurvesPass;
|
|
}
|
|
}
|