Apply shadow only to the naturally lit part of the fragment color (#11722)

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.
This commit is contained in:
x2048 2021-10-31 19:18:30 +01:00 committed by GitHub
parent 532d5b21fd
commit cef016d393
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 10 deletions

@ -1,5 +1,6 @@
uniform sampler2D baseTexture; uniform sampler2D baseTexture;
uniform vec3 dayLight;
uniform vec4 skyBgColor; uniform vec4 skyBgColor;
uniform float fogDistance; uniform float fogDistance;
uniform vec3 eyePosition; uniform vec3 eyePosition;
@ -497,23 +498,35 @@ void main(void)
shadow_int = visibility.r; shadow_int = visibility.r;
shadow_color = visibility.gba; shadow_color = visibility.gba;
#else #else
if (cosLight > 0.0)
shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z);
else
shadow_int = 1.0;
#endif #endif
shadow_int *= distance_rate; 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) { 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 // calculate fragment color from components:
col.rgb = col.rgb * (1.0 - (1.0 - shadow_color) * (1.0 - pow(shadow_int, 2.0))); 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 = 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 #endif
#if ENABLE_TONE_MAPPING #if ENABLE_TONE_MAPPING

@ -33,9 +33,8 @@ void main()
//col.rgb = col.a == 1.0 ? vec3(1.0) : col.rgb; //col.rgb = col.a == 1.0 ? vec3(1.0) : col.rgb;
#ifdef COLORED_SHADOWS #ifdef COLORED_SHADOWS
col.rgb *= varColor.rgb; col.rgb *= varColor.rgb;
// alpha 0.0 results in all-white, 0.5 means full color, 1.0 means all black // premultiply color alpha (see-through side)
// resulting color is used as a factor in the final shader float packedColor = packColor(col.rgb * (1.0 - col.a));
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)));
gl_FragColor = vec4(depth, packedColor, 0.0,1.0); gl_FragColor = vec4(depth, packedColor, 0.0,1.0);
#else #else
gl_FragColor = vec4(depth, 0.0, 0.0, 1.0); gl_FragColor = vec4(depth, 0.0, 0.0, 1.0);