]> git.lizzy.rs Git - minetest.git/commitdiff
Apply shadow only to the naturally lit part of the fragment color (#11722)
authorx2048 <codeforsmile@gmail.com>
Sun, 31 Oct 2021 18:18:30 +0000 (19:18 +0100)
committerGitHub <noreply@github.com>
Sun, 31 Oct 2021 18:18:30 +0000 (19:18 +0100)
Fragment color for nodes is now calculated from:

 * Texture color, highlighted by artificial light if present (light color conveyed via vertex color).
 * Texture color highlighted by natural light (conveyed via vertex color) filtered by shadow.
 * Reflected day/moonlight filtered by shadow (color and intensity), assuming some portion of the light is directly reflected from the materials.

client/shaders/nodes_shader/opengl_fragment.glsl
client/shaders/shadow_shaders/pass1_trans_fragment.glsl

index e21890710bf738357b5d923b7a53a9c381ffac20..b4a605b28e2cf11910263295af182cbbcac4052b 100644 (file)
@@ -1,5 +1,6 @@
 uniform sampler2D baseTexture;
 
+uniform vec3 dayLight;
 uniform vec4 skyBgColor;
 uniform float fogDistance;
 uniform vec3 eyePosition;
@@ -497,23 +498,35 @@ void main(void)
                shadow_int = visibility.r;
                shadow_color = visibility.gba;
 #else
-               shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
+               if (cosLight > 0.0)
+                       shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
+               else
+                       shadow_int = 1.0;
 #endif
                shadow_int *= distance_rate;
-               shadow_int *= 1.0 - nightRatio;
-
+               shadow_int = clamp(shadow_int, 0.0, 1.0);
 
        }
 
+       // turns out that nightRatio falls off much faster than
+       // actual brightness of artificial light in relation to natual light.
+       // Power ratio was measured on torches in MTG (brightness = 14).
+       float adjusted_night_ratio = pow(nightRatio, 0.6);
+
        if (f_normal_length != 0 && cosLight < 0.035) {
-               shadow_int = max(shadow_int, min(clamp(1.0-nightRatio, 0.0, 1.0), 1 - clamp(cosLight, 0.0, 0.035)/0.035));
+               shadow_int = max(shadow_int, 1 - clamp(cosLight, 0.0, 0.035)/0.035);
        }
 
-       shadow_int = 1.0 - (shadow_int * f_adj_shadow_strength);
+       shadow_int *= f_adj_shadow_strength;
        
-       // apply shadow (+color) as a factor to the material color
-       col.rgb = col.rgb * (1.0 - (1.0 - shadow_color) * (1.0 - pow(shadow_int, 2.0)));
+       // calculate fragment color from components:
+       col.rgb =
+                       adjusted_night_ratio * col.rgb + // artificial light
+                       (1.0 - adjusted_night_ratio) * ( // natural light
+                                       col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) +  // filtered texture color
+                                       dayLight * shadow_color * shadow_int);                 // reflected filtered sunlight/moonlight
        // col.r = 0.5 * clamp(getPenumbraRadius(ShadowMapSampler, posLightSpace.xy, posLightSpace.z, 1.0) / SOFTSHADOWRADIUS, 0.0, 1.0) + 0.5 * col.r;
+       // col.r = adjusted_night_ratio; // debug night ratio adjustment
 #endif
 
 #if ENABLE_TONE_MAPPING
index 032cd93798c436e8e81afb9a092c7ab9803bce93..b267c221480b434fcddabf2eb35ed61bc332e5a2 100644 (file)
@@ -33,9 +33,8 @@ void main()
        //col.rgb = col.a == 1.0 ? vec3(1.0) : col.rgb;
 #ifdef COLORED_SHADOWS
        col.rgb *= varColor.rgb;
-       // alpha 0.0 results in all-white, 0.5 means full color, 1.0 means all black
-       // resulting color is used as a factor in the final shader
-       float packedColor = packColor(mix(mix(vec3(1.0), col.rgb, 2.0 * clamp(col.a, 0.0, 0.5)), black, 2.0 * clamp(col.a - 0.5, 0.0, 0.5)));
+       // premultiply color alpha (see-through side)
+       float packedColor = packColor(col.rgb * (1.0 - col.a));
        gl_FragColor = vec4(depth, packedColor, 0.0,1.0);
 #else
        gl_FragColor = vec4(depth, 0.0, 0.0, 1.0);