]> git.lizzy.rs Git - dragonfireclient.git/blob - client/shaders/object_shader/opengl_fragment.glsl
3390e72277e21ba169c61012f9115ce9c525f67b
[dragonfireclient.git] / client / shaders / object_shader / opengl_fragment.glsl
1 uniform sampler2D baseTexture;
2
3 uniform vec4 emissiveColor;
4 uniform vec4 skyBgColor;
5 uniform float fogDistance;
6 uniform vec3 eyePosition;
7
8 varying vec3 vNormal;
9 varying vec3 vPosition;
10 varying vec3 worldPosition;
11 varying lowp vec4 varColor;
12 #ifdef GL_ES
13 varying mediump vec2 varTexCoord;
14 #else
15 centroid varying vec2 varTexCoord;
16 #endif
17
18 varying vec3 eyeVec;
19 varying float vIDiff;
20
21 const float e = 2.718281828459;
22 const float BS = 10.0;
23 const float fogStart = FOG_START;
24 const float fogShadingParameter = 1.0 / (1.0 - fogStart);
25
26 #ifdef ENABLE_DYNAMIC_SHADOWS
27         // shadow texture
28         uniform sampler2D ShadowMapSampler;
29         // shadow uniforms
30         uniform vec3 v_LightDirection;
31         uniform float f_textureresolution;
32         uniform mat4 m_ShadowViewProj;
33         uniform float f_shadowfar;
34         uniform float f_timeofday;
35         varying float normalOffsetScale;
36         varying float adj_shadow_strength;
37         varying float cosLight;
38         varying float f_normal_length;
39 #endif
40
41 #if ENABLE_TONE_MAPPING
42 /* Hable's UC2 Tone mapping parameters
43         A = 0.22;
44         B = 0.30;
45         C = 0.10;
46         D = 0.20;
47         E = 0.01;
48         F = 0.30;
49         W = 11.2;
50         equation used:  ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F
51 */
52
53 vec3 uncharted2Tonemap(vec3 x)
54 {
55         return ((x * (0.22 * x + 0.03) + 0.002) / (x * (0.22 * x + 0.3) + 0.06)) - 0.03333;
56 }
57
58 vec4 applyToneMapping(vec4 color)
59 {
60         color = vec4(pow(color.rgb, vec3(2.2)), color.a);
61         const float gamma = 1.6;
62         const float exposureBias = 5.5;
63         color.rgb = uncharted2Tonemap(exposureBias * color.rgb);
64         // Precalculated white_scale from
65         //vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
66         vec3 whiteScale = vec3(1.036015346);
67         color.rgb *= whiteScale;
68         return vec4(pow(color.rgb, vec3(1.0 / gamma)), color.a);
69 }
70 #endif
71
72 #ifdef ENABLE_DYNAMIC_SHADOWS
73 const float bias0 = 0.9;
74 const float zPersFactor = 0.5;
75 const float bias1 = 1.0 - bias0;
76
77 vec4 getPerspectiveFactor(in vec4 shadowPosition)
78 {
79         float pDistance = length(shadowPosition.xy);
80         float pFactor = pDistance * bias0 + bias1;
81         shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPersFactor);
82
83         return shadowPosition;
84 }
85
86 // assuming near is always 1.0
87 float getLinearDepth()
88 {
89         return 2.0 * f_shadowfar / (f_shadowfar + 1.0 - (2.0 * gl_FragCoord.z - 1.0) * (f_shadowfar - 1.0));
90 }
91
92 vec3 getLightSpacePosition()
93 {
94         vec4 pLightSpace;
95         float normalBias = 0.0005 * getLinearDepth() * cosLight + normalOffsetScale;
96         pLightSpace = m_ShadowViewProj * vec4(worldPosition + normalBias * normalize(vNormal), 1.0);
97         pLightSpace = getPerspectiveFactor(pLightSpace);
98         return pLightSpace.xyz * 0.5 + 0.5;
99 }
100
101 #ifdef COLORED_SHADOWS
102
103 // c_precision of 128 fits within 7 base-10 digits
104 const float c_precision = 128.0;
105 const float c_precisionp1 = c_precision + 1.0;
106
107 float packColor(vec3 color)
108 {
109         return floor(color.b * c_precision + 0.5)
110                 + floor(color.g * c_precision + 0.5) * c_precisionp1
111                 + floor(color.r * c_precision + 0.5) * c_precisionp1 * c_precisionp1;
112 }
113
114 vec3 unpackColor(float value)
115 {
116         vec3 color;
117         color.b = mod(value, c_precisionp1) / c_precision;
118         color.g = mod(floor(value / c_precisionp1), c_precisionp1) / c_precision;
119         color.r = floor(value / (c_precisionp1 * c_precisionp1)) / c_precision;
120         return color;
121 }
122
123 vec4 getHardShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
124 {
125         vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy).rgba;
126
127         float visibility = step(0.0, (realDistance-2e-5) - texDepth.r);
128         vec4 result = vec4(visibility, vec3(0.0,0.0,0.0));//unpackColor(texDepth.g));
129         if (visibility < 0.1) {
130                 visibility = step(0.0, (realDistance-2e-5) - texDepth.r);
131                 result = vec4(visibility, unpackColor(texDepth.a));
132         }
133         return result;
134 }
135
136 #else
137
138 float getHardShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
139 {
140         float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
141         float visibility = step(0.0, (realDistance-2e-5) - texDepth);
142
143         return visibility;
144 }
145
146 #endif
147
148 #if SHADOW_FILTER == 2
149         #define PCFBOUND 3.5
150         #define PCFSAMPLES 64.0
151 #elif SHADOW_FILTER == 1
152         #define PCFBOUND 1.5
153         #if defined(POISSON_FILTER)
154                 #define PCFSAMPLES 32.0
155         #else
156                 #define PCFSAMPLES 16.0
157         #endif
158 #else
159         #define PCFBOUND 0.0
160         #if defined(POISSON_FILTER)
161                 #define PCFSAMPLES 4.0
162         #else
163                 #define PCFSAMPLES 1.0
164         #endif
165 #endif
166
167 #ifdef POISSON_FILTER
168 const vec2[64] poissonDisk = vec2[64](
169         vec2(0.170019, -0.040254),
170         vec2(-0.299417, 0.791925),
171         vec2(0.645680, 0.493210),
172         vec2(-0.651784, 0.717887),
173         vec2(0.421003, 0.027070),
174         vec2(-0.817194, -0.271096),
175         vec2(-0.705374, -0.668203),
176         vec2(0.977050, -0.108615),
177         vec2(0.063326, 0.142369),
178         vec2(0.203528, 0.214331),
179         vec2(-0.667531, 0.326090),
180         vec2(-0.098422, -0.295755),
181         vec2(-0.885922, 0.215369),
182         vec2(0.566637, 0.605213),
183         vec2(0.039766, -0.396100),
184         vec2(0.751946, 0.453352),
185         vec2(0.078707, -0.715323),
186         vec2(-0.075838, -0.529344),
187         vec2(0.724479, -0.580798),
188         vec2(0.222999, -0.215125),
189         vec2(-0.467574, -0.405438),
190         vec2(-0.248268, -0.814753),
191         vec2(0.354411, -0.887570),
192         vec2(0.175817, 0.382366),
193         vec2(0.487472, -0.063082),
194         vec2(0.355476, 0.025357),
195         vec2(-0.084078, 0.898312),
196         vec2(0.488876, -0.783441),
197         vec2(0.470016, 0.217933),
198         vec2(-0.696890, -0.549791),
199         vec2(-0.149693, 0.605762),
200         vec2(0.034211, 0.979980),
201         vec2(0.503098, -0.308878),
202         vec2(-0.016205, -0.872921),
203         vec2(0.385784, -0.393902),
204         vec2(-0.146886, -0.859249),
205         vec2(0.643361, 0.164098),
206         vec2(0.634388, -0.049471),
207         vec2(-0.688894, 0.007843),
208         vec2(0.464034, -0.188818),
209         vec2(-0.440840, 0.137486),
210         vec2(0.364483, 0.511704),
211         vec2(0.034028, 0.325968),
212         vec2(0.099094, -0.308023),
213         vec2(0.693960, -0.366253),
214         vec2(0.678884, -0.204688),
215         vec2(0.001801, 0.780328),
216         vec2(0.145177, -0.898984),
217         vec2(0.062655, -0.611866),
218         vec2(0.315226, -0.604297),
219         vec2(-0.780145, 0.486251),
220         vec2(-0.371868, 0.882138),
221         vec2(0.200476, 0.494430),
222         vec2(-0.494552, -0.711051),
223         vec2(0.612476, 0.705252),
224         vec2(-0.578845, -0.768792),
225         vec2(-0.772454, -0.090976),
226         vec2(0.504440, 0.372295),
227         vec2(0.155736, 0.065157),
228         vec2(0.391522, 0.849605),
229         vec2(-0.620106, -0.328104),
230         vec2(0.789239, -0.419965),
231         vec2(-0.545396, 0.538133),
232         vec2(-0.178564, -0.596057)
233 );
234
235 #ifdef COLORED_SHADOWS
236
237 vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
238 {
239         vec2 clampedpos;
240         vec4 visibility = vec4(0.0);
241
242         float texture_size = 1.0 / (f_textureresolution * 0.5);
243         int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-PCFSAMPLES)));
244         int end_offset = int(PCFSAMPLES) + init_offset;
245
246         for (int x = init_offset; x < end_offset; x++) {
247                 clampedpos = poissonDisk[x] * texture_size * SOFTSHADOWRADIUS + smTexCoord.xy;
248                 visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
249         }
250
251         return visibility / PCFSAMPLES;
252 }
253
254 #else
255
256 float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
257 {
258         vec2 clampedpos;
259         float visibility = 0.0;
260
261         float texture_size = 1.0 / (f_textureresolution * 0.5);
262         int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-PCFSAMPLES)));
263         int end_offset = int(PCFSAMPLES) + init_offset;
264
265         for (int x = init_offset; x < end_offset; x++) {
266                 clampedpos = poissonDisk[x] * texture_size * SOFTSHADOWRADIUS + smTexCoord.xy;
267                 visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
268         }
269
270         return visibility / PCFSAMPLES;
271 }
272
273 #endif
274
275 #else
276 /* poisson filter disabled */
277
278 #ifdef COLORED_SHADOWS
279
280 vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
281 {
282         vec2 clampedpos;
283         vec4 visibility = vec4(0.0);
284         float sradius=0.0;
285         if( PCFBOUND>0)
286                 sradius = SOFTSHADOWRADIUS / PCFBOUND;  
287         float texture_size = 1.0 / (f_textureresolution * 0.5);
288         float y, x;
289         // basic PCF filter
290         for (y = -PCFBOUND; y <= PCFBOUND; y += 1.0)
291         for (x = -PCFBOUND; x <= PCFBOUND; x += 1.0) {
292                 clampedpos = vec2(x,y) * texture_size* sradius +  smTexCoord.xy;
293                 visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
294         }
295
296         return visibility / PCFSAMPLES;
297 }
298
299 #else
300 float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
301 {
302         vec2 clampedpos;
303         float visibility = 0.0;
304         float sradius=0.0;
305         if( PCFBOUND>0)
306                 sradius = SOFTSHADOWRADIUS / PCFBOUND;  
307         
308         float texture_size = 1.0 / (f_textureresolution * 0.5);
309         float y, x;
310         // basic PCF filter
311         for (y = -PCFBOUND; y <= PCFBOUND; y += 1.0)
312         for (x = -PCFBOUND; x <= PCFBOUND; x += 1.0) {
313                 clampedpos =  vec2(x,y) * texture_size * sradius + smTexCoord.xy;
314                 visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
315         }
316
317         return visibility / PCFSAMPLES;
318 }
319
320 #endif
321
322 #endif
323 #endif
324
325 void main(void)
326 {
327         vec3 color;
328         vec2 uv = varTexCoord.st;
329         vec4 base = texture2D(baseTexture, uv).rgba;
330
331         // If alpha is zero, we can just discard the pixel. This fixes transparency
332         // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa,
333         // and also on GLES 2, where GL_ALPHA_TEST is missing entirely.
334 #ifdef USE_DISCARD
335         if (base.a == 0.0)
336                 discard;
337 #endif
338 #ifdef USE_DISCARD_REF
339         if (base.a < 0.5)
340                 discard;
341 #endif
342
343         color = base.rgb;
344         vec4 col = vec4(color.rgb, base.a);
345         col.rgb *= varColor.rgb;
346         col.rgb *= emissiveColor.rgb * vIDiff;
347
348 #ifdef ENABLE_DYNAMIC_SHADOWS
349         float shadow_int = 0.0;
350         vec3 shadow_color = vec3(0.0, 0.0, 0.0);
351         vec3 posLightSpace = getLightSpacePosition();
352
353 #ifdef COLORED_SHADOWS
354         vec4 visibility;
355         if (cosLight > 0.0)
356                 visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
357         else
358                 visibility = vec4(1.0, 0.0, 0.0, 0.0);
359         shadow_int = visibility.r;
360         shadow_color = visibility.gba;
361 #else
362         shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
363 #endif
364
365         if (f_normal_length != 0 && cosLight <= 0.001) {
366                 shadow_int = clamp(shadow_int + 0.5 * abs(cosLight), 0.0, 1.0);
367         }
368
369         shadow_int = 1.0 - (shadow_int * adj_shadow_strength);
370
371         col.rgb = mix(shadow_color, col.rgb, shadow_int) * shadow_int;
372 #endif
373
374
375
376 #if ENABLE_TONE_MAPPING
377         col = applyToneMapping(col);
378 #endif
379
380         // Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?),
381         // the fog will only be rendered correctly if the last operation before the
382         // clamp() is an addition. Else, the clamp() seems to be ignored.
383         // E.g. the following won't work:
384         //      float clarity = clamp(fogShadingParameter
385         //              * (fogDistance - length(eyeVec)) / fogDistance), 0.0, 1.0);
386         // As additions usually come for free following a multiplication, the new formula
387         // should be more efficient as well.
388         // Note: clarity = (1 - fogginess)
389         float clarity = clamp(fogShadingParameter
390                 - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
391         col = mix(skyBgColor, col, clarity);
392
393         gl_FragColor = vec4(col.rgb, base.a);
394 }