-
Notifications
You must be signed in to change notification settings - Fork 71
Expand file tree
/
Copy pathcameraEffects_fp.glsl
More file actions
219 lines (171 loc) · 6.42 KB
/
cameraEffects_fp.glsl
File metadata and controls
219 lines (171 loc) · 6.42 KB
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
===========================================================================
Copyright (C) 2009-2010 Robert Beckebans <trebor_7@users.sourceforge.net>
This file is part of XreaL source code.
XreaL source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
XreaL source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with XreaL source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/* cameraEffects_fp.glsl */
#define CAMERAEFFECTS_GLSL
uniform sampler2D u_CurrentMap;
#if defined(r_colorGrading)
uniform sampler3D u_ColorMap3D;
#endif
uniform vec4 u_ColorModulate;
uniform float u_GlobalLightFactor; // 1 / tr.identityLight
uniform float u_InverseGamma;
uniform bool u_SRGB;
void convertToSRGB(inout vec3 color) {
#if defined(r_accurateSRGB)
float threshold = 0.0031308f;
bvec3 cutoff = lessThan(color, vec3(threshold));
vec3 low = vec3(12.92f) * color;
vec3 high = vec3(1.055f) * pow(color, vec3(1.0f / 2.4f)) - vec3(0.055f);
#if __VERSION__ > 120
color = mix(high, low, cutoff);
#else
color = mix(high, low, vec3(cutoff));
#endif
#else
float inverse = 0.4545454f; // 1 / 2.2
color = pow(color, vec3(inverse));
#endif
}
uniform float u_Exposure;
// Tone mapping is not available when high-precision float framebuffer isn't enabled or supported.
#if defined(r_highPrecisionRendering) && defined(HAVE_ARB_texture_float)
/* x: contrast
y: highlightsCompressionSpeed
z: shoulderClip
w: highlightsCompression */
uniform bool u_Tonemap;
uniform vec4 u_TonemapParms;
vec3 TonemapLottes( vec3 color ) {
// Lottes 2016, "Advanced Techniques and Optimization of HDR Color Pipelines"
return pow( color, vec3( u_TonemapParms[0] ) )
/ ( pow( color, vec3( u_TonemapParms[0] * u_TonemapParms[1] ) ) * u_TonemapParms[2] + u_TonemapParms[3] );
}
#endif
DECLARE_OUTPUT(vec4)
void main()
{
#insert material_fp
// calculate the screen texcoord in the 0.0 to 1.0 range
vec2 st = gl_FragCoord.st / r_FBufSize;
vec4 color = texture2D(u_CurrentMap, st);
color *= u_GlobalLightFactor;
color.rgb *= u_Exposure;
#if defined(r_highPrecisionRendering) && defined(HAVE_ARB_texture_float)
if( u_Tonemap ) {
#if defined(r_toneMappingLowLightRestorationSteps)
vec3 mapped = TonemapLottes( color.rgb );
/* The threshold is the color channel value under which we blend
the tone mapped color with the original color to restore low
light in dark shadows clipped by the tone mapper.
The threshold is in sRGB space for convenience. For example,
a threshold of 5 would make sure we start restoring low light
when the sRGB-converted tone mapped color goes below #050505,
a threshold of 10 would do the same for #0A0A0A and 16 would
target #101010.
We need to convert the threshold back to linear because we're
still operating in linear space at this point.
We don't exactly restore up to the threshold, we blend half
the tone-mapped color with half the color, to avoid producing
color artifacts that would happen by bumping the RGB channels
directly. Each step does the half blend again, so we can say
that the restoration _tends to the threshold_ with each step.
Each step is done with a small bias to lower the threshold a bit
every step to not not always use the exact same frontier between
the area having light restored and the area being kept unmodified,
then smoothly blending the restoratiin with a gradient.
Since we blend with half the colors, a threshold smaller than 2
would do nothing. */
float threshold;
if ( u_SRGB )
{
threshold = pow( float( r_toneMappingLowLightRestorationThreshold ) / 255.0f, 2.2f );
}
else
{
threshold = float( r_toneMappingLowLightRestorationThreshold ) / 255.0f;
}
#if defined(r_showToneMappingLowLightRestoration)
color.rgb = vec3(1.0f, 0.0f, 0.0f);
#endif
bvec3 colorCutoff = lessThan( color.rgb, vec3( threshold ) );
for ( int i = 0; i < r_toneMappingLowLightRestorationSteps; i++ )
{
float t = threshold - ( i * ( threshold / 10.0f ) );
bvec3 mappedCutoff = lessThan( mapped, vec3(t) );
bvec3 cutoff = bvec3(ivec3(mappedCutoff) * ivec3(colorCutoff));
#if __VERSION__ > 120
vec3 interpolation = vec3(0.5f) * vec3(cutoff);
#else
vec3 interpolation = 0.5f * cutoff;
#endif
mapped = mix( mapped, color.rgb, interpolation );
}
color.rgb = mapped;
#else
color.rgb = TonemapLottes( color.rgb );
#endif
}
#endif
#if defined(r_lowLightDithering)
{
float threshold;
if ( u_SRGB )
{
threshold = pow( float( r_lowLightDitheringThreshold ) / 255.0f, 2.2f );
}
else
{
threshold = float( r_lowLightDitheringThreshold ) / 255.0f;
}
float sum = ( color.r + color.g + color.b );
if ( sum != 0.0f && sum < ( 3.0f * threshold ) )
{
const float bayer[ 16 ] = {
0.0f, 8.0f, 2.0f, 10.0f,
12.0f, 4.0f, 14.0f, 6.0f,
3.0f, 11.0f, 1.0f, 9.0f,
15.0f, 7.0f, 13.0f, 5.0f
};
float dither = bayer[
int( mod( gl_FragCoord.x, 4.0f ) ) +
int( mod( gl_FragCoord.y, 4.0f ) ) * 4
] / 16.0f;
color.rgb += vec3( ( ( dither - 0.5f ) / 255.0f ) * r_lowLightDitheringAmplitudeFactor );
#if defined(r_showLowLightDithering)
color.rgb = vec3(1.0f, 0.0f, 0.0f);
#endif
}
}
#endif
color.rgb = clamp( color.rgb, vec3( 0.0f ), vec3( 1.0f ) );
if ( u_SRGB )
{
convertToSRGB( color.rgb );
}
#if defined(r_colorGrading)
// apply color grading
vec3 colCoord = color.rgb * 15.0 / 16.0 + 0.5 / 16.0;
colCoord.z *= 0.25;
color.rgb = u_ColorModulate.x * texture3D(u_ColorMap3D, colCoord).rgb;
color.rgb += u_ColorModulate.y * texture3D(u_ColorMap3D, colCoord + vec3(0.0, 0.0, 0.25)).rgb;
color.rgb += u_ColorModulate.z * texture3D(u_ColorMap3D, colCoord + vec3(0.0, 0.0, 0.50)).rgb;
color.rgb += u_ColorModulate.w * texture3D(u_ColorMap3D, colCoord + vec3(0.0, 0.0, 0.75)).rgb;
#endif
color.xyz = pow(color.xyz, vec3(u_InverseGamma));
outputColor = color;
}