From 4801bdf45aaaa9238bc52a157e1d25c9d477d81a Mon Sep 17 00:00:00 2001 From: Dmitry Kostenko Date: Sun, 20 Feb 2022 00:04:48 +0100 Subject: Correct normal bias for entities Remove use of magic constants. Apply cameraOffset Calculate distance projected on SM plane --- src/client/shadows/dynamicshadowsrender.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/client/shadows/dynamicshadowsrender.cpp') diff --git a/src/client/shadows/dynamicshadowsrender.cpp b/src/client/shadows/dynamicshadowsrender.cpp index a913a9290..528415aaf 100644 --- a/src/client/shadows/dynamicshadowsrender.cpp +++ b/src/client/shadows/dynamicshadowsrender.cpp @@ -118,12 +118,8 @@ size_t ShadowRenderer::getDirectionalLightCount() const f32 ShadowRenderer::getMaxShadowFar() const { if (!m_light_list.empty()) { - float wanted_range = m_client->getEnv().getClientMap().getWantedRange(); - - float zMax = m_light_list[0].getMaxFarValue() > wanted_range - ? wanted_range - : m_light_list[0].getMaxFarValue(); - return zMax * MAP_BLOCKSIZE; + float zMax = m_light_list[0].getMaxFarValue(); + return zMax; } return 0.0f; } -- cgit v1.2.3 From 0f25fa7af655b98fa401176a523f269c843d1943 Mon Sep 17 00:00:00 2001 From: x2048 Date: Sat, 26 Mar 2022 16:58:26 +0100 Subject: Add API to control shadow intensity from the game/mod (#11944) * Also Disable shadows when sun/moon is hidden. Fixes #11972. --- builtin/settingtypes.txt | 5 +- client/shaders/nodes_shader/opengl_fragment.glsl | 85 ++++++++++---------- client/shaders/nodes_shader/opengl_vertex.glsl | 57 +++++++------- client/shaders/object_shader/opengl_fragment.glsl | 84 ++++++++++---------- client/shaders/object_shader/opengl_vertex.glsl | 56 ++++++------- doc/lua_api.txt | 7 ++ games/devtest/mods/experimental/init.lua | 1 + games/devtest/mods/experimental/lighting.lua | 8 ++ src/client/client.h | 1 + src/client/game.cpp | 7 +- src/client/localplayer.h | 4 + src/client/shadows/dynamicshadowsrender.cpp | 95 ++++++++++++++++------- src/client/shadows/dynamicshadowsrender.h | 10 ++- src/client/sky.h | 2 + src/defaultsettings.cpp | 2 +- src/lighting.h | 27 +++++++ src/network/clientopcodes.cpp | 1 + src/network/clientpackethandler.cpp | 8 ++ src/network/networkprotocol.h | 7 +- src/remoteplayer.h | 7 ++ src/script/lua_api/l_object.cpp | 43 ++++++++++ src/script/lua_api/l_object.h | 6 ++ src/server.cpp | 17 ++++ src/server.h | 4 + 24 files changed, 375 insertions(+), 169 deletions(-) create mode 100644 games/devtest/mods/experimental/lighting.lua create mode 100644 src/lighting.h (limited to 'src/client/shadows/dynamicshadowsrender.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index ff2d72927..3dc165bd1 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -592,9 +592,10 @@ enable_waving_plants (Waving plants) bool false # Requires shaders to be enabled. enable_dynamic_shadows (Dynamic shadows) bool false -# Set the shadow strength. +# Set the shadow strength gamma. +# Adjusts the intensity of in-game dynamic shadows. # Lower value means lighter shadows, higher value means darker shadows. -shadow_strength (Shadow strength) float 0.2 0.05 1.0 +shadow_strength_gamma (Shadow strength gamma) float 1.0 0.1 10.0 # Maximum distance to render shadows. shadow_map_max_distance (Shadow map max distance in nodes to render shadows) float 120.0 10.0 1000.0 diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index e5f5c703a..adc8adccb 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -16,6 +16,7 @@ uniform float animationTimer; uniform float f_textureresolution; uniform mat4 m_ShadowViewProj; uniform float f_shadowfar; + uniform float f_shadow_strength; varying float normalOffsetScale; varying float adj_shadow_strength; varying float cosLight; @@ -483,55 +484,57 @@ void main(void) vec4 col = vec4(color.rgb * varColor.rgb, 1.0); #ifdef ENABLE_DYNAMIC_SHADOWS - float shadow_int = 0.0; - vec3 shadow_color = vec3(0.0, 0.0, 0.0); - vec3 posLightSpace = getLightSpacePosition(); + if (f_shadow_strength > 0.0) { + float shadow_int = 0.0; + vec3 shadow_color = vec3(0.0, 0.0, 0.0); + vec3 posLightSpace = getLightSpacePosition(); - float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 20.0)); - float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z ),0.0); + float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 20.0)); + float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z ),0.0); - if (distance_rate > 1e-7) { - + if (distance_rate > 1e-7) { + #ifdef COLORED_SHADOWS - vec4 visibility; - if (cosLight > 0.0) - visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); - else - visibility = vec4(1.0, 0.0, 0.0, 0.0); - shadow_int = visibility.r; - shadow_color = visibility.gba; + vec4 visibility; + if (cosLight > 0.0) + visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); + else + visibility = vec4(1.0, 0.0, 0.0, 0.0); + shadow_int = visibility.r; + shadow_color = visibility.gba; #else - if (cosLight > 0.0) - shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); - else - shadow_int = 1.0; + if (cosLight > 0.0) + shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); + else + shadow_int = 1.0; #endif - shadow_int *= distance_rate; - shadow_int = clamp(shadow_int, 0.0, 1.0); + shadow_int *= distance_rate; + 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(max(0.0, nightRatio), 0.6); - - // Apply self-shadowing when light falls at a narrow angle to the surface - // Cosine of the cut-off angle. - const float self_shadow_cutoff_cosine = 0.035; - if (f_normal_length != 0 && cosLight < self_shadow_cutoff_cosine) { - shadow_int = max(shadow_int, 1 - clamp(cosLight, 0.0, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); - shadow_color = mix(vec3(0.0), shadow_color, min(cosLight, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); - } + // 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(max(0.0, nightRatio), 0.6); + + // Apply self-shadowing when light falls at a narrow angle to the surface + // Cosine of the cut-off angle. + const float self_shadow_cutoff_cosine = 0.035; + if (f_normal_length != 0 && cosLight < self_shadow_cutoff_cosine) { + shadow_int = max(shadow_int, 1 - clamp(cosLight, 0.0, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); + shadow_color = mix(vec3(0.0), shadow_color, min(cosLight, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); + } - shadow_int *= f_adj_shadow_strength; - - // 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 + shadow_int *= f_adj_shadow_strength; + + // 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 + } #endif #if ENABLE_TONE_MAPPING diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 95cd138a8..5e77ac719 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -195,34 +195,35 @@ void main(void) varColor = clamp(color, 0.0, 1.0); #ifdef ENABLE_DYNAMIC_SHADOWS - vec3 nNormal = normalize(vNormal); - cosLight = dot(nNormal, -v_LightDirection); - - // Calculate normal offset scale based on the texel size adjusted for - // curvature of the SM texture. This code must be change together with - // getPerspectiveFactor or any light-space transformation. - vec3 eyeToVertex = worldPosition - eyePosition + cameraOffset; - // Distance from the vertex to the player - float distanceToPlayer = length(eyeToVertex - v_LightDirection * dot(eyeToVertex, v_LightDirection)) / f_shadowfar; - // perspective factor estimation according to the - float perspectiveFactor = distanceToPlayer * bias0 + bias1; - float texelSize = f_shadowfar * perspectiveFactor * perspectiveFactor / - (f_textureresolution * bias1 - perspectiveFactor * bias0); - float slopeScale = clamp(pow(1.0 - cosLight*cosLight, 0.5), 0.0, 1.0); - normalOffsetScale = texelSize * slopeScale; - - if (f_timeofday < 0.2) { - adj_shadow_strength = f_shadow_strength * 0.5 * - (1.0 - mtsmoothstep(0.18, 0.2, f_timeofday)); - } else if (f_timeofday >= 0.8) { - adj_shadow_strength = f_shadow_strength * 0.5 * - mtsmoothstep(0.8, 0.83, f_timeofday); - } else { - adj_shadow_strength = f_shadow_strength * - mtsmoothstep(0.20, 0.25, f_timeofday) * - (1.0 - mtsmoothstep(0.7, 0.8, f_timeofday)); + if (f_shadow_strength > 0.0) { + vec3 nNormal = normalize(vNormal); + cosLight = dot(nNormal, -v_LightDirection); + + // Calculate normal offset scale based on the texel size adjusted for + // curvature of the SM texture. This code must be change together with + // getPerspectiveFactor or any light-space transformation. + vec3 eyeToVertex = worldPosition - eyePosition + cameraOffset; + // Distance from the vertex to the player + float distanceToPlayer = length(eyeToVertex - v_LightDirection * dot(eyeToVertex, v_LightDirection)) / f_shadowfar; + // perspective factor estimation according to the + float perspectiveFactor = distanceToPlayer * bias0 + bias1; + float texelSize = f_shadowfar * perspectiveFactor * perspectiveFactor / + (f_textureresolution * bias1 - perspectiveFactor * bias0); + float slopeScale = clamp(pow(1.0 - cosLight*cosLight, 0.5), 0.0, 1.0); + normalOffsetScale = texelSize * slopeScale; + + if (f_timeofday < 0.2) { + adj_shadow_strength = f_shadow_strength * 0.5 * + (1.0 - mtsmoothstep(0.18, 0.2, f_timeofday)); + } else if (f_timeofday >= 0.8) { + adj_shadow_strength = f_shadow_strength * 0.5 * + mtsmoothstep(0.8, 0.83, f_timeofday); + } else { + adj_shadow_strength = f_shadow_strength * + mtsmoothstep(0.20, 0.25, f_timeofday) * + (1.0 - mtsmoothstep(0.7, 0.8, f_timeofday)); + } + f_normal_length = length(vNormal); } - f_normal_length = length(vNormal); #endif - } diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index fdfcec0c8..edb9d2bb1 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -34,6 +34,8 @@ const float fogShadingParameter = 1.0 / (1.0 - fogStart); uniform float f_textureresolution; uniform mat4 m_ShadowViewProj; uniform float f_shadowfar; + uniform float f_timeofday; + uniform float f_shadow_strength; varying float normalOffsetScale; varying float adj_shadow_strength; varying float cosLight; @@ -470,55 +472,57 @@ void main(void) col.rgb *= vIDiff; #ifdef ENABLE_DYNAMIC_SHADOWS - float shadow_int = 0.0; - vec3 shadow_color = vec3(0.0, 0.0, 0.0); - vec3 posLightSpace = getLightSpacePosition(); + if (f_shadow_strength > 0.0) { + float shadow_int = 0.0; + vec3 shadow_color = vec3(0.0, 0.0, 0.0); + vec3 posLightSpace = getLightSpacePosition(); - float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 20.0)); - float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z ),0.0); + float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 20.0)); + float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z ),0.0); - if (distance_rate > 1e-7) { + if (distance_rate > 1e-7) { #ifdef COLORED_SHADOWS - vec4 visibility; - if (cosLight > 0.0) - visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); - else - visibility = vec4(1.0, 0.0, 0.0, 0.0); - shadow_int = visibility.r; - shadow_color = visibility.gba; + vec4 visibility; + if (cosLight > 0.0) + visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); + else + visibility = vec4(1.0, 0.0, 0.0, 0.0); + shadow_int = visibility.r; + shadow_color = visibility.gba; #else - if (cosLight > 0.0) - shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); - else - shadow_int = 1.0; + if (cosLight > 0.0) + shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); + else + shadow_int = 1.0; #endif - shadow_int *= distance_rate; - shadow_int = clamp(shadow_int, 0.0, 1.0); + shadow_int *= distance_rate; + 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(max(0.0, nightRatio), 0.6); - - // cosine of the normal-to-light angle when - // we start to apply self-shadowing - const float self_shadow_cutoff_cosine = 0.14; - if (f_normal_length != 0 && cosLight < self_shadow_cutoff_cosine) { - shadow_int = max(shadow_int, 1 - clamp(cosLight, 0.0, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); - shadow_color = mix(vec3(0.0), shadow_color, min(cosLight, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); - } + // 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(max(0.0, nightRatio), 0.6); + + // cosine of the normal-to-light angle when + // we start to apply self-shadowing + const float self_shadow_cutoff_cosine = 0.14; + if (f_normal_length != 0 && cosLight < self_shadow_cutoff_cosine) { + shadow_int = max(shadow_int, 1 - clamp(cosLight, 0.0, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); + shadow_color = mix(vec3(0.0), shadow_color, min(cosLight, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); + } - shadow_int *= f_adj_shadow_strength; - - // 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 + shadow_int *= f_adj_shadow_strength; + + // 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 + } #endif #if ENABLE_TONE_MAPPING diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index 185551c58..ff0067302 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -105,33 +105,35 @@ void main(void) #ifdef ENABLE_DYNAMIC_SHADOWS - vec3 nNormal = normalize(vNormal); - cosLight = dot(nNormal, -v_LightDirection); - - // Calculate normal offset scale based on the texel size adjusted for - // curvature of the SM texture. This code must be change together with - // getPerspectiveFactor or any light-space transformation. - vec3 eyeToVertex = worldPosition - eyePosition + cameraOffset; - // Distance from the vertex to the player - float distanceToPlayer = length(eyeToVertex - v_LightDirection * dot(eyeToVertex, v_LightDirection)) / f_shadowfar; - // perspective factor estimation according to the - float perspectiveFactor = distanceToPlayer * bias0 + bias1; - float texelSize = f_shadowfar * perspectiveFactor * perspectiveFactor / - (f_textureresolution * bias1 - perspectiveFactor * bias0); - float slopeScale = clamp(pow(1.0 - cosLight*cosLight, 0.5), 0.0, 1.0); - normalOffsetScale = texelSize * slopeScale; - - if (f_timeofday < 0.2) { - adj_shadow_strength = f_shadow_strength * 0.5 * - (1.0 - mtsmoothstep(0.18, 0.2, f_timeofday)); - } else if (f_timeofday >= 0.8) { - adj_shadow_strength = f_shadow_strength * 0.5 * - mtsmoothstep(0.8, 0.83, f_timeofday); - } else { - adj_shadow_strength = f_shadow_strength * - mtsmoothstep(0.20, 0.25, f_timeofday) * - (1.0 - mtsmoothstep(0.7, 0.8, f_timeofday)); + if (f_shadow_strength > 0.0) { + vec3 nNormal = normalize(vNormal); + cosLight = dot(nNormal, -v_LightDirection); + + // Calculate normal offset scale based on the texel size adjusted for + // curvature of the SM texture. This code must be change together with + // getPerspectiveFactor or any light-space transformation. + vec3 eyeToVertex = worldPosition - eyePosition + cameraOffset; + // Distance from the vertex to the player + float distanceToPlayer = length(eyeToVertex - v_LightDirection * dot(eyeToVertex, v_LightDirection)) / f_shadowfar; + // perspective factor estimation according to the + float perspectiveFactor = distanceToPlayer * bias0 + bias1; + float texelSize = f_shadowfar * perspectiveFactor * perspectiveFactor / + (f_textureresolution * bias1 - perspectiveFactor * bias0); + float slopeScale = clamp(pow(1.0 - cosLight*cosLight, 0.5), 0.0, 1.0); + normalOffsetScale = texelSize * slopeScale; + + if (f_timeofday < 0.2) { + adj_shadow_strength = f_shadow_strength * 0.5 * + (1.0 - mtsmoothstep(0.18, 0.2, f_timeofday)); + } else if (f_timeofday >= 0.8) { + adj_shadow_strength = f_shadow_strength * 0.5 * + mtsmoothstep(0.8, 0.83, f_timeofday); + } else { + adj_shadow_strength = f_shadow_strength * + mtsmoothstep(0.20, 0.25, f_timeofday) * + (1.0 - mtsmoothstep(0.7, 0.8, f_timeofday)); + } + f_normal_length = length(vNormal); } - f_normal_length = length(vNormal); #endif } diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 52da17e9c..029c53616 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -7019,6 +7019,13 @@ object you are working with still exists. * Returns `false` if failed. * Resource intensive - use sparsely * To get blockpos, integer divide pos by 16 +* `set_lighting(light_definition)`: sets lighting for the player + * `light_definition` is a table with the following optional fields: + * `shadows` is a table that controls ambient shadows + * `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness) + * Returns true on success. +* `get_lighting()`: returns the current state of lighting for the player. + * Result is a table with the same fields as `light_definition` in `set_lighting`. `PcgRandom` ----------- diff --git a/games/devtest/mods/experimental/init.lua b/games/devtest/mods/experimental/init.lua index b292f792e..70091179c 100644 --- a/games/devtest/mods/experimental/init.lua +++ b/games/devtest/mods/experimental/init.lua @@ -7,6 +7,7 @@ experimental = {} dofile(minetest.get_modpath("experimental").."/detached.lua") dofile(minetest.get_modpath("experimental").."/items.lua") dofile(minetest.get_modpath("experimental").."/commands.lua") +dofile(minetest.get_modpath("experimental").."/lighting.lua") function experimental.print_to_everything(msg) minetest.log("action", msg) diff --git a/games/devtest/mods/experimental/lighting.lua b/games/devtest/mods/experimental/lighting.lua new file mode 100644 index 000000000..2b350550f --- /dev/null +++ b/games/devtest/mods/experimental/lighting.lua @@ -0,0 +1,8 @@ +core.register_chatcommand("set_lighting", { + params = "shadow_intensity", + description = "Set lighting parameters.", + func = function(player_name, param) + local shadow_intensity = tonumber(param) + minetest.get_player_by_name(player_name):set_lighting({shadows = { intensity = shadow_intensity} }) + end +}) \ No newline at end of file diff --git a/src/client/client.h b/src/client/client.h index 84c85471d..0e29fdbe2 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -227,6 +227,7 @@ public: void handleCommand_PlayerSpeed(NetworkPacket *pkt); void handleCommand_MediaPush(NetworkPacket *pkt); void handleCommand_MinimapModes(NetworkPacket *pkt); + void handleCommand_SetLighting(NetworkPacket *pkt); void ProcessData(NetworkPacket *pkt); diff --git a/src/client/game.cpp b/src/client/game.cpp index 7450fb91c..edc69dcc2 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -4037,7 +4037,12 @@ void Game::updateShadows() float in_timeofday = fmod(runData.time_of_day_smooth, 1.0f); - float timeoftheday = fmod(getWickedTimeOfDay(in_timeofday) + 0.75f, 0.5f) + 0.25f; + float timeoftheday = getWickedTimeOfDay(in_timeofday); + bool is_day = timeoftheday > 0.25 && timeoftheday < 0.75; + bool is_shadow_visible = is_day ? sky->getSunVisible() : sky->getMoonVisible(); + shadow->setShadowIntensity(is_shadow_visible ? client->getEnv().getLocalPlayer()->getLighting().shadow_intensity : 0.0f); + + timeoftheday = fmod(timeoftheday + 0.75f, 0.5f) + 0.25f; const float offset_constant = 10000.0f; v3f light(0.0f, 0.0f, -1.0f); diff --git a/src/client/localplayer.h b/src/client/localplayer.h index 577be2803..3d0072fc1 100644 --- a/src/client/localplayer.h +++ b/src/client/localplayer.h @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "environment.h" #include "constants.h" #include "settings.h" +#include "lighting.h" #include class Client; @@ -158,6 +159,8 @@ public: added_velocity += vel; } + inline Lighting& getLighting() { return m_lighting; } + private: void accelerate(const v3f &target_speed, const f32 max_increase_H, const f32 max_increase_V, const bool use_pitch); @@ -209,4 +212,5 @@ private: GenericCAO *m_cao = nullptr; Client *m_client; + Lighting m_lighting; }; diff --git a/src/client/shadows/dynamicshadowsrender.cpp b/src/client/shadows/dynamicshadowsrender.cpp index 528415aaf..24adb21e2 100644 --- a/src/client/shadows/dynamicshadowsrender.cpp +++ b/src/client/shadows/dynamicshadowsrender.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include +#include #include "client/shadows/dynamicshadowsrender.h" #include "client/shadows/shadowsScreenQuad.h" #include "client/shadows/shadowsshadercallbacks.h" @@ -33,9 +34,13 @@ ShadowRenderer::ShadowRenderer(IrrlichtDevice *device, Client *client) : m_device(device), m_smgr(device->getSceneManager()), m_driver(device->getVideoDriver()), m_client(client), m_current_frame(0) { + m_shadows_supported = true; // assume shadows supported. We will check actual support in initialize m_shadows_enabled = true; - m_shadow_strength = g_settings->getFloat("shadow_strength"); + m_shadow_strength_gamma = g_settings->getFloat("shadow_strength_gamma"); + if (std::isnan(m_shadow_strength_gamma)) + m_shadow_strength_gamma = 1.0f; + m_shadow_strength_gamma = core::clamp(m_shadow_strength_gamma, 0.1f, 10.0f); m_shadow_map_max_distance = g_settings->getFloat("shadow_map_max_distance"); @@ -49,6 +54,9 @@ ShadowRenderer::ShadowRenderer(IrrlichtDevice *device, Client *client) : ShadowRenderer::~ShadowRenderer() { + // call to disable releases dynamically allocated resources + disable(); + if (m_shadow_depth_cb) delete m_shadow_depth_cb; if (m_shadow_mix_cb) @@ -72,15 +80,25 @@ ShadowRenderer::~ShadowRenderer() m_driver->removeTexture(shadowMapClientMapFuture); } +void ShadowRenderer::disable() +{ + m_shadows_enabled = false; + if (shadowMapTextureFinal) { + m_driver->setRenderTarget(shadowMapTextureFinal, true, true, + video::SColor(255, 255, 255, 255)); + m_driver->setRenderTarget(0, true, true); + } +} + void ShadowRenderer::initialize() { auto *gpu = m_driver->getGPUProgrammingServices(); // we need glsl - if (m_shadows_enabled && gpu && m_driver->queryFeature(video::EVDF_ARB_GLSL)) { + if (m_shadows_supported && gpu && m_driver->queryFeature(video::EVDF_ARB_GLSL)) { createShaders(); } else { - m_shadows_enabled = false; + m_shadows_supported = false; warningstream << "Shadows: GLSL Shader not supported on this system." << std::endl; @@ -94,6 +112,8 @@ void ShadowRenderer::initialize() m_texture_format_color = m_shadow_map_texture_32bit ? video::ECOLOR_FORMAT::ECF_G32R32F : video::ECOLOR_FORMAT::ECF_G16R16F; + + m_shadows_enabled &= m_shadows_supported; } @@ -124,6 +144,16 @@ f32 ShadowRenderer::getMaxShadowFar() const return 0.0f; } +void ShadowRenderer::setShadowIntensity(float shadow_intensity) +{ + m_shadow_strength = pow(shadow_intensity, 1.0f / m_shadow_strength_gamma); + if (m_shadow_strength > 1E-2) + enable(); + else + disable(); +} + + void ShadowRenderer::addNodeToShadowList( scene::ISceneNode *node, E_SHADOW_MODE shadowMode) { @@ -153,6 +183,7 @@ void ShadowRenderer::updateSMTextures() shadowMapTextureDynamicObjects = getSMTexture( std::string("shadow_dynamic_") + itos(m_shadow_map_texture_size), m_texture_format, true); + assert(shadowMapTextureDynamicObjects != nullptr); } if (!shadowMapClientMap) { @@ -161,6 +192,7 @@ void ShadowRenderer::updateSMTextures() std::string("shadow_clientmap_") + itos(m_shadow_map_texture_size), m_shadow_map_colored ? m_texture_format_color : m_texture_format, true); + assert(shadowMapClientMap != nullptr); } if (!shadowMapClientMapFuture && m_map_shadow_update_frames > 1) { @@ -168,6 +200,7 @@ void ShadowRenderer::updateSMTextures() std::string("shadow_clientmap_bb_") + itos(m_shadow_map_texture_size), m_shadow_map_colored ? m_texture_format_color : m_texture_format, true); + assert(shadowMapClientMapFuture != nullptr); } if (m_shadow_map_colored && !shadowMapTextureColors) { @@ -175,6 +208,7 @@ void ShadowRenderer::updateSMTextures() std::string("shadow_colored_") + itos(m_shadow_map_texture_size), m_shadow_map_colored ? m_texture_format_color : m_texture_format, true); + assert(shadowMapTextureColors != nullptr); } // The merge all shadowmaps texture @@ -194,6 +228,7 @@ void ShadowRenderer::updateSMTextures() shadowMapTextureFinal = getSMTexture( std::string("shadowmap_final_") + itos(m_shadow_map_texture_size), frt, true); + assert(shadowMapTextureFinal != nullptr); } if (!m_shadow_node_array.empty() && !m_light_list.empty()) { @@ -270,6 +305,10 @@ void ShadowRenderer::update(video::ITexture *outputTarget) updateSMTextures(); + if (shadowMapTextureFinal == nullptr) { + return; + } + if (!m_shadow_node_array.empty() && !m_light_list.empty()) { for (DirectionalLight &light : m_light_list) { @@ -307,19 +346,23 @@ void ShadowRenderer::drawDebug() /* this code just shows shadows textures in screen and in ONLY for debugging*/ #if 0 // this is debug, ignore for now. - m_driver->draw2DImage(shadowMapTextureFinal, - core::rect(0, 50, 128, 128 + 50), - core::rect({0, 0}, shadowMapTextureFinal->getSize())); + if (shadowMapTextureFinal) + m_driver->draw2DImage(shadowMapTextureFinal, + core::rect(0, 50, 128, 128 + 50), + core::rect({0, 0}, shadowMapTextureFinal->getSize())); - m_driver->draw2DImage(shadowMapClientMap, - core::rect(0, 50 + 128, 128, 128 + 50 + 128), - core::rect({0, 0}, shadowMapTextureFinal->getSize())); - m_driver->draw2DImage(shadowMapTextureDynamicObjects, - core::rect(0, 128 + 50 + 128, 128, - 128 + 50 + 128 + 128), - core::rect({0, 0}, shadowMapTextureDynamicObjects->getSize())); + if (shadowMapClientMap) + m_driver->draw2DImage(shadowMapClientMap, + core::rect(0, 50 + 128, 128, 128 + 50 + 128), + core::rect({0, 0}, shadowMapTextureFinal->getSize())); + + if (shadowMapTextureDynamicObjects) + m_driver->draw2DImage(shadowMapTextureDynamicObjects, + core::rect(0, 128 + 50 + 128, 128, + 128 + 50 + 128 + 128), + core::rect({0, 0}, shadowMapTextureDynamicObjects->getSize())); - if (m_shadow_map_colored) { + if (m_shadow_map_colored && shadowMapTextureColors) { m_driver->draw2DImage(shadowMapTextureColors, core::rect(128,128 + 50 + 128 + 128, @@ -469,13 +512,13 @@ void ShadowRenderer::createShaders() if (depth_shader == -1) { std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass1_vertex.glsl"); if (depth_shader_vs.empty()) { - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error shadow mapping vs shader not found." << std::endl; return; } std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass1_fragment.glsl"); if (depth_shader_fs.empty()) { - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error shadow mapping fs shader not found." << std::endl; return; } @@ -490,7 +533,7 @@ void ShadowRenderer::createShaders() if (depth_shader == -1) { // upsi, something went wrong loading shader. delete m_shadow_depth_cb; - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error compiling shadow mapping shader." << std::endl; return; } @@ -506,13 +549,13 @@ void ShadowRenderer::createShaders() if (depth_shader_entities == -1) { std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass1_vertex.glsl"); if (depth_shader_vs.empty()) { - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error shadow mapping vs shader not found." << std::endl; return; } std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass1_fragment.glsl"); if (depth_shader_fs.empty()) { - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error shadow mapping fs shader not found." << std::endl; return; } @@ -525,7 +568,7 @@ void ShadowRenderer::createShaders() if (depth_shader_entities == -1) { // upsi, something went wrong loading shader. - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error compiling shadow mapping shader (dynamic)." << std::endl; return; } @@ -539,14 +582,14 @@ void ShadowRenderer::createShaders() if (mixcsm_shader == -1) { std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass2_vertex.glsl"); if (depth_shader_vs.empty()) { - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error cascade shadow mapping fs shader not found." << std::endl; return; } std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass2_fragment.glsl"); if (depth_shader_fs.empty()) { - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error cascade shadow mapping fs shader not found." << std::endl; return; } @@ -565,7 +608,7 @@ void ShadowRenderer::createShaders() // upsi, something went wrong loading shader. delete m_shadow_mix_cb; delete m_screen_quad; - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error compiling cascade shadow mapping shader." << std::endl; return; } @@ -579,13 +622,13 @@ void ShadowRenderer::createShaders() if (m_shadow_map_colored && depth_shader_trans == -1) { std::string depth_shader_vs = getShaderPath("shadow_shaders", "pass1_trans_vertex.glsl"); if (depth_shader_vs.empty()) { - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error shadow mapping vs shader not found." << std::endl; return; } std::string depth_shader_fs = getShaderPath("shadow_shaders", "pass1_trans_fragment.glsl"); if (depth_shader_fs.empty()) { - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error shadow mapping fs shader not found." << std::endl; return; } @@ -601,7 +644,7 @@ void ShadowRenderer::createShaders() // upsi, something went wrong loading shader. delete m_shadow_depth_trans_cb; m_shadow_map_colored = false; - m_shadows_enabled = false; + m_shadows_supported = false; errorstream << "Error compiling colored shadow mapping shader." << std::endl; return; } diff --git a/src/client/shadows/dynamicshadowsrender.h b/src/client/shadows/dynamicshadowsrender.h index e4b3c3e22..dc8f79c56 100644 --- a/src/client/shadows/dynamicshadowsrender.h +++ b/src/client/shadows/dynamicshadowsrender.h @@ -82,11 +82,12 @@ public: } - bool is_active() const { return m_shadows_enabled; } + bool is_active() const { return m_shadows_enabled && shadowMapTextureFinal != nullptr; } void setTimeOfDay(float isDay) { m_time_day = isDay; }; + void setShadowIntensity(float shadow_intensity); s32 getShadowSamples() const { return m_shadow_samples; } - float getShadowStrength() const { return m_shadow_strength; } + float getShadowStrength() const { return m_shadows_enabled ? m_shadow_strength : 0.0f; } float getTimeOfDay() const { return m_time_day; } private: @@ -101,6 +102,9 @@ private: void mixShadowsQuad(); void updateSMTextures(); + void disable(); + void enable() { m_shadows_enabled = m_shadows_supported; } + // a bunch of variables IrrlichtDevice *m_device{nullptr}; scene::ISceneManager *m_smgr{nullptr}; @@ -116,12 +120,14 @@ private: std::vector m_shadow_node_array; float m_shadow_strength; + float m_shadow_strength_gamma; float m_shadow_map_max_distance; float m_shadow_map_texture_size; float m_time_day{0.0f}; int m_shadow_samples; bool m_shadow_map_texture_32bit; bool m_shadows_enabled; + bool m_shadows_supported; bool m_shadow_map_colored; u8 m_map_shadow_update_frames; /* Use this number of frames to update map shaodw */ u8 m_current_frame{0}; /* Current frame */ diff --git a/src/client/sky.h b/src/client/sky.h index 3dc057b70..e03683f12 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -65,6 +65,7 @@ public: } void setSunVisible(bool sun_visible) { m_sun_params.visible = sun_visible; } + bool getSunVisible() const { return m_sun_params.visible; } void setSunTexture(const std::string &sun_texture, const std::string &sun_tonemap, ITextureSource *tsrc); void setSunScale(f32 sun_scale) { m_sun_params.scale = sun_scale; } @@ -72,6 +73,7 @@ public: void setSunriseTexture(const std::string &sunglow_texture, ITextureSource* tsrc); void setMoonVisible(bool moon_visible) { m_moon_params.visible = moon_visible; } + bool getMoonVisible() const { return m_moon_params.visible; } void setMoonTexture(const std::string &moon_texture, const std::string &moon_tonemap, ITextureSource *tsrc); void setMoonScale(f32 moon_scale) { m_moon_params.scale = moon_scale; } diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index b935c0e21..2e9a19199 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -266,7 +266,7 @@ void set_default_settings() // Effects Shadows settings->setDefault("enable_dynamic_shadows", "false"); - settings->setDefault("shadow_strength", "0.2"); + settings->setDefault("shadow_strength_gamma", "1.0"); settings->setDefault("shadow_map_max_distance", "200.0"); settings->setDefault("shadow_map_texture_size", "2048"); settings->setDefault("shadow_map_texture_32bit", "true"); diff --git a/src/lighting.h b/src/lighting.h new file mode 100644 index 000000000..e0d9cee09 --- /dev/null +++ b/src/lighting.h @@ -0,0 +1,27 @@ +/* +Minetest +Copyright (C) 2021 x2048, Dmitry Kostenko + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +/** Describes ambient light settings for a player + */ +struct Lighting +{ + float shadow_intensity {0.0f}; +}; diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp index a98a5e7d1..6a78b4652 100644 --- a/src/network/clientopcodes.cpp +++ b/src/network/clientopcodes.cpp @@ -123,6 +123,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] = { "TOCLIENT_SRP_BYTES_S_B", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_SrpBytesSandB }, // 0x60 { "TOCLIENT_FORMSPEC_PREPEND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FormspecPrepend }, // 0x61, { "TOCLIENT_MINIMAP_MODES", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MinimapModes }, // 0x62, + { "TOCLIENT_SET_LIGHTING", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_SetLighting }, // 0x63, }; const static ServerCommandFactory null_command_factory = { "TOSERVER_NULL", 0, false }; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 48ad60ac6..15b576640 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1682,3 +1682,11 @@ void Client::handleCommand_MinimapModes(NetworkPacket *pkt) if (m_minimap) m_minimap->setModeIndex(mode); } + +void Client::handleCommand_SetLighting(NetworkPacket *pkt) +{ + Lighting& lighting = m_env.getLocalPlayer()->getLighting(); + + if (pkt->getRemainingBytes() >= 4) + *pkt >> lighting.shadow_intensity; +} diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index a5ff53216..f98a829ba 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -762,7 +762,12 @@ enum ToClientCommand std::string extra */ - TOCLIENT_NUM_MSG_TYPES = 0x63, + TOCLIENT_SET_LIGHTING = 0x63, + /* + f32 shadow_intensity + */ + + TOCLIENT_NUM_MSG_TYPES = 0x64, }; enum ToServerCommand diff --git a/src/remoteplayer.h b/src/remoteplayer.h index e33630841..0ab33adfe 100644 --- a/src/remoteplayer.h +++ b/src/remoteplayer.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "player.h" #include "skyparams.h" +#include "lighting.h" class PlayerSAO; @@ -125,6 +126,10 @@ public: *frame_speed = local_animation_speed; } + void setLighting(const Lighting &lighting) { m_lighting = lighting; } + + const Lighting& getLighting() const { return m_lighting; } + void setDirty(bool dirty) { m_dirty = true; } u16 protocol_version = 0; @@ -160,5 +165,7 @@ private: MoonParams m_moon_params; StarParams m_star_params; + Lighting m_lighting; + session_t m_peer_id = PEER_ID_INEXISTENT; }; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 1ed6b0d5c..6153a0399 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2295,6 +2295,47 @@ int ObjectRef::l_set_minimap_modes(lua_State *L) return 0; } +// set_lighting(self, lighting) +int ObjectRef::l_set_lighting(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + RemotePlayer *player = getplayer(ref); + if (player == nullptr) + return 0; + + luaL_checktype(L, 2, LUA_TTABLE); + Lighting lighting = player->getLighting(); + lua_getfield(L, 2, "shadows"); + if (lua_istable(L, -1)) { + lighting.shadow_intensity = getfloatfield_default(L, -1, "intensity", lighting.shadow_intensity); + } + lua_pop(L, -1); + + getServer(L)->setLighting(player, lighting); + lua_pushboolean(L, true); + return 1; +} + +// get_lighting(self) +int ObjectRef::l_get_lighting(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + RemotePlayer *player = getplayer(ref); + if (player == nullptr) + return 0; + + const Lighting &lighting = player->getLighting(); + + lua_newtable(L); // result + lua_newtable(L); // "shadows" + lua_pushnumber(L, lighting.shadow_intensity); + lua_setfield(L, -2, "intensity"); + lua_setfield(L, -2, "shadows"); + return 1; +} + ObjectRef::ObjectRef(ServerActiveObject *object): m_object(object) {} @@ -2448,5 +2489,7 @@ luaL_Reg ObjectRef::methods[] = { luamethod(ObjectRef, get_eye_offset), luamethod(ObjectRef, send_mapblock), luamethod(ObjectRef, set_minimap_modes), + luamethod(ObjectRef, set_lighting), + luamethod(ObjectRef, get_lighting), {0,0} }; diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index 084d40c05..3e4e6681a 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -376,4 +376,10 @@ private: // set_minimap_modes(self, modes, wanted_mode) static int l_set_minimap_modes(lua_State *L); + + // set_lighting(self, lighting) + static int l_set_lighting(lua_State *L); + + // get_lighting(self) + static int l_get_lighting(lua_State *L); }; diff --git a/src/server.cpp b/src/server.cpp index d9205c895..4bc049e32 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1795,6 +1795,16 @@ void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override, Send(&pkt); } +void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) +{ + NetworkPacket pkt(TOCLIENT_SET_LIGHTING, + 4, peer_id); + + pkt << lighting.shadow_intensity; + + Send(&pkt); +} + void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed) { NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id); @@ -3386,6 +3396,13 @@ void Server::overrideDayNightRatio(RemotePlayer *player, bool do_override, SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio); } +void Server::setLighting(RemotePlayer *player, const Lighting &lighting) +{ + sanity_check(player); + player->setLighting(lighting); + SendSetLighting(player->getPeerId(), lighting); +} + void Server::notifyPlayers(const std::wstring &msg) { SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg)); diff --git a/src/server.h b/src/server.h index 2741b3157..c05393291 100644 --- a/src/server.h +++ b/src/server.h @@ -69,6 +69,7 @@ struct SkyboxParams; struct SunParams; struct MoonParams; struct StarParams; +struct Lighting; class ServerThread; class ServerModManager; class ServerInventoryManager; @@ -333,6 +334,8 @@ public: void overrideDayNightRatio(RemotePlayer *player, bool do_override, float brightness); + void setLighting(RemotePlayer *player, const Lighting &lighting); + /* con::PeerHandler implementation. */ void peerAdded(con::Peer *peer); void deletingPeer(con::Peer *peer, bool timeout); @@ -459,6 +462,7 @@ private: void SendSetStars(session_t peer_id, const StarParams ¶ms); void SendCloudParams(session_t peer_id, const CloudParams ¶ms); void SendOverrideDayNightRatio(session_t peer_id, bool do_override, float ratio); + void SendSetLighting(session_t peer_id, const Lighting &lighting); void broadcastModChannelMessage(const std::string &channel, const std::string &message, session_t from_peer); -- cgit v1.2.3 From 31578303a4eab6b6b083e57b6bf8d12ff3b3d991 Mon Sep 17 00:00:00 2001 From: x2048 Date: Thu, 31 Mar 2022 22:40:06 +0200 Subject: Tune shadow perspective distortion (#12146) * Pass perspective distortion parameters as uniforms * Set all perspective bias parameters via ShadowRenderer * Recalibrate perspective distortion and shadow range to render less shadow geometry with the same quality and observed shadow distance --- builtin/mainmenu/tab_settings.lua | 10 ++--- client/shaders/nodes_shader/opengl_fragment.glsl | 18 ++++---- client/shaders/nodes_shader/opengl_vertex.glsl | 8 ++-- client/shaders/object_shader/opengl_fragment.glsl | 18 ++++---- client/shaders/object_shader/opengl_vertex.glsl | 8 ++-- .../shaders/shadow_shaders/pass1_trans_vertex.glsl | 10 ++--- client/shaders/shadow_shaders/pass1_vertex.glsl | 10 ++--- src/client/shader.cpp | 48 ++++++++++++++++------ src/client/shadows/dynamicshadowsrender.cpp | 25 +++++++++-- src/client/shadows/dynamicshadowsrender.h | 6 +++ src/client/shadows/shadowsshadercallbacks.cpp | 6 +++ src/client/shadows/shadowsshadercallbacks.h | 9 +++- 12 files changed, 117 insertions(+), 59 deletions(-) (limited to 'src/client/shadows/dynamicshadowsrender.cpp') diff --git a/builtin/mainmenu/tab_settings.lua b/builtin/mainmenu/tab_settings.lua index 42f7f8daf..0e761d324 100644 --- a/builtin/mainmenu/tab_settings.lua +++ b/builtin/mainmenu/tab_settings.lua @@ -364,11 +364,11 @@ local function handle_settings_buttons(this, fields, tabname, tabdata) core.settings:set("enable_dynamic_shadows", "false") else local shadow_presets = { - [2] = { 80, 512, "true", 0, "false" }, - [3] = { 120, 1024, "true", 1, "false" }, - [4] = { 350, 2048, "true", 1, "false" }, - [5] = { 350, 2048, "true", 2, "true" }, - [6] = { 450, 4096, "true", 2, "true" }, + [2] = { 55, 512, "true", 0, "false" }, + [3] = { 82, 1024, "true", 1, "false" }, + [4] = { 240, 2048, "true", 1, "false" }, + [5] = { 240, 2048, "true", 2, "true" }, + [6] = { 300, 4096, "true", 2, "true" }, } local s = shadow_presets[table.indexof(labels.shadow_levels, fields["dd_shadows"])] if s then diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index adc8adccb..3dc66bdb3 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -47,17 +47,17 @@ const float fogShadingParameter = 1.0 / ( 1.0 - fogStart); #ifdef ENABLE_DYNAMIC_SHADOWS -const float bias0 = 0.9; -const float zPersFactor = 0.5; -const float bias1 = 1.0 - bias0 + 1e-6; +uniform float xyPerspectiveBias0; +uniform float xyPerspectiveBias1; +uniform float zPerspectiveBias; vec4 getPerspectiveFactor(in vec4 shadowPosition) { float pDistance = length(shadowPosition.xy); - float pFactor = pDistance * bias0 + bias1; + float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; - shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPersFactor); + shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPerspectiveBias); return shadowPosition; } @@ -172,12 +172,12 @@ float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDis float getBaseLength(vec2 smTexCoord) { float l = length(2.0 * smTexCoord.xy - 1.0); // length in texture coords - return bias1 / (1.0 / l - bias0); // return to undistorted coords + return xyPerspectiveBias1 / (1.0 / l - xyPerspectiveBias0); // return to undistorted coords } float getDeltaPerspectiveFactor(float l) { - return 0.1 / (bias0 * l + bias1); // original distortion factor, divided by 10 + return 0.1 / (xyPerspectiveBias0 * l + xyPerspectiveBias1); // original distortion factor, divided by 10 } float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance, float multiplier) @@ -489,8 +489,8 @@ void main(void) vec3 shadow_color = vec3(0.0, 0.0, 0.0); vec3 posLightSpace = getLightSpacePosition(); - float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 20.0)); - float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z ),0.0); + float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 50.0)); + float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z),0.0); if (distance_rate > 1e-7) { diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 5e77ac719..935fbf043 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -45,8 +45,8 @@ varying float nightRatio; const vec3 artificialLight = vec3(1.04, 1.04, 1.04); const float e = 2.718281828459; const float BS = 10.0; -const float bias0 = 0.9; -const float bias1 = 1.0 - bias0; +uniform float xyPerspectiveBias0; +uniform float xyPerspectiveBias1; #ifdef ENABLE_DYNAMIC_SHADOWS // custom smoothstep implementation because it's not defined in glsl1.2 @@ -206,9 +206,9 @@ void main(void) // Distance from the vertex to the player float distanceToPlayer = length(eyeToVertex - v_LightDirection * dot(eyeToVertex, v_LightDirection)) / f_shadowfar; // perspective factor estimation according to the - float perspectiveFactor = distanceToPlayer * bias0 + bias1; + float perspectiveFactor = distanceToPlayer * xyPerspectiveBias0 + xyPerspectiveBias1; float texelSize = f_shadowfar * perspectiveFactor * perspectiveFactor / - (f_textureresolution * bias1 - perspectiveFactor * bias0); + (f_textureresolution * xyPerspectiveBias1 - perspectiveFactor * xyPerspectiveBias0); float slopeScale = clamp(pow(1.0 - cosLight*cosLight, 0.5), 0.0, 1.0); normalOffsetScale = texelSize * slopeScale; diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index edb9d2bb1..2b9a59cd7 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -43,17 +43,17 @@ const float fogShadingParameter = 1.0 / (1.0 - fogStart); #endif #ifdef ENABLE_DYNAMIC_SHADOWS -const float bias0 = 0.9; -const float zPersFactor = 0.5; -const float bias1 = 1.0 - bias0 + 1e-6; +uniform float xyPerspectiveBias0; +uniform float xyPerspectiveBias1; +uniform float zPerspectiveBias; vec4 getPerspectiveFactor(in vec4 shadowPosition) { float pDistance = length(shadowPosition.xy); - float pFactor = pDistance * bias0 + bias1; + float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; - shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPersFactor); + shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPerspectiveBias); return shadowPosition; } @@ -162,12 +162,12 @@ float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDis float getBaseLength(vec2 smTexCoord) { float l = length(2.0 * smTexCoord.xy - 1.0); // length in texture coords - return bias1 / (1.0 / l - bias0); // return to undistorted coords + return xyPerspectiveBias1 / (1.0 / l - xyPerspectiveBias0); // return to undistorted coords } float getDeltaPerspectiveFactor(float l) { - return 0.1 / (bias0 * l + bias1); // original distortion factor, divided by 10 + return 0.1 / (xyPerspectiveBias0 * l + xyPerspectiveBias1); // original distortion factor, divided by 10 } float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance, float multiplier) @@ -477,8 +477,8 @@ void main(void) vec3 shadow_color = vec3(0.0, 0.0, 0.0); vec3 posLightSpace = getLightSpacePosition(); - float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 20.0)); - float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z ),0.0); + float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 50.0)); + float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z),0.0); if (distance_rate > 1e-7) { diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index ff0067302..55861b0e9 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -37,8 +37,8 @@ const vec3 artificialLight = vec3(1.04, 1.04, 1.04); varying float vIDiff; const float e = 2.718281828459; const float BS = 10.0; -const float bias0 = 0.9; -const float bias1 = 1.0 - bias0; +uniform float xyPerspectiveBias0; +uniform float xyPerspectiveBias1; #ifdef ENABLE_DYNAMIC_SHADOWS // custom smoothstep implementation because it's not defined in glsl1.2 @@ -116,9 +116,9 @@ void main(void) // Distance from the vertex to the player float distanceToPlayer = length(eyeToVertex - v_LightDirection * dot(eyeToVertex, v_LightDirection)) / f_shadowfar; // perspective factor estimation according to the - float perspectiveFactor = distanceToPlayer * bias0 + bias1; + float perspectiveFactor = distanceToPlayer * xyPerspectiveBias0 + xyPerspectiveBias1; float texelSize = f_shadowfar * perspectiveFactor * perspectiveFactor / - (f_textureresolution * bias1 - perspectiveFactor * bias0); + (f_textureresolution * xyPerspectiveBias1 - perspectiveFactor * xyPerspectiveBias0); float slopeScale = clamp(pow(1.0 - cosLight*cosLight, 0.5), 0.0, 1.0); normalOffsetScale = texelSize * slopeScale; diff --git a/client/shaders/shadow_shaders/pass1_trans_vertex.glsl b/client/shaders/shadow_shaders/pass1_trans_vertex.glsl index 0a9efe450..6d2877d18 100644 --- a/client/shaders/shadow_shaders/pass1_trans_vertex.glsl +++ b/client/shaders/shadow_shaders/pass1_trans_vertex.glsl @@ -4,15 +4,15 @@ varying vec4 tPos; varying vec3 varColor; #endif -const float bias0 = 0.9; -const float zPersFactor = 0.5; -const float bias1 = 1.0 - bias0 + 1e-6; +uniform float xyPerspectiveBias0; +uniform float xyPerspectiveBias1; +uniform float zPerspectiveBias; vec4 getPerspectiveFactor(in vec4 shadowPosition) { float pDistance = length(shadowPosition.xy); - float pFactor = pDistance * bias0 + bias1; - shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPersFactor); + float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; + shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPerspectiveBias); return shadowPosition; } diff --git a/client/shaders/shadow_shaders/pass1_vertex.glsl b/client/shaders/shadow_shaders/pass1_vertex.glsl index feee9467f..3873ac6e6 100644 --- a/client/shaders/shadow_shaders/pass1_vertex.glsl +++ b/client/shaders/shadow_shaders/pass1_vertex.glsl @@ -1,15 +1,15 @@ uniform mat4 LightMVP; // world matrix varying vec4 tPos; -const float bias0 = 0.9; -const float zPersFactor = 0.5; -const float bias1 = 1.0 - bias0 + 1e-6; +uniform float xyPerspectiveBias0; +uniform float xyPerspectiveBias1; +uniform float zPerspectiveBias; vec4 getPerspectiveFactor(in vec4 shadowPosition) { float pDistance = length(shadowPosition.xy); - float pFactor = pDistance * bias0 + bias1; - shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPersFactor); + float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; + shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPerspectiveBias); return shadowPosition; } diff --git a/src/client/shader.cpp b/src/client/shader.cpp index fa5ffb914..d9c1952c4 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -210,17 +210,23 @@ public: class MainShaderConstantSetter : public IShaderConstantSetter { - CachedVertexShaderSetting m_world_view_proj; - CachedVertexShaderSetting m_world; + CachedVertexShaderSetting m_world_view_proj; + CachedVertexShaderSetting m_world; // Shadow-related - CachedPixelShaderSetting m_shadow_view_proj; - CachedPixelShaderSetting m_light_direction; - CachedPixelShaderSetting m_texture_res; - CachedPixelShaderSetting m_shadow_strength; - CachedPixelShaderSetting m_time_of_day; - CachedPixelShaderSetting m_shadowfar; + CachedPixelShaderSetting m_shadow_view_proj; + CachedPixelShaderSetting m_light_direction; + CachedPixelShaderSetting m_texture_res; + CachedPixelShaderSetting m_shadow_strength; + CachedPixelShaderSetting m_time_of_day; + CachedPixelShaderSetting m_shadowfar; CachedPixelShaderSetting m_shadow_texture; + CachedVertexShaderSetting m_perspective_bias0_vertex; + CachedPixelShaderSetting m_perspective_bias0_pixel; + CachedVertexShaderSetting m_perspective_bias1_vertex; + CachedPixelShaderSetting m_perspective_bias1_pixel; + CachedVertexShaderSetting m_perspective_zbias_vertex; + CachedPixelShaderSetting m_perspective_zbias_pixel; #if ENABLE_GLES // Modelview matrix @@ -247,6 +253,12 @@ public: , m_time_of_day("f_timeofday") , m_shadowfar("f_shadowfar") , m_shadow_texture("ShadowMapSampler") + , m_perspective_bias0_vertex("xyPerspectiveBias0") + , m_perspective_bias0_pixel("xyPerspectiveBias0") + , m_perspective_bias1_vertex("xyPerspectiveBias1") + , m_perspective_bias1_pixel("xyPerspectiveBias1") + , m_perspective_zbias_vertex("zPerspectiveBias") + , m_perspective_zbias_pixel("zPerspectiveBias") {} ~MainShaderConstantSetter() = default; @@ -293,26 +305,36 @@ public: shadowViewProj *= light.getViewMatrix(); m_shadow_view_proj.set(shadowViewProj.pointer(), services); - float v_LightDirection[3]; + f32 v_LightDirection[3]; light.getDirection().getAs3Values(v_LightDirection); m_light_direction.set(v_LightDirection, services); - float TextureResolution = light.getMapResolution(); + f32 TextureResolution = light.getMapResolution(); m_texture_res.set(&TextureResolution, services); - float ShadowStrength = shadow->getShadowStrength(); + f32 ShadowStrength = shadow->getShadowStrength(); m_shadow_strength.set(&ShadowStrength, services); - float timeOfDay = shadow->getTimeOfDay(); + f32 timeOfDay = shadow->getTimeOfDay(); m_time_of_day.set(&timeOfDay, services); - float shadowFar = shadow->getMaxShadowFar(); + f32 shadowFar = shadow->getMaxShadowFar(); m_shadowfar.set(&shadowFar, services); // I dont like using this hardcoded value. maybe something like // MAX_TEXTURE - 1 or somthing like that?? s32 TextureLayerID = 3; m_shadow_texture.set(&TextureLayerID, services); + + f32 bias0 = shadow->getPerspectiveBiasXY(); + m_perspective_bias0_vertex.set(&bias0, services); + m_perspective_bias0_pixel.set(&bias0, services); + f32 bias1 = 1.0f - bias0 + 1e-5f; + m_perspective_bias1_vertex.set(&bias1, services); + m_perspective_bias1_pixel.set(&bias1, services); + f32 zbias = shadow->getPerspectiveBiasZ(); + m_perspective_zbias_vertex.set(&zbias, services); + m_perspective_zbias_pixel.set(&zbias, services); } } }; diff --git a/src/client/shadows/dynamicshadowsrender.cpp b/src/client/shadows/dynamicshadowsrender.cpp index 24adb21e2..262711221 100644 --- a/src/client/shadows/dynamicshadowsrender.cpp +++ b/src/client/shadows/dynamicshadowsrender.cpp @@ -32,7 +32,8 @@ with this program; if not, write to the Free Software Foundation, Inc., ShadowRenderer::ShadowRenderer(IrrlichtDevice *device, Client *client) : m_device(device), m_smgr(device->getSceneManager()), - m_driver(device->getVideoDriver()), m_client(client), m_current_frame(0) + m_driver(device->getVideoDriver()), m_client(client), m_current_frame(0), + m_perspective_bias_xy(0.8), m_perspective_bias_z(0.5) { m_shadows_supported = true; // assume shadows supported. We will check actual support in initialize m_shadows_enabled = true; @@ -59,6 +60,10 @@ ShadowRenderer::~ShadowRenderer() if (m_shadow_depth_cb) delete m_shadow_depth_cb; + if (m_shadow_depth_entity_cb) + delete m_shadow_depth_entity_cb; + if (m_shadow_depth_trans_cb) + delete m_shadow_depth_trans_cb; if (m_shadow_mix_cb) delete m_shadow_mix_cb; m_shadow_node_array.clear(); @@ -250,8 +255,13 @@ void ShadowRenderer::updateSMTextures() // Update SM incrementally: for (DirectionalLight &light : m_light_list) { // Static shader values. - m_shadow_depth_cb->MapRes = (f32)m_shadow_map_texture_size; - m_shadow_depth_cb->MaxFar = (f32)m_shadow_map_max_distance * BS; + for (auto cb : {m_shadow_depth_cb, m_shadow_depth_entity_cb, m_shadow_depth_trans_cb}) + if (cb) { + cb->MapRes = (f32)m_shadow_map_texture_size; + cb->MaxFar = (f32)m_shadow_map_max_distance * BS; + cb->PerspectiveBiasXY = getPerspectiveBiasXY(); + cb->PerspectiveBiasZ = getPerspectiveBiasZ(); + } // set the Render Target // right now we can only render in usual RTT, not @@ -533,6 +543,8 @@ void ShadowRenderer::createShaders() if (depth_shader == -1) { // upsi, something went wrong loading shader. delete m_shadow_depth_cb; + m_shadow_depth_cb = nullptr; + m_shadows_enabled = false; m_shadows_supported = false; errorstream << "Error compiling shadow mapping shader." << std::endl; return; @@ -559,15 +571,19 @@ void ShadowRenderer::createShaders() errorstream << "Error shadow mapping fs shader not found." << std::endl; return; } + m_shadow_depth_entity_cb = new ShadowDepthShaderCB(); depth_shader_entities = gpu->addHighLevelShaderMaterial( readShaderFile(depth_shader_vs).c_str(), "vertexMain", video::EVST_VS_1_1, readShaderFile(depth_shader_fs).c_str(), "pixelMain", - video::EPST_PS_1_2, m_shadow_depth_cb); + video::EPST_PS_1_2, m_shadow_depth_entity_cb); if (depth_shader_entities == -1) { // upsi, something went wrong loading shader. + delete m_shadow_depth_entity_cb; + m_shadow_depth_entity_cb = nullptr; + m_shadows_enabled = false; m_shadows_supported = false; errorstream << "Error compiling shadow mapping shader (dynamic)." << std::endl; return; @@ -643,6 +659,7 @@ void ShadowRenderer::createShaders() if (depth_shader_trans == -1) { // upsi, something went wrong loading shader. delete m_shadow_depth_trans_cb; + m_shadow_depth_trans_cb = nullptr; m_shadow_map_colored = false; m_shadows_supported = false; errorstream << "Error compiling colored shadow mapping shader." << std::endl; diff --git a/src/client/shadows/dynamicshadowsrender.h b/src/client/shadows/dynamicshadowsrender.h index dc8f79c56..bbeb254b0 100644 --- a/src/client/shadows/dynamicshadowsrender.h +++ b/src/client/shadows/dynamicshadowsrender.h @@ -90,6 +90,9 @@ public: float getShadowStrength() const { return m_shadows_enabled ? m_shadow_strength : 0.0f; } float getTimeOfDay() const { return m_time_day; } + f32 getPerspectiveBiasXY() { return m_perspective_bias_xy; } + f32 getPerspectiveBiasZ() { return m_perspective_bias_z; } + private: video::ITexture *getSMTexture(const std::string &shadow_map_name, video::ECOLOR_FORMAT texture_format, @@ -131,6 +134,8 @@ private: bool m_shadow_map_colored; u8 m_map_shadow_update_frames; /* Use this number of frames to update map shaodw */ u8 m_current_frame{0}; /* Current frame */ + f32 m_perspective_bias_xy; + f32 m_perspective_bias_z; video::ECOLOR_FORMAT m_texture_format{video::ECOLOR_FORMAT::ECF_R16F}; video::ECOLOR_FORMAT m_texture_format_color{video::ECOLOR_FORMAT::ECF_R16G16}; @@ -146,6 +151,7 @@ private: s32 mixcsm_shader{-1}; ShadowDepthShaderCB *m_shadow_depth_cb{nullptr}; + ShadowDepthShaderCB *m_shadow_depth_entity_cb{nullptr}; ShadowDepthShaderCB *m_shadow_depth_trans_cb{nullptr}; shadowScreenQuad *m_screen_quad{nullptr}; diff --git a/src/client/shadows/shadowsshadercallbacks.cpp b/src/client/shadows/shadowsshadercallbacks.cpp index 65a63f49c..51ea8aa93 100644 --- a/src/client/shadows/shadowsshadercallbacks.cpp +++ b/src/client/shadows/shadowsshadercallbacks.cpp @@ -33,4 +33,10 @@ void ShadowDepthShaderCB::OnSetConstants( m_max_far_setting.set(&MaxFar, services); s32 TextureId = 0; m_color_map_sampler_setting.set(&TextureId, services); + f32 bias0 = PerspectiveBiasXY; + m_perspective_bias0.set(&bias0, services); + f32 bias1 = 1.0f - bias0 + 1e-5f; + m_perspective_bias1.set(&bias1, services); + f32 zbias = PerspectiveBiasZ; + m_perspective_zbias.set(&zbias, services); } diff --git a/src/client/shadows/shadowsshadercallbacks.h b/src/client/shadows/shadowsshadercallbacks.h index 3549567c3..d00f59c37 100644 --- a/src/client/shadows/shadowsshadercallbacks.h +++ b/src/client/shadows/shadowsshadercallbacks.h @@ -30,7 +30,10 @@ public: m_light_mvp_setting("LightMVP"), m_map_resolution_setting("MapResolution"), m_max_far_setting("MaxFar"), - m_color_map_sampler_setting("ColorMapSampler") + m_color_map_sampler_setting("ColorMapSampler"), + m_perspective_bias0("xyPerspectiveBias0"), + m_perspective_bias1("xyPerspectiveBias1"), + m_perspective_zbias("zPerspectiveBias") {} void OnSetMaterial(const video::SMaterial &material) override {} @@ -39,10 +42,14 @@ public: s32 userData) override; f32 MaxFar{2048.0f}, MapRes{1024.0f}; + f32 PerspectiveBiasXY {0.9f}, PerspectiveBiasZ {0.5f}; private: CachedVertexShaderSetting m_light_mvp_setting; CachedVertexShaderSetting m_map_resolution_setting; CachedVertexShaderSetting m_max_far_setting; CachedPixelShaderSetting m_color_map_sampler_setting; + CachedVertexShaderSetting m_perspective_bias0; + CachedVertexShaderSetting m_perspective_bias1; + CachedVertexShaderSetting m_perspective_zbias; }; -- cgit v1.2.3 From 48f7c5603e5b2dfca941d228e76e452bc269a1fa Mon Sep 17 00:00:00 2001 From: x2048 Date: Thu, 7 Apr 2022 22:13:50 +0200 Subject: Adjust shadowmap distortion to use entire SM texture (#12166) --- client/shaders/nodes_shader/opengl_fragment.glsl | 25 +++--- client/shaders/object_shader/opengl_fragment.glsl | 89 +++++++++++++--------- .../shaders/shadow_shaders/pass1_trans_vertex.glsl | 10 ++- client/shaders/shadow_shaders/pass1_vertex.glsl | 10 ++- src/client/clientmap.cpp | 36 +++------ src/client/clientmap.h | 2 +- src/client/shader.cpp | 6 ++ src/client/shadows/dynamicshadows.cpp | 58 ++++++++------ src/client/shadows/dynamicshadows.h | 10 ++- src/client/shadows/dynamicshadowsrender.cpp | 11 +-- src/client/shadows/shadowsshadercallbacks.cpp | 6 ++ src/client/shadows/shadowsshadercallbacks.h | 5 +- 12 files changed, 156 insertions(+), 112 deletions(-) (limited to 'src/client/shadows/dynamicshadowsrender.cpp') diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 3dc66bdb3..4d0d107d1 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -17,6 +17,7 @@ uniform float animationTimer; uniform mat4 m_ShadowViewProj; uniform float f_shadowfar; uniform float f_shadow_strength; + uniform vec4 CameraPos; varying float normalOffsetScale; varying float adj_shadow_strength; varying float cosLight; @@ -53,12 +54,13 @@ uniform float zPerspectiveBias; vec4 getPerspectiveFactor(in vec4 shadowPosition) { - - float pDistance = length(shadowPosition.xy); + vec2 s = vec2(shadowPosition.x > CameraPos.x ? 1.0 : -1.0, shadowPosition.y > CameraPos.y ? 1.0 : -1.0); + vec2 l = s * (shadowPosition.xy - CameraPos.xy) / (1.0 - s * CameraPos.xy); + float pDistance = length(l); float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; - - shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPerspectiveBias); - + l /= pFactor; + shadowPosition.xy = CameraPos.xy * (1.0 - l) + s * l; + shadowPosition.z *= zPerspectiveBias; return shadowPosition; } @@ -171,13 +173,13 @@ float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDis float getBaseLength(vec2 smTexCoord) { - float l = length(2.0 * smTexCoord.xy - 1.0); // length in texture coords + float l = length(2.0 * smTexCoord.xy - 1.0 - CameraPos.xy); // length in texture coords return xyPerspectiveBias1 / (1.0 / l - xyPerspectiveBias0); // return to undistorted coords } float getDeltaPerspectiveFactor(float l) { - return 0.1 / (xyPerspectiveBias0 * l + xyPerspectiveBias1); // original distortion factor, divided by 10 + return 0.04 * pow(512.0 / f_textureresolution, 0.4) / (xyPerspectiveBias0 * l + xyPerspectiveBias1); // original distortion factor, divided by 10 } float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance, float multiplier) @@ -185,7 +187,6 @@ float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDist float baseLength = getBaseLength(smTexCoord); float perspectiveFactor; - if (PCFBOUND == 0.0) return 0.0; // Return fast if sharp shadows are requested if (PCFBOUND == 0.0) return 0.0; @@ -489,11 +490,13 @@ void main(void) vec3 shadow_color = vec3(0.0, 0.0, 0.0); vec3 posLightSpace = getLightSpacePosition(); - float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 50.0)); + float distance_rate = (1.0 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 10.0)); + if (max(abs(posLightSpace.x - 0.5), abs(posLightSpace.y - 0.5)) > 0.5) + distance_rate = 0.0; float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z),0.0); if (distance_rate > 1e-7) { - + #ifdef COLORED_SHADOWS vec4 visibility; if (cosLight > 0.0) @@ -527,7 +530,7 @@ void main(void) } shadow_int *= f_adj_shadow_strength; - + // calculate fragment color from components: col.rgb = adjusted_night_ratio * col.rgb + // artificial light diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 2b9a59cd7..2611bf8ef 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -6,8 +6,33 @@ uniform vec4 skyBgColor; uniform float fogDistance; uniform vec3 eyePosition; +// The cameraOffset is the current center of the visible world. +uniform vec3 cameraOffset; +uniform float animationTimer; +#ifdef ENABLE_DYNAMIC_SHADOWS + // shadow texture + uniform sampler2D ShadowMapSampler; + // shadow uniforms + uniform vec3 v_LightDirection; + uniform float f_textureresolution; + uniform mat4 m_ShadowViewProj; + uniform float f_shadowfar; + uniform float f_shadow_strength; + uniform vec4 CameraPos; + varying float normalOffsetScale; + varying float adj_shadow_strength; + varying float cosLight; + varying float f_normal_length; +#endif + + varying vec3 vNormal; varying vec3 vPosition; +// World position in the visible world (i.e. relative to the cameraOffset.) +// This can be used for many shader effects without loss of precision. +// If the absolute position is required it can be calculated with +// cameraOffset + worldPosition (for large coordinates the limits of float +// precision must be considered). varying vec3 worldPosition; varying lowp vec4 varColor; #ifdef GL_ES @@ -15,32 +40,15 @@ varying mediump vec2 varTexCoord; #else centroid varying vec2 varTexCoord; #endif - varying vec3 eyeVec; varying float nightRatio; varying float vIDiff; -const float e = 2.718281828459; -const float BS = 10.0; const float fogStart = FOG_START; const float fogShadingParameter = 1.0 / (1.0 - fogStart); -#ifdef ENABLE_DYNAMIC_SHADOWS - // shadow texture - uniform sampler2D ShadowMapSampler; - // shadow uniforms - uniform vec3 v_LightDirection; - uniform float f_textureresolution; - uniform mat4 m_ShadowViewProj; - uniform float f_shadowfar; - uniform float f_timeofday; - uniform float f_shadow_strength; - varying float normalOffsetScale; - varying float adj_shadow_strength; - varying float cosLight; - varying float f_normal_length; -#endif + #ifdef ENABLE_DYNAMIC_SHADOWS uniform float xyPerspectiveBias0; @@ -49,15 +57,22 @@ uniform float zPerspectiveBias; vec4 getPerspectiveFactor(in vec4 shadowPosition) { - - float pDistance = length(shadowPosition.xy); + vec2 s = vec2(shadowPosition.x > CameraPos.x ? 1.0 : -1.0, shadowPosition.y > CameraPos.y ? 1.0 : -1.0); + vec2 l = s * (shadowPosition.xy - CameraPos.xy) / (1.0 - s * CameraPos.xy); + float pDistance = length(l); float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; - - shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPerspectiveBias); - + l /= pFactor; + shadowPosition.xy = CameraPos.xy * (1.0 - l) + s * l; + shadowPosition.z *= zPerspectiveBias; return shadowPosition; } +// assuming near is always 1.0 +float getLinearDepth() +{ + return 2.0 * f_shadowfar / (f_shadowfar + 1.0 - (2.0 * gl_FragCoord.z - 1.0) * (f_shadowfar - 1.0)); +} + vec3 getLightSpacePosition() { vec4 pLightSpace; @@ -161,13 +176,13 @@ float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDis float getBaseLength(vec2 smTexCoord) { - float l = length(2.0 * smTexCoord.xy - 1.0); // length in texture coords + float l = length(2.0 * smTexCoord.xy - 1.0 - CameraPos.xy); // length in texture coords return xyPerspectiveBias1 / (1.0 / l - xyPerspectiveBias0); // return to undistorted coords } float getDeltaPerspectiveFactor(float l) { - return 0.1 / (xyPerspectiveBias0 * l + xyPerspectiveBias1); // original distortion factor, divided by 10 + return 0.04 * pow(512.0 / f_textureresolution, 0.4) / (xyPerspectiveBias0 * l + xyPerspectiveBias1); // original distortion factor, divided by 10 } float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance, float multiplier) @@ -178,7 +193,7 @@ float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDist // Return fast if sharp shadows are requested if (PCFBOUND == 0.0) return 0.0; - + if (SOFTSHADOWRADIUS <= 1.0) { perspectiveFactor = getDeltaPerspectiveFactor(baseLength); return max(2 * length(smTexCoord.xy) * 2048 / f_textureresolution / pow(perspectiveFactor, 3), SOFTSHADOWRADIUS); @@ -418,6 +433,7 @@ float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance) #endif #if ENABLE_TONE_MAPPING + /* Hable's UC2 Tone mapping parameters A = 0.22; B = 0.30; @@ -448,12 +464,14 @@ vec4 applyToneMapping(vec4 color) } #endif + + void main(void) { vec3 color; vec2 uv = varTexCoord.st; - vec4 base = texture2D(baseTexture, uv).rgba; + vec4 base = texture2D(baseTexture, uv).rgba; // If alpha is zero, we can just discard the pixel. This fixes transparency // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa, // and also on GLES 2, where GL_ALPHA_TEST is missing entirely. @@ -467,8 +485,7 @@ void main(void) #endif color = base.rgb; - vec4 col = vec4(color.rgb, base.a); - col.rgb *= varColor.rgb; + vec4 col = vec4(color.rgb * varColor.rgb, 1.0); col.rgb *= vIDiff; #ifdef ENABLE_DYNAMIC_SHADOWS @@ -477,11 +494,13 @@ void main(void) vec3 shadow_color = vec3(0.0, 0.0, 0.0); vec3 posLightSpace = getLightSpacePosition(); - float distance_rate = (1 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 50.0)); + float distance_rate = (1.0 - pow(clamp(2.0 * length(posLightSpace.xy - 0.5),0.0,1.0), 10.0)); + if (max(abs(posLightSpace.x - 0.5), abs(posLightSpace.y - 0.5)) > 0.5) + distance_rate = 0.0; float f_adj_shadow_strength = max(adj_shadow_strength-mtsmoothstep(0.9,1.1, posLightSpace.z),0.0); if (distance_rate > 1e-7) { - + #ifdef COLORED_SHADOWS vec4 visibility; if (cosLight > 0.0) @@ -506,8 +525,8 @@ void main(void) // Power ratio was measured on torches in MTG (brightness = 14). float adjusted_night_ratio = pow(max(0.0, nightRatio), 0.6); - // cosine of the normal-to-light angle when - // we start to apply self-shadowing + // Apply self-shadowing when light falls at a narrow angle to the surface + // Cosine of the cut-off angle. const float self_shadow_cutoff_cosine = 0.14; if (f_normal_length != 0 && cosLight < self_shadow_cutoff_cosine) { shadow_int = max(shadow_int, 1 - clamp(cosLight, 0.0, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); @@ -541,5 +560,7 @@ void main(void) float clarity = clamp(fogShadingParameter - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); col = mix(skyBgColor, col, clarity); - gl_FragColor = vec4(col.rgb, base.a); + col = vec4(col.rgb, base.a); + + gl_FragColor = col; } diff --git a/client/shaders/shadow_shaders/pass1_trans_vertex.glsl b/client/shaders/shadow_shaders/pass1_trans_vertex.glsl index 6d2877d18..c2f575876 100644 --- a/client/shaders/shadow_shaders/pass1_trans_vertex.glsl +++ b/client/shaders/shadow_shaders/pass1_trans_vertex.glsl @@ -1,4 +1,5 @@ uniform mat4 LightMVP; // world matrix +uniform vec4 CameraPos; varying vec4 tPos; #ifdef COLORED_SHADOWS varying vec3 varColor; @@ -10,10 +11,13 @@ uniform float zPerspectiveBias; vec4 getPerspectiveFactor(in vec4 shadowPosition) { - float pDistance = length(shadowPosition.xy); + vec2 s = vec2(shadowPosition.x > CameraPos.x ? 1.0 : -1.0, shadowPosition.y > CameraPos.y ? 1.0 : -1.0); + vec2 l = s * (shadowPosition.xy - CameraPos.xy) / (1.0 - s * CameraPos.xy); + float pDistance = length(l); float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; - shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPerspectiveBias); - + l /= pFactor; + shadowPosition.xy = CameraPos.xy * (1.0 - l) + s * l; + shadowPosition.z *= zPerspectiveBias; return shadowPosition; } diff --git a/client/shaders/shadow_shaders/pass1_vertex.glsl b/client/shaders/shadow_shaders/pass1_vertex.glsl index 3873ac6e6..38aef3619 100644 --- a/client/shaders/shadow_shaders/pass1_vertex.glsl +++ b/client/shaders/shadow_shaders/pass1_vertex.glsl @@ -1,4 +1,5 @@ uniform mat4 LightMVP; // world matrix +uniform vec4 CameraPos; // camera position varying vec4 tPos; uniform float xyPerspectiveBias0; @@ -7,10 +8,13 @@ uniform float zPerspectiveBias; vec4 getPerspectiveFactor(in vec4 shadowPosition) { - float pDistance = length(shadowPosition.xy); + vec2 s = vec2(shadowPosition.x > CameraPos.x ? 1.0 : -1.0, shadowPosition.y > CameraPos.y ? 1.0 : -1.0); + vec2 l = s * (shadowPosition.xy - CameraPos.xy) / (1.0 - s * CameraPos.xy); + float pDistance = length(l); float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; - shadowPosition.xyz *= vec3(vec2(1.0 / pFactor), zPerspectiveBias); - + l /= pFactor; + shadowPosition.xy = CameraPos.xy * (1.0 - l) + s * l; + shadowPosition.z *= zPerspectiveBias; return shadowPosition; } diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index f070a58bb..8a059c922 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -862,20 +862,14 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver, /* Custom update draw list for the pov of shadow light. */ -void ClientMap::updateDrawListShadow(const v3f &shadow_light_pos, const v3f &shadow_light_dir, float shadow_range) +void ClientMap::updateDrawListShadow(v3f shadow_light_pos, v3f shadow_light_dir, float radius, float length) { ScopeProfiler sp(g_profiler, "CM::updateDrawListShadow()", SPT_AVG); - const v3f camera_position = shadow_light_pos; - const v3f camera_direction = shadow_light_dir; - // I "fake" fov just to avoid creating a new function to handle orthographic - // projection. - const f32 camera_fov = m_camera_fov * 1.9f; - - v3s16 cam_pos_nodes = floatToInt(camera_position, BS); + v3s16 cam_pos_nodes = floatToInt(shadow_light_pos, BS); v3s16 p_blocks_min; v3s16 p_blocks_max; - getBlocksInViewRange(cam_pos_nodes, &p_blocks_min, &p_blocks_max, shadow_range); + getBlocksInViewRange(cam_pos_nodes, &p_blocks_min, &p_blocks_max, radius + length); std::vector blocks_in_range; @@ -889,10 +883,10 @@ void ClientMap::updateDrawListShadow(const v3f &shadow_light_pos, const v3f &sha // they are not inside the light frustum and it creates glitches. // FIXME: This could be removed if we figure out why they are missing // from the light frustum. - for (auto &i : m_drawlist) { - i.second->refGrab(); - m_drawlist_shadow[i.first] = i.second; - } + // for (auto &i : m_drawlist) { + // i.second->refGrab(); + // m_drawlist_shadow[i.first] = i.second; + // } // Number of blocks currently loaded by the client u32 blocks_loaded = 0; @@ -919,23 +913,13 @@ void ClientMap::updateDrawListShadow(const v3f &shadow_light_pos, const v3f &sha continue; } - float range = shadow_range; - - float d = 0.0; - if (!isBlockInSight(block->getPos(), camera_position, - camera_direction, camera_fov, range, &d)) + v3f block_pos = intToFloat(block->getPos() * MAP_BLOCKSIZE, BS); + v3f projection = shadow_light_pos + shadow_light_dir * shadow_light_dir.dotProduct(block_pos - shadow_light_pos); + if (projection.getDistanceFrom(block_pos) > radius) continue; blocks_in_range_with_mesh++; - /* - Occlusion culling - */ - if (isBlockOccluded(block, cam_pos_nodes)) { - blocks_occlusion_culled++; - continue; - } - // This block is in range. Reset usage timer. block->resetUsageTimer(); diff --git a/src/client/clientmap.h b/src/client/clientmap.h index 4edad0d20..7bd7af266 100644 --- a/src/client/clientmap.h +++ b/src/client/clientmap.h @@ -116,7 +116,7 @@ public: void getBlocksInViewRange(v3s16 cam_pos_nodes, v3s16 *p_blocks_min, v3s16 *p_blocks_max, float range=-1.0f); void updateDrawList(); - void updateDrawListShadow(const v3f &shadow_light_pos, const v3f &shadow_light_dir, float shadow_range); + void updateDrawListShadow(v3f shadow_light_pos, v3f shadow_light_dir, float radius, float length); // Returns true if draw list needs updating before drawing the next frame. bool needsUpdateDrawList() { return m_needs_update_drawlist; } void renderMap(video::IVideoDriver* driver, s32 pass); diff --git a/src/client/shader.cpp b/src/client/shader.cpp index d9c1952c4..1be9ef128 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -220,6 +220,7 @@ class MainShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_shadow_strength; CachedPixelShaderSetting m_time_of_day; CachedPixelShaderSetting m_shadowfar; + CachedPixelShaderSetting m_camera_pos; CachedPixelShaderSetting m_shadow_texture; CachedVertexShaderSetting m_perspective_bias0_vertex; CachedPixelShaderSetting m_perspective_bias0_pixel; @@ -252,6 +253,7 @@ public: , m_shadow_strength("f_shadow_strength") , m_time_of_day("f_timeofday") , m_shadowfar("f_shadowfar") + , m_camera_pos("CameraPos") , m_shadow_texture("ShadowMapSampler") , m_perspective_bias0_vertex("xyPerspectiveBias0") , m_perspective_bias0_pixel("xyPerspectiveBias0") @@ -321,6 +323,10 @@ public: f32 shadowFar = shadow->getMaxShadowFar(); m_shadowfar.set(&shadowFar, services); + f32 cam_pos[4]; + shadowViewProj.transformVect(cam_pos, light.getPlayerPos()); + m_camera_pos.set(cam_pos, services); + // I dont like using this hardcoded value. maybe something like // MAX_TEXTURE - 1 or somthing like that?? s32 TextureLayerID = 3; diff --git a/src/client/shadows/dynamicshadows.cpp b/src/client/shadows/dynamicshadows.cpp index ddec3a5d5..ca2d3ce37 100644 --- a/src/client/shadows/dynamicshadows.cpp +++ b/src/client/shadows/dynamicshadows.cpp @@ -29,7 +29,6 @@ using m4f = core::matrix4; void DirectionalLight::createSplitMatrices(const Camera *cam) { - float radius; v3f newCenter; v3f look = cam->getDirection(); @@ -42,17 +41,16 @@ void DirectionalLight::createSplitMatrices(const Camera *cam) float sfFar = adjustDist(future_frustum.zFar, cam->getFovY()); // adjusted camera positions - v3f camPos2 = cam->getPosition(); - v3f camPos = v3f(camPos2.X - cam->getOffset().X * BS, - camPos2.Y - cam->getOffset().Y * BS, - camPos2.Z - cam->getOffset().Z * BS); - camPos += look * sfNear; - camPos2 += look * sfNear; + v3f cam_pos_world = cam->getPosition(); + v3f cam_pos_scene = v3f(cam_pos_world.X - cam->getOffset().X * BS, + cam_pos_world.Y - cam->getOffset().Y * BS, + cam_pos_world.Z - cam->getOffset().Z * BS); + cam_pos_scene += look * sfNear; + cam_pos_world += look * sfNear; // center point of light frustum - float end = sfNear + sfFar; - newCenter = camPos + look * (sfNear + 0.05f * end); - v3f world_center = camPos2 + look * (sfNear + 0.05f * end); + v3f center_scene = cam_pos_scene + look * 0.35 * (sfFar - sfNear); + v3f center_world = cam_pos_world + look * 0.35 * (sfFar - sfNear); // Create a vector to the frustum far corner const v3f &viewUp = cam->getCameraNode()->getUpVector(); @@ -60,22 +58,21 @@ void DirectionalLight::createSplitMatrices(const Camera *cam) v3f farCorner = (look + viewRight * tanFovX + viewUp * tanFovY).normalize(); // Compute the frustumBoundingSphere radius - v3f boundVec = (camPos + farCorner * sfFar) - newCenter; - radius = boundVec.getLength(); - // boundVec.getLength(); - float vvolume = radius; - v3f frustumCenter = newCenter; - v3f eye_displacement = direction * vvolume; + v3f boundVec = (cam_pos_scene + farCorner * sfFar) - center_scene; + float radius = boundVec.getLength(); + float length = radius * 3.0f; + v3f eye_displacement = direction * length; // we must compute the viewmat with the position - the camera offset // but the future_frustum position must be the actual world position - v3f eye = frustumCenter - eye_displacement; - future_frustum.position = world_center - eye_displacement; - future_frustum.length = vvolume; - future_frustum.ViewMat.buildCameraLookAtMatrixLH(eye, frustumCenter, v3f(0.0f, 1.0f, 0.0f)); - future_frustum.ProjOrthMat.buildProjectionMatrixOrthoLH(future_frustum.length, - future_frustum.length, -future_frustum.length, - future_frustum.length,false); + v3f eye = center_scene - eye_displacement; + future_frustum.player = cam_pos_scene; + future_frustum.position = center_world - eye_displacement; + future_frustum.length = length; + future_frustum.radius = radius; + future_frustum.ViewMat.buildCameraLookAtMatrixLH(eye, center_scene, v3f(0.0f, 1.0f, 0.0f)); + future_frustum.ProjOrthMat.buildProjectionMatrixOrthoLH(radius, radius, + 0.0f, length, false); future_frustum.camera_offset = cam->getOffset(); } @@ -94,7 +91,7 @@ void DirectionalLight::update_frustum(const Camera *cam, Client *client, bool fo float zNear = cam->getCameraNode()->getNearValue(); float zFar = getMaxFarValue(); if (!client->getEnv().getClientMap().getControl().range_all) - zFar = MYMIN(zFar, client->getEnv().getClientMap().getControl().wanted_range * BS * 1.5); + zFar = MYMIN(zFar, client->getEnv().getClientMap().getControl().wanted_range * BS); /////////////////////////////////// // update splits near and fars @@ -105,7 +102,7 @@ void DirectionalLight::update_frustum(const Camera *cam, Client *client, bool fo createSplitMatrices(cam); // get the draw list for shadows client->getEnv().getClientMap().updateDrawListShadow( - getPosition(), getDirection(), future_frustum.length); + getPosition(), getDirection(), future_frustum.radius, future_frustum.length); should_update_map_shadow = true; dirty = true; @@ -115,6 +112,7 @@ void DirectionalLight::update_frustum(const Camera *cam, Client *client, bool fo v3f rotated_offset; shadow_frustum.ViewMat.rotateVect(rotated_offset, intToFloat(cam_offset - shadow_frustum.camera_offset, BS)); shadow_frustum.ViewMat.setTranslation(shadow_frustum.ViewMat.getTranslation() + rotated_offset); + shadow_frustum.player += intToFloat(shadow_frustum.camera_offset - cam->getOffset(), BS); shadow_frustum.camera_offset = cam_offset; } } @@ -139,6 +137,16 @@ v3f DirectionalLight::getPosition() const return shadow_frustum.position; } +v3f DirectionalLight::getPlayerPos() const +{ + return shadow_frustum.player; +} + +v3f DirectionalLight::getFuturePlayerPos() const +{ + return future_frustum.player; +} + const m4f &DirectionalLight::getViewMatrix() const { return shadow_frustum.ViewMat; diff --git a/src/client/shadows/dynamicshadows.h b/src/client/shadows/dynamicshadows.h index 03dd36014..70574aa6c 100644 --- a/src/client/shadows/dynamicshadows.h +++ b/src/client/shadows/dynamicshadows.h @@ -29,12 +29,14 @@ class Client; struct shadowFrustum { - float zNear{0.0f}; - float zFar{0.0f}; - float length{0.0f}; + f32 zNear{0.0f}; + f32 zFar{0.0f}; + f32 length{0.0f}; + f32 radius{0.0f}; core::matrix4 ProjOrthMat; core::matrix4 ViewMat; v3f position; + v3f player; v3s16 camera_offset; }; @@ -57,6 +59,8 @@ public: return direction; }; v3f getPosition() const; + v3f getPlayerPos() const; + v3f getFuturePlayerPos() const; /// Gets the light's matrices. const core::matrix4 &getViewMatrix() const; diff --git a/src/client/shadows/dynamicshadowsrender.cpp b/src/client/shadows/dynamicshadowsrender.cpp index 262711221..1dfc90d1c 100644 --- a/src/client/shadows/dynamicshadowsrender.cpp +++ b/src/client/shadows/dynamicshadowsrender.cpp @@ -158,7 +158,6 @@ void ShadowRenderer::setShadowIntensity(float shadow_intensity) disable(); } - void ShadowRenderer::addNodeToShadowList( scene::ISceneNode *node, E_SHADOW_MODE shadowMode) { @@ -261,8 +260,9 @@ void ShadowRenderer::updateSMTextures() cb->MaxFar = (f32)m_shadow_map_max_distance * BS; cb->PerspectiveBiasXY = getPerspectiveBiasXY(); cb->PerspectiveBiasZ = getPerspectiveBiasZ(); + cb->CameraPos = light.getFuturePlayerPos(); } - + // set the Render Target // right now we can only render in usual RTT, not // Depth texture is available in irrlicth maybe we @@ -322,9 +322,10 @@ void ShadowRenderer::update(video::ITexture *outputTarget) if (!m_shadow_node_array.empty() && !m_light_list.empty()) { for (DirectionalLight &light : m_light_list) { - // Static shader values. - m_shadow_depth_cb->MapRes = (f32)m_shadow_map_texture_size; - m_shadow_depth_cb->MaxFar = (f32)m_shadow_map_max_distance * BS; + // Static shader values for entities are set in updateSMTextures + // SM texture for entities is not updated incrementally and + // must by updated using current player position. + m_shadow_depth_entity_cb->CameraPos = light.getPlayerPos(); // render shadows for the n0n-map objects. m_driver->setRenderTarget(shadowMapTextureDynamicObjects, true, diff --git a/src/client/shadows/shadowsshadercallbacks.cpp b/src/client/shadows/shadowsshadercallbacks.cpp index 51ea8aa93..b571ea939 100644 --- a/src/client/shadows/shadowsshadercallbacks.cpp +++ b/src/client/shadows/shadowsshadercallbacks.cpp @@ -26,6 +26,10 @@ void ShadowDepthShaderCB::OnSetConstants( core::matrix4 lightMVP = driver->getTransform(video::ETS_PROJECTION); lightMVP *= driver->getTransform(video::ETS_VIEW); + + f32 cam_pos[4]; + lightMVP.transformVect(cam_pos, CameraPos); + lightMVP *= driver->getTransform(video::ETS_WORLD); m_light_mvp_setting.set(lightMVP.pointer(), services); @@ -39,4 +43,6 @@ void ShadowDepthShaderCB::OnSetConstants( m_perspective_bias1.set(&bias1, services); f32 zbias = PerspectiveBiasZ; m_perspective_zbias.set(&zbias, services); + + m_cam_pos_setting.set(cam_pos, services); } diff --git a/src/client/shadows/shadowsshadercallbacks.h b/src/client/shadows/shadowsshadercallbacks.h index d00f59c37..87833c0ec 100644 --- a/src/client/shadows/shadowsshadercallbacks.h +++ b/src/client/shadows/shadowsshadercallbacks.h @@ -33,7 +33,8 @@ public: m_color_map_sampler_setting("ColorMapSampler"), m_perspective_bias0("xyPerspectiveBias0"), m_perspective_bias1("xyPerspectiveBias1"), - m_perspective_zbias("zPerspectiveBias") + m_perspective_zbias("zPerspectiveBias"), + m_cam_pos_setting("CameraPos") {} void OnSetMaterial(const video::SMaterial &material) override {} @@ -43,6 +44,7 @@ public: f32 MaxFar{2048.0f}, MapRes{1024.0f}; f32 PerspectiveBiasXY {0.9f}, PerspectiveBiasZ {0.5f}; + v3f CameraPos; private: CachedVertexShaderSetting m_light_mvp_setting; @@ -52,4 +54,5 @@ private: CachedVertexShaderSetting m_perspective_bias0; CachedVertexShaderSetting m_perspective_bias1; CachedVertexShaderSetting m_perspective_zbias; + CachedVertexShaderSetting m_cam_pos_setting; }; -- cgit v1.2.3 From a5d29fa1d4bc6849d7a6529edc522accac8219d2 Mon Sep 17 00:00:00 2001 From: x2048 Date: Thu, 14 Apr 2022 22:49:30 +0200 Subject: Implement shadow offsets for the new SM distortion function (#12191) * Move shadow position calculation to vertex shaders * Animate entire scene before rendering shadows to prevent lagging of shadows * Remove unnecessary use of PolygonOffsetFactor * Apply normal offset to both nodes and objects * Rename getPerspectiveFactor -> applyPerspectiveDistortion * Remove perspective distortion from fragment shaders --- client/shaders/nodes_shader/opengl_fragment.glsl | 36 +++-------- client/shaders/nodes_shader/opengl_vertex.glsl | 73 +++++++++++++++++----- client/shaders/object_shader/opengl_fragment.glsl | 35 +++-------- client/shaders/object_shader/opengl_vertex.glsl | 72 ++++++++++++++++----- .../shaders/shadow_shaders/pass1_trans_vertex.glsl | 31 ++++++--- client/shaders/shadow_shaders/pass1_vertex.glsl | 31 ++++++--- src/client/render/core.cpp | 5 +- src/client/shadows/dynamicshadows.h | 8 ++- src/client/shadows/dynamicshadowsrender.cpp | 13 +--- 9 files changed, 183 insertions(+), 121 deletions(-) (limited to 'src/client/shadows/dynamicshadowsrender.cpp') diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index fea350788..8110f6fd3 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -18,10 +18,13 @@ uniform float animationTimer; uniform float f_shadowfar; uniform float f_shadow_strength; uniform vec4 CameraPos; - varying float normalOffsetScale; + uniform float xyPerspectiveBias0; + uniform float xyPerspectiveBias1; + varying float adj_shadow_strength; varying float cosLight; varying float f_normal_length; + varying vec3 shadow_position; #endif @@ -45,24 +48,7 @@ varying float nightRatio; const float fogStart = FOG_START; const float fogShadingParameter = 1.0 / ( 1.0 - fogStart); - - #ifdef ENABLE_DYNAMIC_SHADOWS -uniform float xyPerspectiveBias0; -uniform float xyPerspectiveBias1; -uniform float zPerspectiveBias; - -vec4 getPerspectiveFactor(in vec4 shadowPosition) -{ - vec2 s = vec2(shadowPosition.x > CameraPos.x ? 1.0 : -1.0, shadowPosition.y > CameraPos.y ? 1.0 : -1.0); - vec2 l = s * (shadowPosition.xy - CameraPos.xy) / (1.0 - s * CameraPos.xy); - float pDistance = length(l); - float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; - l /= pFactor; - shadowPosition.xy = CameraPos.xy * (1.0 - l) + s * l; - shadowPosition.z *= zPerspectiveBias; - return shadowPosition; -} // assuming near is always 1.0 float getLinearDepth() @@ -72,15 +58,7 @@ float getLinearDepth() vec3 getLightSpacePosition() { - vec4 pLightSpace; - // some drawtypes have zero normals, so we need to handle it :( - #if DRAW_TYPE == NDT_PLANTLIKE - pLightSpace = m_ShadowViewProj * vec4(worldPosition, 1.0); - #else - pLightSpace = m_ShadowViewProj * vec4(worldPosition + normalOffsetScale * normalize(vNormal), 1.0); - #endif - pLightSpace = getPerspectiveFactor(pLightSpace); - return pLightSpace.xyz * 0.5 + 0.5; + return shadow_position * 0.5 + 0.5; } // custom smoothstep implementation because it's not defined in glsl1.2 // https://docs.gl/sl4/smoothstep @@ -499,14 +477,14 @@ void main(void) #ifdef COLORED_SHADOWS vec4 visibility; - if (cosLight > 0.0) + if (cosLight > 0.0 || f_normal_length < 1e-3) visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); else visibility = vec4(1.0, 0.0, 0.0, 0.0); shadow_int = visibility.r; shadow_color = visibility.gba; #else - if (cosLight > 0.0) + if (cosLight > 0.0 || f_normal_length < 1e-3) shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); else shadow_int = 1.0; diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 8c7e27459..3ea0faa36 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -32,10 +32,13 @@ centroid varying vec2 varTexCoord; uniform float f_shadowfar; uniform float f_shadow_strength; uniform float f_timeofday; + uniform vec4 CameraPos; + varying float cosLight; varying float normalOffsetScale; varying float adj_shadow_strength; varying float f_normal_length; + varying vec3 shadow_position; #endif @@ -47,8 +50,36 @@ const float e = 2.718281828459; const float BS = 10.0; uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias1; +uniform float zPerspectiveBias; #ifdef ENABLE_DYNAMIC_SHADOWS + +vec4 getRelativePosition(in vec4 position) +{ + vec2 l = position.xy - CameraPos.xy; + vec2 s = l / abs(l); + s = (1.0 - s * CameraPos.xy); + l /= s; + return vec4(l, s); +} + +float getPerspectiveFactor(in vec4 relativePosition) +{ + float pDistance = length(relativePosition.xy); + float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; + return pFactor; +} + +vec4 applyPerspectiveDistortion(in vec4 position) +{ + vec4 l = getRelativePosition(position); + float pFactor = getPerspectiveFactor(l); + l.xy /= pFactor; + position.xy = l.xy * l.zw + CameraPos.xy; + position.z *= zPerspectiveBias; + return position; +} + // custom smoothstep implementation because it's not defined in glsl1.2 // https://docs.gl/sl4/smoothstep float mtsmoothstep(in float edge0, in float edge1, in float x) @@ -196,21 +227,32 @@ void main(void) #ifdef ENABLE_DYNAMIC_SHADOWS if (f_shadow_strength > 0.0) { - vec3 nNormal = normalize(vNormal); - cosLight = dot(nNormal, -v_LightDirection); - - // Calculate normal offset scale based on the texel size adjusted for - // curvature of the SM texture. This code must be change together with - // getPerspectiveFactor or any light-space transformation. - vec3 eyeToVertex = worldPosition - eyePosition + cameraOffset; - // Distance from the vertex to the player - float distanceToPlayer = length(eyeToVertex - v_LightDirection * dot(eyeToVertex, v_LightDirection)) / f_shadowfar; - // perspective factor estimation according to the - float perspectiveFactor = distanceToPlayer * xyPerspectiveBias0 + xyPerspectiveBias1; - float texelSize = f_shadowfar * perspectiveFactor * perspectiveFactor / - (f_textureresolution * xyPerspectiveBias1 - perspectiveFactor * xyPerspectiveBias0); - float slopeScale = clamp(pow(1.0 - cosLight*cosLight, 0.5), 0.0, 1.0); - normalOffsetScale = texelSize * slopeScale; + vec3 nNormal; + f_normal_length = length(vNormal); + + /* normalOffsetScale is in world coordinates (1/10th of a meter) + z_bias is in light space coordinates */ + float normalOffsetScale, z_bias; + float pFactor = getPerspectiveFactor(getRelativePosition(m_ShadowViewProj * mWorld * inVertexPosition)); + if (f_normal_length > 0.0) { + nNormal = normalize(vNormal); + cosLight = dot(nNormal, -v_LightDirection); + float sinLight = pow(1 - pow(cosLight, 2.0), 0.5); + normalOffsetScale = 2.0 * pFactor * pFactor * sinLight * min(f_shadowfar, 500.0) / + xyPerspectiveBias1 / f_textureresolution; + z_bias = 1.0 * sinLight / cosLight; + } + else { + nNormal = vec3(0.0); + cosLight = clamp(dot(v_LightDirection, normalize(vec3(v_LightDirection.x, 0.0, v_LightDirection.z))), 1e-2, 1.0); + float sinLight = pow(1 - pow(cosLight, 2.0), 0.5); + normalOffsetScale = 0.0; + z_bias = 3.6e3 * sinLight / cosLight; + } + z_bias *= pFactor * pFactor / f_textureresolution / f_shadowfar; + + shadow_position = applyPerspectiveDistortion(m_ShadowViewProj * mWorld * (inVertexPosition + vec4(normalOffsetScale * nNormal, 0.0))).xyz; + shadow_position.z -= z_bias; if (f_timeofday < 0.2) { adj_shadow_strength = f_shadow_strength * 0.5 * @@ -223,7 +265,6 @@ void main(void) mtsmoothstep(0.20, 0.25, f_timeofday) * (1.0 - mtsmoothstep(0.7, 0.8, f_timeofday)); } - f_normal_length = length(vNormal); } #endif } diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 2611bf8ef..7baf5826f 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -19,10 +19,13 @@ uniform float animationTimer; uniform float f_shadowfar; uniform float f_shadow_strength; uniform vec4 CameraPos; - varying float normalOffsetScale; + uniform float xyPerspectiveBias0; + uniform float xyPerspectiveBias1; + varying float adj_shadow_strength; varying float cosLight; varying float f_normal_length; + varying vec3 shadow_position; #endif @@ -48,24 +51,7 @@ varying float vIDiff; const float fogStart = FOG_START; const float fogShadingParameter = 1.0 / (1.0 - fogStart); - - #ifdef ENABLE_DYNAMIC_SHADOWS -uniform float xyPerspectiveBias0; -uniform float xyPerspectiveBias1; -uniform float zPerspectiveBias; - -vec4 getPerspectiveFactor(in vec4 shadowPosition) -{ - vec2 s = vec2(shadowPosition.x > CameraPos.x ? 1.0 : -1.0, shadowPosition.y > CameraPos.y ? 1.0 : -1.0); - vec2 l = s * (shadowPosition.xy - CameraPos.xy) / (1.0 - s * CameraPos.xy); - float pDistance = length(l); - float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; - l /= pFactor; - shadowPosition.xy = CameraPos.xy * (1.0 - l) + s * l; - shadowPosition.z *= zPerspectiveBias; - return shadowPosition; -} // assuming near is always 1.0 float getLinearDepth() @@ -75,15 +61,7 @@ float getLinearDepth() vec3 getLightSpacePosition() { - vec4 pLightSpace; - // some drawtypes have zero normals, so we need to handle it :( - #if DRAW_TYPE == NDT_PLANTLIKE - pLightSpace = m_ShadowViewProj * vec4(worldPosition, 1.0); - #else - pLightSpace = m_ShadowViewProj * vec4(worldPosition + normalOffsetScale * normalize(vNormal), 1.0); - #endif - pLightSpace = getPerspectiveFactor(pLightSpace); - return pLightSpace.xyz * 0.5 + 0.5; + return shadow_position * 0.5 + 0.5; } // custom smoothstep implementation because it's not defined in glsl1.2 // https://docs.gl/sl4/smoothstep @@ -503,13 +481,14 @@ void main(void) #ifdef COLORED_SHADOWS vec4 visibility; - if (cosLight > 0.0) + if (cosLight > 0.0 || f_normal_length < 1e-3) visibility = getShadowColor(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); else visibility = vec4(1.0, 0.0, 0.0, 0.0); shadow_int = visibility.r; shadow_color = visibility.gba; #else + if (cosLight > 0.0 || f_normal_length < 1e-3) if (cosLight > 0.0) shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); else diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index 55861b0e9..6dc25f854 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -24,10 +24,12 @@ centroid varying vec2 varTexCoord; uniform float f_shadowfar; uniform float f_shadow_strength; uniform float f_timeofday; + uniform vec4 CameraPos; + varying float cosLight; - varying float normalOffsetScale; varying float adj_shadow_strength; varying float f_normal_length; + varying vec3 shadow_position; #endif varying vec3 eyeVec; @@ -39,8 +41,36 @@ const float e = 2.718281828459; const float BS = 10.0; uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias1; +uniform float zPerspectiveBias; #ifdef ENABLE_DYNAMIC_SHADOWS + +vec4 getRelativePosition(in vec4 position) +{ + vec2 l = position.xy - CameraPos.xy; + vec2 s = l / abs(l); + s = (1.0 - s * CameraPos.xy); + l /= s; + return vec4(l, s); +} + +float getPerspectiveFactor(in vec4 relativePosition) +{ + float pDistance = length(relativePosition.xy); + float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; + return pFactor; +} + +vec4 applyPerspectiveDistortion(in vec4 position) +{ + vec4 l = getRelativePosition(position); + float pFactor = getPerspectiveFactor(l); + l.xy /= pFactor; + position.xy = l.xy * l.zw + CameraPos.xy; + position.z *= zPerspectiveBias; + return position; +} + // custom smoothstep implementation because it's not defined in glsl1.2 // https://docs.gl/sl4/smoothstep float mtsmoothstep(in float edge0, in float edge1, in float x) @@ -107,20 +137,31 @@ void main(void) #ifdef ENABLE_DYNAMIC_SHADOWS if (f_shadow_strength > 0.0) { vec3 nNormal = normalize(vNormal); - cosLight = dot(nNormal, -v_LightDirection); - - // Calculate normal offset scale based on the texel size adjusted for - // curvature of the SM texture. This code must be change together with - // getPerspectiveFactor or any light-space transformation. - vec3 eyeToVertex = worldPosition - eyePosition + cameraOffset; - // Distance from the vertex to the player - float distanceToPlayer = length(eyeToVertex - v_LightDirection * dot(eyeToVertex, v_LightDirection)) / f_shadowfar; - // perspective factor estimation according to the - float perspectiveFactor = distanceToPlayer * xyPerspectiveBias0 + xyPerspectiveBias1; - float texelSize = f_shadowfar * perspectiveFactor * perspectiveFactor / - (f_textureresolution * xyPerspectiveBias1 - perspectiveFactor * xyPerspectiveBias0); - float slopeScale = clamp(pow(1.0 - cosLight*cosLight, 0.5), 0.0, 1.0); - normalOffsetScale = texelSize * slopeScale; + f_normal_length = length(vNormal); + + /* normalOffsetScale is in world coordinates (1/10th of a meter) + z_bias is in light space coordinates */ + float normalOffsetScale, z_bias; + float pFactor = getPerspectiveFactor(getRelativePosition(m_ShadowViewProj * mWorld * inVertexPosition)); + if (f_normal_length > 0.0) { + nNormal = normalize(vNormal); + cosLight = dot(nNormal, -v_LightDirection); + float sinLight = pow(1 - pow(cosLight, 2.0), 0.5); + normalOffsetScale = 0.1 * pFactor * pFactor * sinLight * min(f_shadowfar, 500.0) / + xyPerspectiveBias1 / f_textureresolution; + z_bias = 1e3 * sinLight / cosLight * (0.5 + f_textureresolution / 1024.0); + } + else { + nNormal = vec3(0.0); + cosLight = clamp(dot(v_LightDirection, normalize(vec3(v_LightDirection.x, 0.0, v_LightDirection.z))), 1e-2, 1.0); + float sinLight = pow(1 - pow(cosLight, 2.0), 0.5); + normalOffsetScale = 0.0; + z_bias = 3.6e3 * sinLight / cosLight; + } + z_bias *= pFactor * pFactor / f_textureresolution / f_shadowfar; + + shadow_position = applyPerspectiveDistortion(m_ShadowViewProj * mWorld * (inVertexPosition + vec4(normalOffsetScale * nNormal, 0.0))).xyz; + shadow_position.z -= z_bias; if (f_timeofday < 0.2) { adj_shadow_strength = f_shadow_strength * 0.5 * @@ -133,7 +174,6 @@ void main(void) mtsmoothstep(0.20, 0.25, f_timeofday) * (1.0 - mtsmoothstep(0.7, 0.8, f_timeofday)); } - f_normal_length = length(vNormal); } #endif } diff --git a/client/shaders/shadow_shaders/pass1_trans_vertex.glsl b/client/shaders/shadow_shaders/pass1_trans_vertex.glsl index c2f575876..244d2562a 100644 --- a/client/shaders/shadow_shaders/pass1_trans_vertex.glsl +++ b/client/shaders/shadow_shaders/pass1_trans_vertex.glsl @@ -9,24 +9,37 @@ uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias1; uniform float zPerspectiveBias; -vec4 getPerspectiveFactor(in vec4 shadowPosition) +vec4 getRelativePosition(in vec4 position) { - vec2 s = vec2(shadowPosition.x > CameraPos.x ? 1.0 : -1.0, shadowPosition.y > CameraPos.y ? 1.0 : -1.0); - vec2 l = s * (shadowPosition.xy - CameraPos.xy) / (1.0 - s * CameraPos.xy); - float pDistance = length(l); + vec2 l = position.xy - CameraPos.xy; + vec2 s = l / abs(l); + s = (1.0 - s * CameraPos.xy); + l /= s; + return vec4(l, s); +} + +float getPerspectiveFactor(in vec4 relativePosition) +{ + float pDistance = length(relativePosition.xy); float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; - l /= pFactor; - shadowPosition.xy = CameraPos.xy * (1.0 - l) + s * l; - shadowPosition.z *= zPerspectiveBias; - return shadowPosition; + return pFactor; } +vec4 applyPerspectiveDistortion(in vec4 position) +{ + vec4 l = getRelativePosition(position); + float pFactor = getPerspectiveFactor(l); + l.xy /= pFactor; + position.xy = l.xy * l.zw + CameraPos.xy; + position.z *= zPerspectiveBias; + return position; +} void main() { vec4 pos = LightMVP * gl_Vertex; - tPos = getPerspectiveFactor(LightMVP * gl_Vertex); + tPos = applyPerspectiveDistortion(LightMVP * gl_Vertex); gl_Position = vec4(tPos.xyz, 1.0); gl_TexCoord[0].st = gl_MultiTexCoord0.st; diff --git a/client/shaders/shadow_shaders/pass1_vertex.glsl b/client/shaders/shadow_shaders/pass1_vertex.glsl index 38aef3619..1dceb93c6 100644 --- a/client/shaders/shadow_shaders/pass1_vertex.glsl +++ b/client/shaders/shadow_shaders/pass1_vertex.glsl @@ -6,24 +6,37 @@ uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias1; uniform float zPerspectiveBias; -vec4 getPerspectiveFactor(in vec4 shadowPosition) +vec4 getRelativePosition(in vec4 position) { - vec2 s = vec2(shadowPosition.x > CameraPos.x ? 1.0 : -1.0, shadowPosition.y > CameraPos.y ? 1.0 : -1.0); - vec2 l = s * (shadowPosition.xy - CameraPos.xy) / (1.0 - s * CameraPos.xy); - float pDistance = length(l); + vec2 l = position.xy - CameraPos.xy; + vec2 s = l / abs(l); + s = (1.0 - s * CameraPos.xy); + l /= s; + return vec4(l, s); +} + +float getPerspectiveFactor(in vec4 relativePosition) +{ + float pDistance = length(relativePosition.xy); float pFactor = pDistance * xyPerspectiveBias0 + xyPerspectiveBias1; - l /= pFactor; - shadowPosition.xy = CameraPos.xy * (1.0 - l) + s * l; - shadowPosition.z *= zPerspectiveBias; - return shadowPosition; + return pFactor; } +vec4 applyPerspectiveDistortion(in vec4 position) +{ + vec4 l = getRelativePosition(position); + float pFactor = getPerspectiveFactor(l); + l.xy /= pFactor; + position.xy = l.xy * l.zw + CameraPos.xy; + position.z *= zPerspectiveBias; + return position; +} void main() { vec4 pos = LightMVP * gl_Vertex; - tPos = getPerspectiveFactor(pos); + tPos = applyPerspectiveDistortion(pos); gl_Position = vec4(tPos.xyz, 1.0); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; diff --git a/src/client/render/core.cpp b/src/client/render/core.cpp index c67f297c4..55cc4e490 100644 --- a/src/client/render/core.cpp +++ b/src/client/render/core.cpp @@ -76,8 +76,11 @@ void RenderingCore::draw(video::SColor _skycolor, bool _show_hud, bool _show_min draw_wield_tool = _draw_wield_tool; draw_crosshair = _draw_crosshair; - if (shadow_renderer) + if (shadow_renderer) { + // This is necessary to render shadows for animations correctly + smgr->getRootSceneNode()->OnAnimate(device->getTimer()->getTime()); shadow_renderer->update(); + } beforeDraw(); drawAll(); diff --git a/src/client/shadows/dynamicshadows.h b/src/client/shadows/dynamicshadows.h index 70574aa6c..6e9d96b15 100644 --- a/src/client/shadows/dynamicshadows.h +++ b/src/client/shadows/dynamicshadows.h @@ -69,12 +69,18 @@ public: const core::matrix4 &getFutureProjectionMatrix() const; core::matrix4 getViewProjMatrix(); - /// Gets the light's far value. + /// Gets the light's maximum far value, i.e. the shadow boundary f32 getMaxFarValue() const { return farPlane * BS; } + /// Gets the current far value of the light + f32 getFarValue() const + { + return shadow_frustum.zFar; + } + /// Gets the light's color. const video::SColorf &getLightColor() const diff --git a/src/client/shadows/dynamicshadowsrender.cpp b/src/client/shadows/dynamicshadowsrender.cpp index 1dfc90d1c..a008c3e06 100644 --- a/src/client/shadows/dynamicshadowsrender.cpp +++ b/src/client/shadows/dynamicshadowsrender.cpp @@ -143,7 +143,7 @@ size_t ShadowRenderer::getDirectionalLightCount() const f32 ShadowRenderer::getMaxShadowFar() const { if (!m_light_list.empty()) { - float zMax = m_light_list[0].getMaxFarValue(); + float zMax = m_light_list[0].getFarValue(); return zMax; } return 0.0f; @@ -418,10 +418,6 @@ void ShadowRenderer::renderShadowMap(video::ITexture *target, material.BackfaceCulling = false; material.FrontfaceCulling = true; - material.PolygonOffsetFactor = 4.0f; - material.PolygonOffsetDirection = video::EPO_BACK; - //material.PolygonOffsetDepthBias = 1.0f/4.0f; - //material.PolygonOffsetSlopeScale = -1.f; if (m_shadow_map_colored && pass != scene::ESNRP_SOLID) { material.MaterialType = (video::E_MATERIAL_TYPE) depth_shader_trans; @@ -431,9 +427,6 @@ void ShadowRenderer::renderShadowMap(video::ITexture *target, material.BlendOperation = video::EBO_MIN; } - // FIXME: I don't think this is needed here - map_node->OnAnimate(m_device->getTimer()->getTime()); - m_driver->setTransform(video::ETS_WORLD, map_node->getAbsoluteTransformation()); @@ -479,10 +472,6 @@ void ShadowRenderer::renderShadowObjects( current_mat.BackfaceCulling = true; current_mat.FrontfaceCulling = false; - current_mat.PolygonOffsetFactor = 1.0f/2048.0f; - current_mat.PolygonOffsetDirection = video::EPO_BACK; - //current_mat.PolygonOffsetDepthBias = 1.0 * 2.8e-6; - //current_mat.PolygonOffsetSlopeScale = -1.f; } m_driver->setTransform(video::ETS_WORLD, -- cgit v1.2.3 From a89afe1229e327da3c397a3912b2d43d2196ea2b Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 28 Apr 2022 20:53:15 +0200 Subject: Deal with compiler warnings --- src/client/client.h | 2 +- src/client/clientmap.h | 16 +++++++--------- src/client/content_cao.cpp | 2 +- src/client/content_cao.h | 2 +- src/client/game.cpp | 6 +++--- src/client/minimap.cpp | 2 +- src/client/shadows/dynamicshadowsrender.cpp | 6 ++++-- src/client/shadows/dynamicshadowsrender.h | 1 - src/database/database-postgresql.h | 3 ++- src/map.h | 14 +++++++------- src/network/connection.h | 2 +- src/network/socket.cpp | 4 ++-- 12 files changed, 30 insertions(+), 30 deletions(-) (limited to 'src/client/shadows/dynamicshadowsrender.cpp') diff --git a/src/client/client.h b/src/client/client.h index 0e29fdbe2..cb1227768 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -407,7 +407,7 @@ public: } ClientScripting *getScript() { return m_script; } - const bool modsLoaded() const { return m_mods_loaded; } + bool modsLoaded() const { return m_mods_loaded; } void pushToEventQueue(ClientEvent *event); diff --git a/src/client/clientmap.h b/src/client/clientmap.h index 7bd7af266..6d57f1911 100644 --- a/src/client/clientmap.h +++ b/src/client/clientmap.h @@ -81,9 +81,9 @@ public: return false; } - void drop() + void drop() override { - ISceneNode::drop(); + ISceneNode::drop(); // calls destructor } void updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset); @@ -91,24 +91,22 @@ public: /* Forcefully get a sector from somewhere */ - MapSector * emergeSector(v2s16 p); - - //void deSerializeSector(v2s16 p2d, std::istream &is); + MapSector * emergeSector(v2s16 p) override; /* ISceneNode methods */ - virtual void OnRegisterSceneNode(); + virtual void OnRegisterSceneNode() override; - virtual void render() + virtual void render() override { video::IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); renderMap(driver, SceneManager->getSceneNodeRenderPass()); } - virtual const aabb3f &getBoundingBox() const + virtual const aabb3f &getBoundingBox() const override { return m_box; } @@ -130,7 +128,7 @@ public: void renderPostFx(CameraMode cam_mode); // For debug printing - virtual void PrintInfo(std::ostream &out); + void PrintInfo(std::ostream &out) override; const MapDrawControl & getControl() const { return m_control; } f32 getWantedRange() const { return m_control.wanted_range; } diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 3c31d4a36..d89bb53b3 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -435,7 +435,7 @@ const v3f GenericCAO::getPosition() const return m_position; } -const bool GenericCAO::isImmortal() +bool GenericCAO::isImmortal() const { return itemgroup_get(getGroups(), "immortal"); } diff --git a/src/client/content_cao.h b/src/client/content_cao.h index 70f1557e1..783aa4199 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -172,7 +172,7 @@ public: inline const v3f &getRotation() const { return m_rotation; } - const bool isImmortal(); + bool isImmortal() const; inline const ObjectProperties &getProperties() const { return m_prop; } diff --git a/src/client/game.cpp b/src/client/game.cpp index 1290534eb..d21bdbe99 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1063,9 +1063,9 @@ bool Game::startup(bool *kill, void Game::run() { ProfilerGraph graph; - RunStats stats = { 0 }; - CameraOrientation cam_view_target = { 0 }; - CameraOrientation cam_view = { 0 }; + RunStats stats; + CameraOrientation cam_view_target = {}; + CameraOrientation cam_view = {}; FpsControl draw_times; f32 dtime; // in seconds diff --git a/src/client/minimap.cpp b/src/client/minimap.cpp index f26aa1c70..320621d91 100644 --- a/src/client/minimap.cpp +++ b/src/client/minimap.cpp @@ -304,7 +304,7 @@ void Minimap::setModeIndex(size_t index) data->mode = m_modes[index]; m_current_mode_index = index; } else { - data->mode = MinimapModeDef{MINIMAP_TYPE_OFF, gettext("Minimap hidden"), 0, 0, ""}; + data->mode = {MINIMAP_TYPE_OFF, gettext("Minimap hidden"), 0, 0, "", 0}; m_current_mode_index = 0; } diff --git a/src/client/shadows/dynamicshadowsrender.cpp b/src/client/shadows/dynamicshadowsrender.cpp index a008c3e06..07dc6daf2 100644 --- a/src/client/shadows/dynamicshadowsrender.cpp +++ b/src/client/shadows/dynamicshadowsrender.cpp @@ -31,10 +31,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "profiler.h" ShadowRenderer::ShadowRenderer(IrrlichtDevice *device, Client *client) : - m_device(device), m_smgr(device->getSceneManager()), - m_driver(device->getVideoDriver()), m_client(client), m_current_frame(0), + m_smgr(device->getSceneManager()), m_driver(device->getVideoDriver()), + m_client(client), m_current_frame(0), m_perspective_bias_xy(0.8), m_perspective_bias_z(0.5) { + (void) m_client; + m_shadows_supported = true; // assume shadows supported. We will check actual support in initialize m_shadows_enabled = true; diff --git a/src/client/shadows/dynamicshadowsrender.h b/src/client/shadows/dynamicshadowsrender.h index bbeb254b0..0e4ef6b70 100644 --- a/src/client/shadows/dynamicshadowsrender.h +++ b/src/client/shadows/dynamicshadowsrender.h @@ -109,7 +109,6 @@ private: void enable() { m_shadows_enabled = m_shadows_supported; } // a bunch of variables - IrrlichtDevice *m_device{nullptr}; scene::ISceneManager *m_smgr{nullptr}; video::IVideoDriver *m_driver{nullptr}; Client *m_client{nullptr}; diff --git a/src/database/database-postgresql.h b/src/database/database-postgresql.h index 81b4a2b10..0a9ead01e 100644 --- a/src/database/database-postgresql.h +++ b/src/database/database-postgresql.h @@ -94,7 +94,8 @@ protected: checkResults(PQprepare(m_conn, name.c_str(), sql.c_str(), 0, NULL)); } - const int getPGVersion() const { return m_pgversion; } + int getPGVersion() const { return m_pgversion; } + private: // Database connectivity checks void ping(); diff --git a/src/map.h b/src/map.h index 9dc7a101c..d8ed29106 100644 --- a/src/map.h +++ b/src/map.h @@ -327,7 +327,7 @@ public: - Create blank filled with CONTENT_IGNORE */ - MapBlock *emergeBlock(v3s16 p, bool create_blank=true); + MapBlock *emergeBlock(v3s16 p, bool create_blank=true) override; /* Try to get a block. @@ -349,27 +349,27 @@ public: static MapDatabase *createDatabase(const std::string &name, const std::string &savedir, Settings &conf); // Call these before and after saving of blocks - void beginSave(); - void endSave(); + void beginSave() override; + void endSave() override; - void save(ModifiedState save_level); + void save(ModifiedState save_level) override; void listAllLoadableBlocks(std::vector &dst); void listAllLoadedBlocks(std::vector &dst); MapgenParams *getMapgenParams(); - bool saveBlock(MapBlock *block); + bool saveBlock(MapBlock *block) override; static bool saveBlock(MapBlock *block, MapDatabase *db, int compression_level = -1); MapBlock* loadBlock(v3s16 p); // Database version void loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load=false); - bool deleteBlock(v3s16 blockpos); + bool deleteBlock(v3s16 blockpos) override; void updateVManip(v3s16 pos); // For debug printing - virtual void PrintInfo(std::ostream &out); + void PrintInfo(std::ostream &out) override; bool isSavingEnabled(){ return m_map_saving_enabled; } diff --git a/src/network/connection.h b/src/network/connection.h index 88e323bb1..b5ae24882 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -194,7 +194,7 @@ struct BufferedPacket { u16 getSeqnum() const; - inline const size_t size() const { return m_data.size(); } + inline size_t size() const { return m_data.size(); } u8 *data; // Direct memory access float time = 0.0f; // Seconds from buffering the packet or re-sending diff --git a/src/network/socket.cpp b/src/network/socket.cpp index 0bb7ea234..97a5f19f7 100644 --- a/src/network/socket.cpp +++ b/src/network/socket.cpp @@ -231,7 +231,7 @@ void UDPSocket::Send(const Address &destination, const void *data, int size) int sent; if (m_addr_family == AF_INET6) { - struct sockaddr_in6 address = {0}; + struct sockaddr_in6 address = {}; address.sin6_family = AF_INET6; address.sin6_addr = destination.getAddress6(); address.sin6_port = htons(destination.getPort()); @@ -239,7 +239,7 @@ void UDPSocket::Send(const Address &destination, const void *data, int size) sent = sendto(m_handle, (const char *)data, size, 0, (struct sockaddr *)&address, sizeof(struct sockaddr_in6)); } else { - struct sockaddr_in address = {0}; + struct sockaddr_in address = {}; address.sin_family = AF_INET; address.sin_addr = destination.getAddress(); address.sin_port = htons(destination.getPort()); -- cgit v1.2.3