]> git.lizzy.rs Git - dragonfireclient.git/blob - client/shaders/nodes_shader/opengl_fragment.glsl
Fix GLES2 discard behaviour (texture transparency)
[dragonfireclient.git] / client / shaders / nodes_shader / opengl_fragment.glsl
1 uniform sampler2D baseTexture;
2
3 uniform vec4 skyBgColor;
4 uniform float fogDistance;
5 uniform vec3 eyePosition;
6
7 // The cameraOffset is the current center of the visible world.
8 uniform vec3 cameraOffset;
9 uniform float animationTimer;
10 #ifdef ENABLE_DYNAMIC_SHADOWS
11         // shadow texture
12         uniform sampler2D ShadowMapSampler;
13         // shadow uniforms
14         uniform vec3 v_LightDirection;
15         uniform float f_textureresolution;
16         uniform mat4 m_ShadowViewProj;
17         uniform float f_shadowfar;
18         varying float normalOffsetScale;
19         varying float adj_shadow_strength;
20         varying float cosLight;
21         varying float f_normal_length;
22 #endif
23
24
25 varying vec3 vNormal;
26 varying vec3 vPosition;
27 // World position in the visible world (i.e. relative to the cameraOffset.)
28 // This can be used for many shader effects without loss of precision.
29 // If the absolute position is required it can be calculated with
30 // cameraOffset + worldPosition (for large coordinates the limits of float
31 // precision must be considered).
32 varying vec3 worldPosition;
33 varying lowp vec4 varColor;
34 #ifdef GL_ES
35 varying mediump vec2 varTexCoord;
36 #else
37 centroid varying vec2 varTexCoord;
38 #endif
39 varying vec3 eyeVec;
40 varying float nightRatio;
41
42 const float fogStart = FOG_START;
43 const float fogShadingParameter = 1.0 / ( 1.0 - fogStart);
44
45
46
47 #ifdef ENABLE_DYNAMIC_SHADOWS
48 const float bias0 = 0.9;
49 const float zPersFactor = 0.5;
50 const float bias1 = 1.0 - bias0 + 1e-6;
51
52 vec4 getPerspectiveFactor(in vec4 shadowPosition)
53 {
54
55         float pDistance = length(shadowPosition.xy);
56         float pFactor = pDistance * bias0 + bias1;
57
58         shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPersFactor);
59
60         return shadowPosition;
61 }
62
63 // assuming near is always 1.0
64 float getLinearDepth()
65 {
66         return 2.0 * f_shadowfar / (f_shadowfar + 1.0 - (2.0 * gl_FragCoord.z - 1.0) * (f_shadowfar - 1.0));
67 }
68
69 vec3 getLightSpacePosition()
70 {
71         vec4 pLightSpace;
72         // some drawtypes have zero normals, so we need to handle it :(
73         #if DRAW_TYPE == NDT_PLANTLIKE
74         pLightSpace = m_ShadowViewProj * vec4(worldPosition, 1.0);
75         #else
76         float offsetScale = (0.0057 * getLinearDepth() + normalOffsetScale);
77         pLightSpace = m_ShadowViewProj * vec4(worldPosition + offsetScale * normalize(vNormal), 1.0);
78         #endif
79         pLightSpace = getPerspectiveFactor(pLightSpace);
80         return pLightSpace.xyz * 0.5 + 0.5;
81 }
82 // custom smoothstep implementation because it's not defined in glsl1.2
83 // https://docs.gl/sl4/smoothstep
84 float mtsmoothstep(in float edge0, in float edge1, in float x)
85 {
86         float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
87         return t * t * (3.0 - 2.0 * t);
88 }
89
90 #ifdef COLORED_SHADOWS
91
92 // c_precision of 128 fits within 7 base-10 digits
93 const float c_precision = 128.0;
94 const float c_precisionp1 = c_precision + 1.0;
95
96 float packColor(vec3 color)
97 {
98         return floor(color.b * c_precision + 0.5)
99                 + floor(color.g * c_precision + 0.5) * c_precisionp1
100                 + floor(color.r * c_precision + 0.5) * c_precisionp1 * c_precisionp1;
101 }
102
103 vec3 unpackColor(float value)
104 {
105         vec3 color;
106         color.b = mod(value, c_precisionp1) / c_precision;
107         color.g = mod(floor(value / c_precisionp1), c_precisionp1) / c_precision;
108         color.r = floor(value / (c_precisionp1 * c_precisionp1)) / c_precision;
109         return color;
110 }
111
112 vec4 getHardShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
113 {
114         vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy).rgba;
115
116         float visibility = step(0.0, realDistance - texDepth.r);
117         vec4 result = vec4(visibility, vec3(0.0,0.0,0.0));//unpackColor(texDepth.g));
118         if (visibility < 0.1) {
119                 visibility = step(0.0, realDistance - texDepth.b);
120                 result = vec4(visibility, unpackColor(texDepth.a));
121         }
122         return result;
123 }
124
125 #else
126
127 float getHardShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
128 {
129         float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
130         float visibility = step(0.0, realDistance - texDepth);
131         return visibility;
132 }
133
134 #endif
135
136
137 #if SHADOW_FILTER == 2
138         #define PCFBOUND 3.5
139         #define PCFSAMPLES 64.0
140 #elif SHADOW_FILTER == 1
141         #define PCFBOUND 1.5
142         #if defined(POISSON_FILTER)
143                 #define PCFSAMPLES 32.0
144         #else
145                 #define PCFSAMPLES 16.0
146         #endif
147 #else
148         #define PCFBOUND 0.0
149         #if defined(POISSON_FILTER)
150                 #define PCFSAMPLES 4.0
151         #else
152                 #define PCFSAMPLES 1.0
153         #endif
154 #endif
155 #ifdef COLORED_SHADOWS
156 float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
157 {
158         vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy);
159         float depth = max(realDistance - texDepth.r, realDistance - texDepth.b);
160         return depth;
161 }
162 #else
163 float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
164 {
165         float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
166         float depth = realDistance - texDepth;
167         return depth;
168 }
169 #endif
170
171 float getBaseLength(vec2 smTexCoord)
172 {
173         float l = length(2.0 * smTexCoord.xy - 1.0);     // length in texture coords
174         return bias1 / (1.0 / l - bias0);                                // return to undistorted coords
175 }
176
177 float getDeltaPerspectiveFactor(float l)
178 {
179         return 0.1 / (bias0 * l + bias1);                      // original distortion factor, divided by 10
180 }
181
182 float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance, float multiplier)
183 {
184         float baseLength = getBaseLength(smTexCoord);
185         float perspectiveFactor;
186
187         // Return fast if sharp shadows are requested
188         if (SOFTSHADOWRADIUS <= 1.0) {
189                 perspectiveFactor = getDeltaPerspectiveFactor(baseLength);
190                 return max(2 * length(smTexCoord.xy) * 2048 / f_textureresolution / pow(perspectiveFactor, 3), SOFTSHADOWRADIUS);
191         }
192
193         vec2 clampedpos;
194         float texture_size = 1.0 / (2048 /*f_textureresolution*/ * 0.5);
195         float y, x;
196         float depth = 0.0;
197         float pointDepth;
198         float maxRadius = SOFTSHADOWRADIUS * 5.0 * multiplier;
199
200         float bound = clamp(PCFBOUND * (1 - baseLength), 0.0, PCFBOUND);
201         int n = 0;
202
203         for (y = -bound; y <= bound; y += 1.0)
204         for (x = -bound; x <= bound; x += 1.0) {
205                 clampedpos = vec2(x,y);
206                 perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * maxRadius);
207                 clampedpos = clampedpos * texture_size * perspectiveFactor * maxRadius * perspectiveFactor + smTexCoord.xy;
208
209                 pointDepth = getHardShadowDepth(shadowsampler, clampedpos.xy, realDistance);
210                 if (pointDepth > -0.01) {
211                         depth += pointDepth;
212                         n += 1;
213                 }
214         }
215
216         depth = depth / n;
217         depth = pow(clamp(depth, 0.0, 1000.0), 1.6) / 0.001;
218
219         perspectiveFactor = getDeltaPerspectiveFactor(baseLength);
220         return max(length(smTexCoord.xy) * 2 * 2048 / f_textureresolution / pow(perspectiveFactor, 3), depth * maxRadius);
221 }
222
223 #ifdef POISSON_FILTER
224 const vec2[64] poissonDisk = vec2[64](
225         vec2(0.170019, -0.040254),
226         vec2(-0.299417, 0.791925),
227         vec2(0.645680, 0.493210),
228         vec2(-0.651784, 0.717887),
229         vec2(0.421003, 0.027070),
230         vec2(-0.817194, -0.271096),
231         vec2(-0.705374, -0.668203),
232         vec2(0.977050, -0.108615),
233         vec2(0.063326, 0.142369),
234         vec2(0.203528, 0.214331),
235         vec2(-0.667531, 0.326090),
236         vec2(-0.098422, -0.295755),
237         vec2(-0.885922, 0.215369),
238         vec2(0.566637, 0.605213),
239         vec2(0.039766, -0.396100),
240         vec2(0.751946, 0.453352),
241         vec2(0.078707, -0.715323),
242         vec2(-0.075838, -0.529344),
243         vec2(0.724479, -0.580798),
244         vec2(0.222999, -0.215125),
245         vec2(-0.467574, -0.405438),
246         vec2(-0.248268, -0.814753),
247         vec2(0.354411, -0.887570),
248         vec2(0.175817, 0.382366),
249         vec2(0.487472, -0.063082),
250         vec2(0.355476, 0.025357),
251         vec2(-0.084078, 0.898312),
252         vec2(0.488876, -0.783441),
253         vec2(0.470016, 0.217933),
254         vec2(-0.696890, -0.549791),
255         vec2(-0.149693, 0.605762),
256         vec2(0.034211, 0.979980),
257         vec2(0.503098, -0.308878),
258         vec2(-0.016205, -0.872921),
259         vec2(0.385784, -0.393902),
260         vec2(-0.146886, -0.859249),
261         vec2(0.643361, 0.164098),
262         vec2(0.634388, -0.049471),
263         vec2(-0.688894, 0.007843),
264         vec2(0.464034, -0.188818),
265         vec2(-0.440840, 0.137486),
266         vec2(0.364483, 0.511704),
267         vec2(0.034028, 0.325968),
268         vec2(0.099094, -0.308023),
269         vec2(0.693960, -0.366253),
270         vec2(0.678884, -0.204688),
271         vec2(0.001801, 0.780328),
272         vec2(0.145177, -0.898984),
273         vec2(0.062655, -0.611866),
274         vec2(0.315226, -0.604297),
275         vec2(-0.780145, 0.486251),
276         vec2(-0.371868, 0.882138),
277         vec2(0.200476, 0.494430),
278         vec2(-0.494552, -0.711051),
279         vec2(0.612476, 0.705252),
280         vec2(-0.578845, -0.768792),
281         vec2(-0.772454, -0.090976),
282         vec2(0.504440, 0.372295),
283         vec2(0.155736, 0.065157),
284         vec2(0.391522, 0.849605),
285         vec2(-0.620106, -0.328104),
286         vec2(0.789239, -0.419965),
287         vec2(-0.545396, 0.538133),
288         vec2(-0.178564, -0.596057)
289 );
290
291 #ifdef COLORED_SHADOWS
292
293 vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
294 {
295         vec2 clampedpos;
296         vec4 visibility = vec4(0.0);
297         float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.5); // scale to align with PCF
298         if (radius < 0.1) {
299                 // we are in the middle of even brightness, no need for filtering
300                 return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
301         }
302
303         float baseLength = getBaseLength(smTexCoord);
304         float perspectiveFactor;
305
306         float texture_size = 1.0 / (f_textureresolution * 0.5);
307         int samples = int(clamp(PCFSAMPLES * (1 - baseLength) * (1 - baseLength), PCFSAMPLES / 4, PCFSAMPLES));
308         int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
309         int end_offset = int(samples) + init_offset;
310
311         for (int x = init_offset; x < end_offset; x++) {
312                 clampedpos = poissonDisk[x];
313                 perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius);
314                 clampedpos = clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor + smTexCoord.xy;
315                 visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
316         }
317
318         return visibility / samples;
319 }
320
321 #else
322
323 float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
324 {
325         vec2 clampedpos;
326         float visibility = 0.0;
327         float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.5); // scale to align with PCF
328         if (radius < 0.1) {
329                 // we are in the middle of even brightness, no need for filtering
330                 return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
331         }
332
333         float baseLength = getBaseLength(smTexCoord);
334         float perspectiveFactor;
335
336         float texture_size = 1.0 / (f_textureresolution * 0.5);
337         int samples = int(clamp(PCFSAMPLES * (1 - baseLength) * (1 - baseLength), PCFSAMPLES / 4, PCFSAMPLES));
338         int init_offset = int(floor(mod(((smTexCoord.x * 34.0) + 1.0) * smTexCoord.y, 64.0-samples)));
339         int end_offset = int(samples) + init_offset;
340
341         for (int x = init_offset; x < end_offset; x++) {
342                 clampedpos = poissonDisk[x];
343                 perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius);
344                 clampedpos = clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor + smTexCoord.xy;
345                 visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
346         }
347
348         return visibility / samples;
349 }
350
351 #endif
352
353 #else
354 /* poisson filter disabled */
355
356 #ifdef COLORED_SHADOWS
357
358 vec4 getShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
359 {
360         vec2 clampedpos;
361         vec4 visibility = vec4(0.0);
362         float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.0);
363         if (radius < 0.1) {
364                 // we are in the middle of even brightness, no need for filtering
365                 return getHardShadowColor(shadowsampler, smTexCoord.xy, realDistance);
366         }
367
368         float baseLength = getBaseLength(smTexCoord);
369         float perspectiveFactor;
370
371         float texture_size = 1.0 / (f_textureresolution * 0.5);
372         float y, x;
373         float bound = clamp(PCFBOUND * (1 - baseLength), PCFBOUND / 2, PCFBOUND);
374         int n = 0;
375
376         // basic PCF filter
377         for (y = -bound; y <= bound; y += 1.0)
378         for (x = -bound; x <= bound; x += 1.0) {
379                 clampedpos = vec2(x,y);     // screen offset
380                 perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius / bound);
381                 clampedpos =  clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor / bound + smTexCoord.xy; // both dx,dy and radius are adjusted
382                 visibility += getHardShadowColor(shadowsampler, clampedpos.xy, realDistance);
383                 n += 1;
384         }
385
386         return visibility / n;
387 }
388
389 #else
390 float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
391 {
392         vec2 clampedpos;
393         float visibility = 0.0;
394         float radius = getPenumbraRadius(shadowsampler, smTexCoord, realDistance, 1.0);
395         if (radius < 0.1) {
396                 // we are in the middle of even brightness, no need for filtering
397                 return getHardShadow(shadowsampler, smTexCoord.xy, realDistance);
398         }
399
400         float baseLength = getBaseLength(smTexCoord);
401         float perspectiveFactor;
402
403         float texture_size = 1.0 / (f_textureresolution * 0.5);
404         float y, x;
405         float bound = clamp(PCFBOUND * (1 - baseLength), PCFBOUND / 2, PCFBOUND);
406         int n = 0;
407
408         // basic PCF filter
409         for (y = -bound; y <= bound; y += 1.0)
410         for (x = -bound; x <= bound; x += 1.0) {
411                 clampedpos = vec2(x,y);     // screen offset
412                 perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * radius / bound);
413                 clampedpos =  clampedpos * texture_size * perspectiveFactor * radius * perspectiveFactor / bound + smTexCoord.xy; // both dx,dy and radius are adjusted
414                 visibility += getHardShadow(shadowsampler, clampedpos.xy, realDistance);
415                 n += 1;
416         }
417
418         return visibility / n;
419 }
420
421 #endif
422
423 #endif
424 #endif
425
426 #if ENABLE_TONE_MAPPING
427
428 /* Hable's UC2 Tone mapping parameters
429         A = 0.22;
430         B = 0.30;
431         C = 0.10;
432         D = 0.20;
433         E = 0.01;
434         F = 0.30;
435         W = 11.2;
436         equation used:  ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F
437 */
438
439 vec3 uncharted2Tonemap(vec3 x)
440 {
441         return ((x * (0.22 * x + 0.03) + 0.002) / (x * (0.22 * x + 0.3) + 0.06)) - 0.03333;
442 }
443
444 vec4 applyToneMapping(vec4 color)
445 {
446         color = vec4(pow(color.rgb, vec3(2.2)), color.a);
447         const float gamma = 1.6;
448         const float exposureBias = 5.5;
449         color.rgb = uncharted2Tonemap(exposureBias * color.rgb);
450         // Precalculated white_scale from
451         //vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
452         vec3 whiteScale = vec3(1.036015346);
453         color.rgb *= whiteScale;
454         return vec4(pow(color.rgb, vec3(1.0 / gamma)), color.a);
455 }
456 #endif
457
458
459
460 void main(void)
461 {
462         vec3 color;
463         vec2 uv = varTexCoord.st;
464
465         vec4 base = texture2D(baseTexture, uv).rgba;
466         // If alpha is zero, we can just discard the pixel. This fixes transparency
467         // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa,
468         // and also on GLES 2, where GL_ALPHA_TEST is missing entirely.
469 #ifdef USE_DISCARD
470         if (base.a == 0.0)
471                 discard;
472 #endif
473 #ifdef USE_DISCARD_REF
474         if (base.a < 0.5)
475                 discard;
476 #endif
477
478         color = base.rgb;
479         vec4 col = vec4(color.rgb * varColor.rgb, 1.0);
480
481 #ifdef ENABLE_DYNAMIC_SHADOWS
482         float shadow_int = 0.0;
483         vec3 shadow_color = vec3(0.0, 0.0, 0.0);
484         vec3 posLightSpace = getLightSpacePosition();
485
486         float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 20.0));
487         float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1,  posLightSpace.z  ),0.0);
488
489         if (distance_rate > 1e-7) {
490         
491 #ifdef COLORED_SHADOWS
492                 vec4 visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
493                 shadow_int = visibility.r;
494                 shadow_color = visibility.gba;
495 #else
496                 shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
497 #endif
498                 shadow_int *= distance_rate;
499                 shadow_int *= 1.0 - nightRatio;
500
501
502         }
503
504         if (f_normal_length != 0 && cosLight < 0.035) {
505                 shadow_int = max(shadow_int, min(clamp(1.0-nightRatio, 0.0, 1.0), 1 - clamp(cosLight, 0.0, 0.035)/0.035));
506         }
507
508         shadow_int = 1.0 - (shadow_int * f_adj_shadow_strength);
509         
510         col.rgb = mix(shadow_color,col.rgb,shadow_int)*shadow_int;
511         // col.r = 0.5 * clamp(getPenumbraRadius(ShadowMapSampler, posLightSpace.xy, posLightSpace.z, 1.0) / SOFTSHADOWRADIUS, 0.0, 1.0) + 0.5 * col.r;
512 #endif
513
514 #if ENABLE_TONE_MAPPING
515         col = applyToneMapping(col);
516 #endif
517
518         // Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?),
519         // the fog will only be rendered correctly if the last operation before the
520         // clamp() is an addition. Else, the clamp() seems to be ignored.
521         // E.g. the following won't work:
522         //      float clarity = clamp(fogShadingParameter
523         //              * (fogDistance - length(eyeVec)) / fogDistance), 0.0, 1.0);
524         // As additions usually come for free following a multiplication, the new formula
525         // should be more efficient as well.
526         // Note: clarity = (1 - fogginess)
527         float clarity = clamp(fogShadingParameter
528                 - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
529         col = mix(skyBgColor, col, clarity);
530         col = vec4(col.rgb, base.a);
531         
532         gl_FragColor = col;
533 }