forked from crosire/reshade-shaders
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Curves.fx
198 lines (164 loc) · 6.1 KB
/
Curves.fx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/**
* Curves
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*
* Curves, uses S-curves to increase contrast, without clipping highlights and shadows.
*/
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 <
ui_type = "drag";
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;
}
}