From ded1b0983842c814f542bae95308feccea2f0ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Thu, 9 May 2024 18:38:29 +0200 Subject: [PATCH 01/40] Add artificial light control --- client/shaders/nodes_shader/opengl_vertex.glsl | 4 ++-- client/shaders/object_shader/opengl_vertex.glsl | 4 ++-- src/client/game.cpp | 3 +++ src/lighting.h | 3 +++ src/network/clientpackethandler.cpp | 2 ++ src/network/networkprotocol.h | 1 + src/script/lua_api/l_object.cpp | 9 +++++++++ src/server.cpp | 2 ++ 8 files changed, 24 insertions(+), 4 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index d96164d76..2c1e5981b 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -46,7 +46,7 @@ varying float area_enable_parallax; varying highp vec3 eyeVec; varying float nightRatio; // Color of the light emitted by the light sources. -const vec3 artificialLight = vec3(1.04, 1.04, 1.04); +uniform vec3 artificialLight; const float e = 2.718281828459; const float BS = 10.0; uniform float xyPerspectiveBias0; @@ -211,7 +211,7 @@ void main(void) // The alpha gives the ratio of sunlight in the incoming light. nightRatio = 1.0 - color.a; color.rgb = color.rgb * (color.a * dayLight.rgb + - nightRatio * artificialLight.rgb) * 2.0; + nightRatio * 2.0 * artificialLight.rgb) * 2.0; color.a = 1.0; // Emphase blue a bit in darker places diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index d5a434da5..53f487a56 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -33,7 +33,7 @@ centroid varying vec2 varTexCoord; varying highp vec3 eyeVec; varying float nightRatio; // Color of the light emitted by the light sources. -const vec3 artificialLight = vec3(1.04, 1.04, 1.04); +uniform vec3 artificialLight; varying float vIDiff; const float e = 2.718281828459; const float BS = 10.0; @@ -120,7 +120,7 @@ void main(void) // The alpha gives the ratio of sunlight in the incoming light. nightRatio = 1.0 - color.a; color.rgb = color.rgb * (color.a * dayLight.rgb + - nightRatio * artificialLight.rgb) * 2.0; + nightRatio * 2.0 * artificialLight.rgb) * 2.0; color.a = 1.0; // Emphase blue a bit in darker places diff --git a/src/client/game.cpp b/src/client/game.cpp index 01739ff25..8c1fb407f 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -381,6 +381,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter m_animation_timer_delta_vertex{"animationTimerDelta"}; CachedPixelShaderSetting m_animation_timer_delta_pixel{"animationTimerDelta"}; + CachedPixelShaderSetting m_artificial_light{ "artificialLight" }; CachedPixelShaderSetting m_day_light{"dayLight"}; CachedPixelShaderSetting m_minimap_yaw{"yawVec"}; CachedPixelShaderSetting m_camera_offset_pixel{"cameraOffset"}; @@ -525,6 +526,8 @@ public: const auto &lighting = m_client->getEnv().getLocalPlayer()->getLighting(); float saturation = lighting.saturation; m_saturation_pixel.set(&saturation, services); + video::SColorf artificial_light = lighting.artificial_light_color; + m_artificial_light.set(artificial_light, services); if (m_volumetric_light_enabled) { // Map directional light to screen space diff --git a/src/lighting.h b/src/lighting.h index 262a48b5d..2a324cff4 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -18,7 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #pragma once +#include +using namespace irr; /** * Parameters for automatic exposure compensation @@ -54,4 +56,5 @@ struct Lighting float shadow_intensity {0.0f}; float saturation {1.0f}; float volumetric_light_strength {0.0f}; + video::SColor artificial_light_color{ 133, 133, 133, 255 }; }; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 90f2bed5b..9fb0c56ad 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1815,4 +1815,6 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt) } if (pkt->getRemainingBytes() >= 4) *pkt >> lighting.volumetric_light_strength; + if (pkt->getRemainingBytes() >= 4) + *pkt >> lighting.artificial_light_color; } diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 4d9900ea0..fbe8eb8be 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -224,6 +224,7 @@ with this program; if not, write to the Free Software Foundation, Inc., Add TOCLIENT_MOVE_PLAYER_REL Move default minimap from client-side C++ to server-side builtin Lua [scheduled bump for 5.9.0] + Add artificial light color packet */ #define LATEST_PROTOCOL_VERSION 44 diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index bc5ddba5c..1246ae104 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2528,6 +2528,13 @@ int ObjectRef::l_set_lighting(lua_State *L) if (!lua_isnoneornil(L, 2)) { luaL_checktype(L, 2, LUA_TTABLE); lighting = player->getLighting(); + + lua_getfield(L, 2, "artificial_light"); + if (!lua_isnil(L, -1)) { + read_color(L, -1, &lighting.artificial_light_color); + } + lua_pop(L, 1); // artificial_light + lua_getfield(L, 2, "shadows"); if (lua_istable(L, -1)) { getfloatfield(L, -1, "intensity", lighting.shadow_intensity); @@ -2571,6 +2578,8 @@ int ObjectRef::l_get_lighting(lua_State *L) const Lighting &lighting = player->getLighting(); lua_newtable(L); // result + push_ARGB8(L, lighting.artificial_light_color); + lua_setfield(L, -2, "artificial_light"); lua_newtable(L); // "shadows" lua_pushnumber(L, lighting.shadow_intensity); lua_setfield(L, -2, "intensity"); diff --git a/src/server.cpp b/src/server.cpp index 6e12017bc..8ae194988 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1895,6 +1895,8 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) pkt << lighting.volumetric_light_strength; + pkt << lighting.artificial_light_color; + Send(&pkt); } From ca4f04ecab64b78cc8861a05a0212ef897ec0afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 12 May 2024 14:44:13 +0200 Subject: [PATCH 02/40] Lots of changes some redundant stuff in vertex shaders needs fixing --- builtin/settingtypes.txt | 24 +++++++ .../shaders/nodes_shader/opengl_fragment.glsl | 68 +++++++++++++++++-- .../shaders/nodes_shader/opengl_vertex.glsl | 12 ++-- .../shaders/object_shader/opengl_vertex.glsl | 12 ++-- .../shaders/second_stage/opengl_fragment.glsl | 18 ++++- src/client/game.cpp | 12 +++- src/client/shader.cpp | 9 +++ src/defaultsettings.cpp | 4 ++ src/lighting.h | 2 +- 9 files changed, 138 insertions(+), 23 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 11dfbf128..b02d5f2ef 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -611,6 +611,23 @@ enable_auto_exposure (Enable Automatic Exposure) bool false # Requires: shaders, enable_post_processing, enable_auto_exposure exposure_compensation (Exposure compensation) float 0.0 -1.0 1.0 +# Set the gamma value. +# Higher values give lower contrast and vice versa. +# Range: from 1.0 to 5.0 +# +# Requires: shaders, enable_post_processing, tone_mapping +gamma (Gamma) float 1.6 1.0 5.0 + +# Apply color grading to make brighter colors warmer and darker colors cooler. +# +# Requires: shaders, enable_post_processing +enable_color_grading (Color grading) bool false + +# Apply vignette effect to darken the edges of the screen. +# +# Requires: shaders, enable_post_processing +enable_vignette (Vignette) bool false + # Apply dithering to reduce color banding artifacts. # Dithering significantly increases the size of losslessly-compressed # screenshots and it works incorrectly if the display or operating system @@ -663,6 +680,13 @@ bloom_radius (Bloom Radius) float 1 0.1 8 # Requires: shaders, enable_post_processing, enable_bloom enable_volumetric_lighting (Volumetric lighting) bool false +[**Other Effects] + +# Apply bump maps to nodes based on their textures. It is recommended to use a tilted sun orbit to go with this (Sky Body Orbit Tilt). +# +# Requires: shaders, enable_dynamic_shadows +enable_bumpmaps (Bump maps) bool false + [*Audio] # Volume of all sounds. diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 46977b147..cc3af027c 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -1,4 +1,12 @@ +#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_OPAQUE || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_BASIC || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT) +#define MATERIAL_WAVING_LIQUID 1 +#define MATERIAL_LIQUID 1 +#elif (MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) +#define MATERIAL_LIQUID 1 +#endif + uniform sampler2D baseTexture; +uniform vec2 texelSize0; uniform vec3 dayLight; uniform lowp vec4 fogColor; @@ -48,6 +56,36 @@ varying float nightRatio; #ifdef ENABLE_DYNAMIC_SHADOWS +#ifdef ENABLE_BUMPMAPS +vec4 perm(vec4 x) +{ + return mod(((x * 34.0) + 1.0) * x, 289.0); +} + +float snoise(vec3 p) +{ + vec3 a = floor(p); + vec3 d = p - a; + d = d * d * (3.0 - 2.0 * d); + + vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0); + vec4 k1 = perm(b.xyxy); + vec4 k2 = perm(k1.xyxy + b.zzww); + + vec4 c = k2 + a.zzzz; + vec4 k3 = perm(c); + vec4 k4 = perm(c + 1.0); + + vec4 o1 = fract(k3 * (1.0 / 41.0)); + vec4 o2 = fract(k4 * (1.0 / 41.0)); + + vec4 o3 = o2 * d.z + o1 * (1.0 - d.z); + vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x); + + return o4.y * d.y + o4.x * (1.0 - d.y); +} +#endif + // assuming near is always 1.0 float getLinearDepth() { @@ -378,6 +416,26 @@ void main(void) vec4 col = vec4(color.rgb * varColor.rgb, 1.0); #ifdef ENABLE_DYNAMIC_SHADOWS + // Fragment normal, can differ from vNormal which is derived from vertex normals. + vec3 fNormal = vNormal; + +#if (defined(ENABLE_BUMPMAPS) && !defined(MATERIAL_LIQUID)) + vec2 dr = vec2(0.25) * texelSize0; + // Sample the texture to then compute the derivative + float fx0y0 = texture2D(baseTexture, uv).r; + float fx1y0 = texture2D(baseTexture, uv + vec2(dr.x, 0.0)).r; + float fx0y1 = texture2D(baseTexture, uv + vec2(0.0, dr.y)).r; + // Compute a set of orthogonal basis vectors representing the node's surface plane. + vec3 orth1 = normalize(cross(vNormal, mix(vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, -1.0), step(0.9, abs(vNormal.y))))); + vec3 orth2 = normalize(cross(vNormal, orth1)); + // The normal is computed using the partial derivatives along the texture space x and y axes. + // These axes in world space are assumed to be parallel to the basis vectors we defined before. + fNormal = normalize(vNormal + (orth1 * (fx1y0 - fx0y0) / dr.x + orth2 * (fx0y1 - fx0y0) / dr.y) * 0.25 * snoise(vec3(uv / texelSize0, 0.0))); + float adj_cosLight = max(1e-5, dot(fNormal, -v_LightDirection)); +#else + float adj_cosLight = cosLight; +#endif + if (f_shadow_strength > 0.0) { float shadow_int = 0.0; vec3 shadow_color = vec3(0.0, 0.0, 0.0); @@ -392,14 +450,14 @@ void main(void) #ifdef COLORED_SHADOWS vec4 visibility; - if (cosLight > 0.0 || f_normal_length < 1e-3) + if (adj_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 (adj_cosLight > 0.0 || f_normal_length < 1e-3) shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); else shadow_int = 1.0; @@ -417,9 +475,9 @@ void main(void) // 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); + if (f_normal_length != 0 && adj_cosLight < self_shadow_cutoff_cosine) { + shadow_int = max(shadow_int, 1 - clamp(adj_cosLight, 0.0, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); + shadow_color = mix(vec3(0.0), shadow_color, min(adj_cosLight, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); } shadow_int *= f_adj_shadow_strength; diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 2c1e5981b..415c51c29 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -259,16 +259,16 @@ void main(void) shadow_position.z -= z_bias; perspective_factor = pFactor; - if (f_timeofday < 0.2) { + if (f_timeofday < 0.21) { adj_shadow_strength = f_shadow_strength * 0.5 * - (1.0 - mtsmoothstep(0.18, 0.2, f_timeofday)); - } else if (f_timeofday >= 0.8) { + (1.0 - mtsmoothstep(0.18, 0.21, f_timeofday)); + } else if (f_timeofday >= 0.793) { adj_shadow_strength = f_shadow_strength * 0.5 * - mtsmoothstep(0.8, 0.83, f_timeofday); + mtsmoothstep(0.793, 0.823, 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)); + mtsmoothstep(0.21, 0.26, f_timeofday) * + (1.0 - mtsmoothstep(0.743, 0.793, f_timeofday)); } } #endif diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index 53f487a56..1cefb13fa 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -162,16 +162,16 @@ void main(void) shadow_position.z -= z_bias; perspective_factor = pFactor; - if (f_timeofday < 0.2) { + if (f_timeofday < 0.21) { adj_shadow_strength = f_shadow_strength * 0.5 * - (1.0 - mtsmoothstep(0.18, 0.2, f_timeofday)); - } else if (f_timeofday >= 0.8) { + (1.0 - mtsmoothstep(0.18, 0.21, f_timeofday)); + } else if (f_timeofday >= 0.793) { adj_shadow_strength = f_shadow_strength * 0.5 * - mtsmoothstep(0.8, 0.83, f_timeofday); + mtsmoothstep(0.793, 0.823, 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)); + mtsmoothstep(0.21, 0.26, f_timeofday) * + (1.0 - mtsmoothstep(0.743, 0.793, f_timeofday)); } } #endif diff --git a/client/shaders/second_stage/opengl_fragment.glsl b/client/shaders/second_stage/opengl_fragment.glsl index 3b0d4c844..f68310844 100644 --- a/client/shaders/second_stage/opengl_fragment.glsl +++ b/client/shaders/second_stage/opengl_fragment.glsl @@ -20,6 +20,7 @@ uniform vec2 texelSize0; uniform ExposureParams exposureParams; uniform lowp float bloomIntensity; uniform lowp float saturation; +uniform float gamma; #ifdef GL_ES varying mediump vec2 varTexCoord; @@ -69,7 +70,6 @@ vec3 uncharted2Tonemap(vec3 x) vec4 applyToneMapping(vec4 color) { color = vec4(pow(color.rgb, vec3(2.2)), color.a); - const float gamma = 1.6; const float exposureBias = 5.5; color.rgb = uncharted2Tonemap(exposureBias * color.rgb); // Precalculated white_scale from @@ -102,6 +102,11 @@ vec3 screen_space_dither(highp vec2 frag_coord) { } #endif +float sFunction(float x, float a) { + x = 2.0 * x - 1.0; + return 0.5 * sign(x) * pow(abs(x), a) + 0.5; +} + void main(void) { vec2 uv = varTexCoord.st; @@ -131,8 +136,6 @@ void main(void) #ifdef ENABLE_BLOOM color = applyBloom(color, uv); #endif - - color.rgb = clamp(color.rgb, vec3(0.), vec3(1.)); // return to sRGB colorspace (approximate) @@ -142,6 +145,15 @@ void main(void) if (uv.x > 0.5 || uv.y > 0.5) #endif { + +#ifdef ENABLE_VIGNETTE + color.rgb *= 0.8 * pow(1.0 - length(uv - vec2(0.5)) * 1.4, 0.9) + 0.3; +#endif + +#ifdef ENABLE_COLOR_GRADING + color.rgb = pow(color.rgb * vec3(1.3, 1.0, 0.8), vec3(1.3, 1.0, 0.9)); +#endif + #if ENABLE_TONE_MAPPING color = applyToneMapping(color); #endif diff --git a/src/client/game.cpp b/src/client/game.cpp index 8c1fb407f..c38a92483 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -409,6 +409,8 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_bloom_radius_pixel{"bloomRadius"}; float m_bloom_radius; CachedPixelShaderSetting m_saturation_pixel{"saturation"}; + float m_gamma; + CachedPixelShaderSetting m_gamma_pixel{"gamma"}; bool m_volumetric_light_enabled; CachedPixelShaderSetting m_sun_position_pixel{"sunPositionScreen"}; @@ -419,11 +421,12 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_volumetric_light_strength_pixel{"volumetricLightStrength"}; - static constexpr std::array SETTING_CALLBACKS = { + static constexpr std::array SETTING_CALLBACKS = { "exposure_compensation", "bloom_intensity", "bloom_strength_factor", - "bloom_radius" + "bloom_radius", + "gamma" }; public: @@ -437,6 +440,8 @@ public: m_bloom_strength = RenderingEngine::BASE_BLOOM_STRENGTH * g_settings->getFloat("bloom_strength_factor", 0.1f, 10.0f); if (name == "bloom_radius") m_bloom_radius = g_settings->getFloat("bloom_radius", 0.1f, 8.0f); + if (name == "gamma") + m_gamma = g_settings->getFloat("gamma", 1.0f, 5.0f); } static void settingsCallback(const std::string &name, void *userdata) @@ -458,6 +463,7 @@ public: m_bloom_intensity = g_settings->getFloat("bloom_intensity", 0.01f, 1.0f); m_bloom_strength = RenderingEngine::BASE_BLOOM_STRENGTH * g_settings->getFloat("bloom_strength_factor", 0.1f, 10.0f); m_bloom_radius = g_settings->getFloat("bloom_radius", 0.1f, 8.0f); + m_gamma = g_settings->getFloat("gamma", 1.0f, 5.0f); m_volumetric_light_enabled = g_settings->getBool("enable_volumetric_lighting") && m_bloom_enabled; } @@ -523,6 +529,8 @@ public: m_bloom_strength_pixel.set(&m_bloom_strength, services); } + m_gamma_pixel.set(&m_gamma, services); + const auto &lighting = m_client->getEnv().getLocalPlayer()->getLighting(); float saturation = lighting.saturation; m_saturation_pixel.set(&saturation, services); diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 3c7aeac39..0f80d9ab5 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -688,6 +688,9 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, if (g_settings->getBool("shadow_poisson_filter")) shaders_header << "#define POISSON_FILTER 1\n"; + if (g_settings->getBool("enable_bumpmaps")) + shaders_header << "#define ENABLE_BUMPMAPS 1\n"; + s32 shadow_filter = g_settings->getS32("shadow_filters"); shaders_header << "#define SHADOW_FILTER " << shadow_filter << "\n"; @@ -706,6 +709,12 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, if (g_settings->getBool("enable_auto_exposure")) shaders_header << "#define ENABLE_AUTO_EXPOSURE 1\n"; + if (g_settings->getBool("enable_color_grading")) + shaders_header << "#define ENABLE_COLOR_GRADING 1\n"; + + if (g_settings->getBool("enable_vignette")) + shaders_header << "#define ENABLE_VIGNETTE 1\n"; + if (g_settings->get("antialiasing") == "ssaa") { shaders_header << "#define ENABLE_SSAA 1\n"; u16 ssaa_scale = MYMAX(2, g_settings->getU16("fsaa")); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 3e62a79e5..6675c3661 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -331,6 +331,9 @@ void set_default_settings() settings->setDefault("enable_waving_plants", "false"); settings->setDefault("exposure_compensation", "0.0"); settings->setDefault("enable_auto_exposure", "false"); + settings->setDefault("enable_color_grading", "false"); + settings->setDefault("enable_vignette", "false"); + settings->setDefault("gamma", "1.6"); settings->setDefault("debanding", "true"); settings->setDefault("antialiasing", "none"); settings->setDefault("enable_bloom", "false"); @@ -339,6 +342,7 @@ void set_default_settings() settings->setDefault("bloom_intensity", "0.05"); settings->setDefault("bloom_radius", "1"); settings->setDefault("enable_volumetric_lighting", "false"); + settings->setDefault("enable_bumpmaps", "false"); // Effects Shadows settings->setDefault("enable_dynamic_shadows", "false"); diff --git a/src/lighting.h b/src/lighting.h index 2a324cff4..991dd6d31 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -56,5 +56,5 @@ struct Lighting float shadow_intensity {0.0f}; float saturation {1.0f}; float volumetric_light_strength {0.0f}; - video::SColor artificial_light_color{ 133, 133, 133, 255 }; + video::SColor artificial_light_color{ 255, 133, 133, 133 }; }; From 415f6b6bdb56070a0481119d060fcde9a18986d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Wed, 22 May 2024 21:05:26 +0200 Subject: [PATCH 03/40] Update opengl_fragment.glsl --- client/shaders/second_stage/opengl_fragment.glsl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/client/shaders/second_stage/opengl_fragment.glsl b/client/shaders/second_stage/opengl_fragment.glsl index f68310844..99af6c618 100644 --- a/client/shaders/second_stage/opengl_fragment.glsl +++ b/client/shaders/second_stage/opengl_fragment.glsl @@ -150,14 +150,20 @@ void main(void) color.rgb *= 0.8 * pow(1.0 - length(uv - vec2(0.5)) * 1.4, 0.9) + 0.3; #endif -#ifdef ENABLE_COLOR_GRADING - color.rgb = pow(color.rgb * vec3(1.3, 1.0, 0.8), vec3(1.3, 1.0, 0.9)); -#endif - #if ENABLE_TONE_MAPPING color = applyToneMapping(color); #endif +#ifdef ENABLE_COLOR_GRADING + // ASC CDL color grading + const vec3 slope = vec3(1.2, 1.0, 0.8); + const vec3 power = vec3(1.25, 1.0, 0.9); + + // Filter out blue pixels, because the color grading tends to wash them out. + float blue_factor = clamp((color.b - max(color.r, color.g)) / max(0.01, min(color.r, color.g)), 0.0, 1.0); + + color.rgb = mix(color.rgb, pow(color.rgb * slope, power), pow(1. - blue_factor, 4.)); +#endif color.rgb = applySaturation(color.rgb, saturation); } From a1b4e66c4ce221f1d3585167941202b3867da69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Tue, 11 Jun 2024 12:50:12 +0200 Subject: [PATCH 04/40] Stuff for volumetric clouds --- src/client/client.h | 5 +++++ src/client/clouds.cpp | 7 +++++++ src/client/clouds.h | 4 ++++ src/client/game.cpp | 1 + src/client/render/plain.cpp | 5 +++++ 5 files changed, 22 insertions(+) diff --git a/src/client/client.h b/src/client/client.h index b2ff9a0da..7918e6d90 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gameparams.h" #include "clientdynamicinfo.h" #include "util/numeric.h" +#include "clouds.h" #ifdef SERVER #error Do not include in server builds @@ -373,6 +374,9 @@ public: Camera* getCamera () { return m_camera; } scene::ISceneManager *getSceneManager(); + Clouds* getClouds() { return m_clouds; } + void setClouds(Clouds* clouds) { m_clouds = clouds; } + // IGameDef interface IItemDefManager* getItemDefManager() override; const NodeDefManager* getNodeDefManager() override; @@ -498,6 +502,7 @@ private: ELoginRegister m_allow_login_or_register = ELoginRegister::Any; Camera *m_camera = nullptr; Minimap *m_minimap = nullptr; + Clouds *m_clouds = nullptr; // Server serialization version u8 m_server_ser_ver; diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 3ab504371..adfdbf842 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -396,6 +396,13 @@ void Clouds::render() fog_pixelfog, fog_rangefog); } +void Clouds::renderVolumetrics() { + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + v2u32 ss = driver->getScreenSize(); + core::rect rect(0, 0, ss.X, ss.Y); + driver->draw2DRectangle(video::SColor(255, 255, 255, 255), rect); +} + void Clouds::step(float dtime) { m_origin = m_origin + dtime * BS * m_params.speed; diff --git a/src/client/clouds.h b/src/client/clouds.h index 23273a3c9..7676136b2 100644 --- a/src/client/clouds.h +++ b/src/client/clouds.h @@ -52,6 +52,8 @@ public: virtual void render(); + void renderVolumetrics(); + virtual const aabb3f &getBoundingBox() const { return m_box; @@ -145,6 +147,8 @@ private: bool gridFilled(int x, int y) const; + video::SMaterial m_volume_material; + video::SMaterial m_material; irr_ptr m_meshbuffer; // Value of m_origin at the time the mesh was last updated diff --git a/src/client/game.cpp b/src/client/game.cpp index c38a92483..9ebe7b3f1 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1516,6 +1516,7 @@ bool Game::createClient(const GameStartData &start_data) */ if (m_cache_enable_clouds) clouds = new Clouds(smgr, shader_src, -1, rand()); + client->setClouds(clouds); /* Skybox */ diff --git a/src/client/render/plain.cpp b/src/client/render/plain.cpp index 60a732415..fb8bcec70 100644 --- a/src/client/render/plain.cpp +++ b/src/client/render/plain.cpp @@ -66,6 +66,11 @@ void DrawHUD::run(PipelineContext &context) context.client->getCamera()->drawNametags(); } context.device->getGUIEnvironment()->drawAll(); + + // TODO: proper settings + if (true && context.client->getClouds()) { + context.client->getClouds()->renderVolumetrics(); + } } From 22ba7449f2de4ec0a5a9474d0b6951e2a63e4c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Fri, 5 Jul 2024 12:15:22 +0200 Subject: [PATCH 05/40] Volumetric effects --- .../shaders/clouds_merge/opengl_fragment.glsl | 44 +++++ .../shaders/clouds_merge/opengl_vertex.glsl | 7 + .../coarse_noise_shader/opengl_fragment.glsl | 17 ++ .../coarse_noise_shader/opengl_vertex.glsl | 4 + .../shaders/noise_shader/opengl_fragment.glsl | 15 ++ .../shaders/noise_shader/opengl_vertex.glsl | 4 + .../shaders/second_stage/opengl_fragment.glsl | 2 +- .../volumetric_clouds/opengl_fragment.glsl | 182 ++++++++++++++++++ .../volumetric_clouds/opengl_vertex.glsl | 17 ++ src/client/clouds.cpp | 10 +- src/client/clouds.h | 16 +- src/client/game.cpp | 45 +++++ src/client/render/plain.cpp | 5 - src/client/render/secondstage.cpp | 120 +++++++++++- src/client/render/secondstage.h | 3 + 15 files changed, 468 insertions(+), 23 deletions(-) create mode 100644 client/shaders/clouds_merge/opengl_fragment.glsl create mode 100644 client/shaders/clouds_merge/opengl_vertex.glsl create mode 100644 client/shaders/coarse_noise_shader/opengl_fragment.glsl create mode 100644 client/shaders/coarse_noise_shader/opengl_vertex.glsl create mode 100644 client/shaders/noise_shader/opengl_fragment.glsl create mode 100644 client/shaders/noise_shader/opengl_vertex.glsl create mode 100644 client/shaders/volumetric_clouds/opengl_fragment.glsl create mode 100644 client/shaders/volumetric_clouds/opengl_vertex.glsl diff --git a/client/shaders/clouds_merge/opengl_fragment.glsl b/client/shaders/clouds_merge/opengl_fragment.glsl new file mode 100644 index 000000000..c88f0d95a --- /dev/null +++ b/client/shaders/clouds_merge/opengl_fragment.glsl @@ -0,0 +1,44 @@ +#define cloudsTexture texture0 +#define sceneTexture texture1 + +uniform sampler2D cloudsTexture; +uniform sampler2D sceneTexture; +uniform vec2 texelSize0; + +uniform vec3 dayLight; + +varying vec2 screenspaceCoordinate; + +vec4 sampleClouds(vec2 uv) { + vec4 cloudsKey = texture2D(cloudsTexture, uv); + + const vec3 darkColor = vec3(0.05, 0.1, 0.2); + const vec3 auroraDark = vec3(0., 0.5, 0.5); + const vec3 auroraBright = vec3(0., 0.5, .0); + + return vec4( + mix(auroraDark, auroraBright, cloudsKey.b) * cloudsKey.b * max(0., 1. - cloudsKey.r) + + cloudsKey.r * (darkColor * max(0., 1. - cloudsKey.g) + dayLight * cloudsKey.g), + cloudsKey.r); +} + +vec4 getClouds(vec2 uv) { + return + sampleClouds(uv - texelSize0 * vec2(-1.0, -1.0)) / 9.0 + + sampleClouds(uv - texelSize0 * vec2( 0.0, -1.0)) / 9.0 + + sampleClouds(uv - texelSize0 * vec2( 1.0, -1.0)) / 9.0 + + sampleClouds(uv - texelSize0 * vec2(-1.0, 0.0)) / 9.0 + + sampleClouds(uv - texelSize0 * vec2( 0.0, 0.0)) / 9.0 + + sampleClouds(uv - texelSize0 * vec2( 1.0, 0.0)) / 9.0 + + sampleClouds(uv - texelSize0 * vec2(-1.0, 1.0)) / 9.0 + + sampleClouds(uv - texelSize0 * vec2( 0.0, 1.0)) / 9.0 + + sampleClouds(uv - texelSize0 * vec2( 1.0, 1.0)) / 9.0; +} + +void main(void) +{ + vec4 cloudsColor = getClouds(screenspaceCoordinate * 0.5 + 0.5); + vec4 sceneColor = texture2D(sceneTexture, screenspaceCoordinate * 0.5 + 0.5); + + gl_FragColor = vec4(sceneColor.rgb * (1. - cloudsColor.a) + cloudsColor.rgb, 1.); +} diff --git a/client/shaders/clouds_merge/opengl_vertex.glsl b/client/shaders/clouds_merge/opengl_vertex.glsl new file mode 100644 index 000000000..5487edeb6 --- /dev/null +++ b/client/shaders/clouds_merge/opengl_vertex.glsl @@ -0,0 +1,7 @@ +varying vec2 screenspaceCoordinate; + +void main(void) +{ + screenspaceCoordinate = inVertexPosition.xy; + gl_Position = inVertexPosition; +} diff --git a/client/shaders/coarse_noise_shader/opengl_fragment.glsl b/client/shaders/coarse_noise_shader/opengl_fragment.glsl new file mode 100644 index 000000000..c0cfecc9a --- /dev/null +++ b/client/shaders/coarse_noise_shader/opengl_fragment.glsl @@ -0,0 +1,17 @@ +uniform float cloudDensity; + +// Pseudorandom number generator +float rand(vec2 n) { + return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); +} + +// More random pseudorandom number generator; +float noise(vec2 p){ + vec2 p2 = p + vec2(rand(p), rand(p.yx)); + return rand(p2); +} + +void main(void) +{ + gl_FragColor = vec4(vec3(step(noise(floor(gl_FragCoord.xy * 0.25)), cloudDensity)), 1.); +} diff --git a/client/shaders/coarse_noise_shader/opengl_vertex.glsl b/client/shaders/coarse_noise_shader/opengl_vertex.glsl new file mode 100644 index 000000000..9182a208a --- /dev/null +++ b/client/shaders/coarse_noise_shader/opengl_vertex.glsl @@ -0,0 +1,4 @@ +void main(void) +{ + gl_Position = inVertexPosition; +} diff --git a/client/shaders/noise_shader/opengl_fragment.glsl b/client/shaders/noise_shader/opengl_fragment.glsl new file mode 100644 index 000000000..3a8081b8f --- /dev/null +++ b/client/shaders/noise_shader/opengl_fragment.glsl @@ -0,0 +1,15 @@ +// Pseudorandom number generator +float rand(vec2 n) { + return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); +} + +// More random pseudorandom number generator; +float noise(vec2 p){ + vec2 p2 = p + vec2(rand(p), rand(p.yx)); + return rand(p2); +} + +void main(void) +{ + gl_FragColor = vec4(vec3(noise(gl_FragCoord.xy)), 1.); +} diff --git a/client/shaders/noise_shader/opengl_vertex.glsl b/client/shaders/noise_shader/opengl_vertex.glsl new file mode 100644 index 000000000..9182a208a --- /dev/null +++ b/client/shaders/noise_shader/opengl_vertex.glsl @@ -0,0 +1,4 @@ +void main(void) +{ + gl_Position = inVertexPosition; +} diff --git a/client/shaders/second_stage/opengl_fragment.glsl b/client/shaders/second_stage/opengl_fragment.glsl index 46b0d1e31..0c39d1e94 100644 --- a/client/shaders/second_stage/opengl_fragment.glsl +++ b/client/shaders/second_stage/opengl_fragment.glsl @@ -163,7 +163,7 @@ void main(void) // Filter out blue pixels, because the color grading tends to wash them out. float blue_factor = clamp((color.b - max(color.r, color.g)) / max(0.01, min(color.r, color.g)), 0.0, 1.0); - color.rgb = mix(color.rgb, pow(color.rgb * slope, power), pow(1. - blue_factor, 4.)); + color.rgb = mix(color.rgb, pow(color.rgb * slope, power), 1.); #endif color.rgb = applySaturation(color.rgb, saturation); } diff --git a/client/shaders/volumetric_clouds/opengl_fragment.glsl b/client/shaders/volumetric_clouds/opengl_fragment.glsl new file mode 100644 index 000000000..af24765be --- /dev/null +++ b/client/shaders/volumetric_clouds/opengl_fragment.glsl @@ -0,0 +1,182 @@ +#define depthmap texture0 +#define noiseTexture texture1 +#define noiseTextureCoarse texture2 + +#define ITERATIONS 50 +#define LIGHT_ITERATIONS 10 +#define LIGHT_DISTANCE 100. +#define AURORA_ITERATIONS 100 + +uniform sampler2D depthmap; +uniform sampler2D noiseTexture; +uniform sampler2D noiseTextureCoarse; + +uniform vec2 texelSize0; + +uniform float cloudHeight; +uniform float cloudThickness; +uniform float cloudDensity; + +varying vec3 relativePosition; +varying vec3 viewDirection; +uniform vec3 eyePosition; +uniform vec3 cameraOffset; +uniform vec3 cameraPosition; + +uniform mat4 mCameraView; +uniform mat4 mCameraProjInv; + +uniform float cameraNear; +uniform float cameraFar; + +varying vec2 screenspaceCoordinate; + +uniform float fogDistance; +uniform float fogShadingParameter; + +uniform vec3 v_LightDirection; + +uniform float animationTimer; + +// Derived From http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf +// and https://www.shadertoy.com/view/MslGR8 (5th one starting from the bottom) +// NOTE: `frag_coord` is in pixels (i.e. not normalized UV). +float screenSpaceDither(highp vec2 frag_coord) { + // Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR. + highp float dither = dot(vec2(171.0, 231.0), frag_coord); + dither = fract(dither / 103.0); + + return dither; +} + +// 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) +{ + float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t); +} + +float getDepth(vec2 screenspacePosition) { + float depth = texture2D(depthmap, screenspacePosition * 0.5 + 0.5).r; + return cameraNear * cameraFar / (cameraFar + depth * (cameraNear - cameraFar)); +} + +float getRawDepth(vec2 screenspacePosition) { + return texture2D(depthmap, screenspacePosition * 0.5 + 0.5).r; +} + +float noise(vec3 p){ + //p.y *= 1.; + float y = floor(p.y); + float f1 = texture2D(noiseTexture, p.xz / 256. + y * 0.2).r; + float f2 = texture2D(noiseTexture, p.xz / 256. + y * 0.2 + 0.2).r; + return mix(f1, f2, fract(p.y)); +} + +float fnoise(vec3 p) { + return noise(p * 4.) * 0.5 + noise(p * 8.) * 0.25; +} + +float fnoise3(vec3 p) { + return noise(p * 4.) * 0.5 + noise(p * 8.) * 0.25 + noise(p * 16.) * 0.125; +} + +float getAuroraDensity(vec3 position) { + float density = pow(max(0., 1. - 10. * abs(fnoise3(vec3(position.x * 0.25, animationTimer, position.z * 0.25)) - 0.5)), 4.); + return 1.0 * density * mtsmoothstep(0.0, 0.05, position.y - 1.) * pow(1. - mtsmoothstep(0.05, 2.0, position.y - 1.), 4.); +} + +float getDensity(vec3 position) { + float density = texture2D(noiseTextureCoarse, position.xz / 2560. / 16.).r * + mtsmoothstep(0.0, cloudThickness * 0.2, position.y - cloudHeight) * + (1.0 - mtsmoothstep(cloudThickness * 0.5, cloudThickness, position.y - cloudHeight)); + + density = max(0., density - 0.5 * fnoise(position * 0.005)); + + return 0.04 * density; +} + +float getBrightness(vec3 position, float bias) { + float density = 0.; + for (int i = 0; i < LIGHT_ITERATIONS; i++) { + vec3 rayPosition = position - v_LightDirection * LIGHT_DISTANCE * (float(i) + bias) / float(LIGHT_ITERATIONS); + + density += getDensity(rayPosition) * float(LIGHT_DISTANCE) / float(LIGHT_ITERATIONS); + } + return exp(-density); +} + +float blend(float A, float B, float alphaA, float alphaB) { + float alphaC = alphaA + (1. - alphaA) * alphaB; + return (alphaA * A + (1. - alphaA) * alphaB * B) / alphaC; +} + +void main(void) +{ + vec3 viewVec = normalize(relativePosition); + + vec3 position = cameraOffset + eyePosition; + + float depth = getDepth(screenspaceCoordinate) / normalize(viewDirection).z; + float bottomPlaneIntersect = clamp(min((cloudHeight - eyePosition.y) / viewVec.y, depth), 0., 4. * fogDistance); + float topPlaneIntersect = clamp(min((cloudHeight + cloudThickness - eyePosition.y) / viewVec.y, depth), 0., 4. * fogDistance); + + float startDepth = min(bottomPlaneIntersect, topPlaneIntersect); + float endDepth = max(bottomPlaneIntersect, topPlaneIntersect); + + float bias = screenSpaceDither(gl_FragCoord.xy + animationTimer * 2400.0); + + vec3 color = vec3(0.); + + float dx = (endDepth - startDepth) / float(ITERATIONS); + + float density = 0.; + + float auroraStartDepth = min(max(0., 1.0 / viewVec.y), 8.); + float auroraEndDepth = min(max(0., 3.0 / viewVec.y), 8.); + float rawDepth = getRawDepth(screenspaceCoordinate); + + if (auroraEndDepth - auroraStartDepth > 0.1 && rawDepth >= 1.0) { + for (int i = 0; i < ITERATIONS; i++) { + vec3 rayPosition = viewVec * (auroraStartDepth + (auroraEndDepth - auroraStartDepth) * (float(i) + bias) / float(ITERATIONS)); + + float localDensity = getAuroraDensity(rayPosition); + + localDensity *= 1.0 - mtsmoothstep(4.0, 8.0, length(rayPosition)); + + density += localDensity; + } + } + + color.b = density * (auroraEndDepth - auroraStartDepth) / float(AURORA_ITERATIONS); + + float sunlightContribution = 0.; + float alpha = 0.; + float outScatter = 2. * (dot(v_LightDirection, viewVec) * 0.5 + 0.5); + density = 0.; + + for (int i = 0; i < ITERATIONS; i++) { + vec3 rayPosition = eyePosition + viewVec * (startDepth + (endDepth - startDepth) * (float(i) + bias) / float(ITERATIONS)); + + float localDensity = getDensity(rayPosition) * dx; + + if (localDensity < 0.0001) continue; + + float clarity = clamp(fogShadingParameter - fogShadingParameter * length(rayPosition - eyePosition) / (4. * fogDistance), 0.0, 1.0); + float brightness = getBrightness(rayPosition, bias) * exp(-outScatter * localDensity); + sunlightContribution = blend(sunlightContribution, brightness, 1. - exp(-density), 1. - exp(-localDensity)); + alpha = blend(alpha, clarity, 1. - exp(-density), 1. - exp(-localDensity)); + + density += localDensity; + + if (density > 10.0) break; + } + + float forwardScatter = 1. + 4. * pow(min(dot(v_LightDirection, viewVec), 0.), 4.); + + color.r = (1. - exp(-density)) * alpha; + color.g = sunlightContribution * forwardScatter; + + gl_FragColor = vec4(color, 1.0); +} diff --git a/client/shaders/volumetric_clouds/opengl_vertex.glsl b/client/shaders/volumetric_clouds/opengl_vertex.glsl new file mode 100644 index 000000000..33ee9edf6 --- /dev/null +++ b/client/shaders/volumetric_clouds/opengl_vertex.glsl @@ -0,0 +1,17 @@ +uniform mat4 mCameraProjInv; +uniform mat4 mCameraView; +uniform vec3 eyePosition; + +varying vec3 relativePosition; +varying vec3 viewDirection; + +varying vec2 screenspaceCoordinate; + +void main(void) +{ + screenspaceCoordinate = inVertexPosition.xy; + vec4 p = mCameraProjInv * inVertexPosition; + viewDirection = p.xyz / p.w; + relativePosition = (p.xyz / p.w) * mat3(mCameraView); + gl_Position = inVertexPosition; +} diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index adfdbf842..81b4086c4 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include - // Menu clouds are created later class Clouds; Clouds *g_menuclouds = NULL; @@ -344,6 +343,7 @@ void Clouds::updateMesh() void Clouds::render() { +#if 0 if (m_params.density <= 0.0f) return; // no need to do anything @@ -394,13 +394,7 @@ void Clouds::render() // Restore fog settings driver->setFog(fog_color, fog_type, fog_start, fog_end, fog_density, fog_pixelfog, fog_rangefog); -} - -void Clouds::renderVolumetrics() { - video::IVideoDriver* driver = SceneManager->getVideoDriver(); - v2u32 ss = driver->getScreenSize(); - core::rect rect(0, 0, ss.X, ss.Y); - driver->draw2DRectangle(video::SColor(255, 255, 255, 255), rect); +#endif } void Clouds::step(float dtime) diff --git a/src/client/clouds.h b/src/client/clouds.h index 7676136b2..100f3fcbe 100644 --- a/src/client/clouds.h +++ b/src/client/clouds.h @@ -52,8 +52,6 @@ public: virtual void render(); - void renderVolumetrics(); - virtual const aabb3f &getBoundingBox() const { return m_box; @@ -93,6 +91,10 @@ public: invalidateMesh(); } + float getDensity() const { + return m_params.density; + } + void setColorBright(video::SColor color_bright) { m_params.color_bright = color_bright; @@ -112,6 +114,10 @@ public: invalidateMesh(); } + float getHeight() const { + return m_params.height; + } + void setSpeed(v2f speed) { m_params.speed = speed; @@ -126,6 +132,10 @@ public: invalidateMesh(); } + float getThickness() const { + return m_params.thickness; + } + bool isCameraInsideCloud() const { return m_camera_inside_cloud; } const video::SColor getColor() const { return m_color.toSColor(); } @@ -147,7 +157,7 @@ private: bool gridFilled(int x, int y) const; - video::SMaterial m_volume_material; + video::ITexture *m_density_texture = nullptr; video::SMaterial m_material; irr_ptr m_meshbuffer; diff --git a/src/client/game.cpp b/src/client/game.cpp index 9bd8fc359..252a59a0e 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -383,9 +383,18 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter m_animation_timer_delta_pixel{"animationTimerDelta"}; CachedPixelShaderSetting m_artificial_light{ "artificialLight" }; CachedPixelShaderSetting m_day_light{"dayLight"}; + CachedPixelShaderSetting m_eye_position_pixel{ "eyePosition" }; + CachedVertexShaderSetting m_eye_position_vertex{ "eyePosition" }; CachedPixelShaderSetting m_minimap_yaw{"yawVec"}; CachedPixelShaderSetting m_camera_offset_pixel{"cameraOffset"}; CachedVertexShaderSetting m_camera_offset_vertex{"cameraOffset"}; + CachedPixelShaderSetting m_camera_position_pixel{"cameraPosition"}; + CachedVertexShaderSetting m_camera_projinv_vertex{"mCameraProjInv"}; + CachedPixelShaderSetting m_camera_projinv_pixel{"mCameraProjInv"}; + CachedVertexShaderSetting m_camera_view_vertex{"mCameraView"}; + CachedPixelShaderSetting m_camera_view_pixel{"mCameraView"}; + CachedPixelShaderSetting m_camera_near_pixel{"cameraNear"}; + CachedPixelShaderSetting m_camera_far_pixel{"cameraFar"}; CachedPixelShaderSetting m_texture0{"texture0"}; CachedPixelShaderSetting m_texture1{"texture1"}; CachedPixelShaderSetting m_texture2{"texture2"}; @@ -408,6 +417,9 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter float m_bloom_strength; CachedPixelShaderSetting m_bloom_radius_pixel{"bloomRadius"}; float m_bloom_radius; + CachedPixelShaderSetting m_cloud_height_pixel{"cloudHeight"}; + CachedPixelShaderSetting m_cloud_thickness_pixel{"cloudThickness"}; + CachedPixelShaderSetting m_cloud_density_pixel{"cloudDensity"}; CachedPixelShaderSetting m_saturation_pixel{"saturation"}; float m_gamma; CachedPixelShaderSetting m_gamma_pixel{"gamma"}; @@ -489,6 +501,10 @@ public: m_animation_timer_delta_vertex.set(&animation_timer_delta_f, services); m_animation_timer_delta_pixel.set(&animation_timer_delta_f, services); + v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition(); + m_eye_position_pixel.set(epos, services); + m_eye_position_vertex.set(epos, services); + if (m_client->getMinimap()) { v3f minimap_yaw = m_client->getMinimap()->getYawVec(); m_minimap_yaw.set(minimap_yaw, services); @@ -498,6 +514,24 @@ public: m_camera_offset_pixel.set(offset, services); m_camera_offset_vertex.set(offset, services); + v3f camera_position = m_client->getCamera()->getPosition(); + m_camera_position_pixel.set(camera_position, services); + + core::matrix4 camera_proj = m_client->getCamera()->getCameraNode()->getProjectionMatrix(); + core::matrix4 camera_projinv; + camera_proj.getInverse(camera_projinv); + m_camera_projinv_vertex.set(camera_projinv, services); + m_camera_projinv_pixel.set(camera_projinv, services); + + core::matrix4 camera_view = m_client->getCamera()->getCameraNode()->getViewMatrix(); + m_camera_view_vertex.set(camera_view, services); + m_camera_view_pixel.set(camera_view, services); + + float camera_near = m_client->getCamera()->getCameraNode()->getNearValue(); + m_camera_near_pixel.set(&camera_near, services); + float camera_far = m_client->getCamera()->getCameraNode()->getFarValue(); + m_camera_far_pixel.set(&camera_far, services); + SamplerLayer_t tex_id; tex_id = 0; m_texture0.set(&tex_id, services); @@ -537,6 +571,17 @@ public: video::SColorf artificial_light = lighting.artificial_light_color; m_artificial_light.set(artificial_light, services); + // TODO: settings + Clouds* clouds = m_client->getClouds(); + if (m_client->getClouds()) { + float cloud_height = clouds->getHeight() * 10.0f; + m_cloud_height_pixel.set(&cloud_height, services); + float cloud_thickness = clouds->getThickness() * 10.0f; + m_cloud_thickness_pixel.set(&cloud_thickness, services); + float cloud_density = clouds->getDensity(); + m_cloud_density_pixel.set(&cloud_density, services); + } + if (m_volumetric_light_enabled) { // Map directional light to screen space auto camera_node = m_client->getCamera()->getCameraNode(); diff --git a/src/client/render/plain.cpp b/src/client/render/plain.cpp index fb8bcec70..60a732415 100644 --- a/src/client/render/plain.cpp +++ b/src/client/render/plain.cpp @@ -66,11 +66,6 @@ void DrawHUD::run(PipelineContext &context) context.client->getCamera()->drawNametags(); } context.device->getGUIEnvironment()->drawAll(); - - // TODO: proper settings - if (true && context.client->getClouds()) { - context.client->getClouds()->renderVolumetrics(); - } } diff --git a/src/client/render/secondstage.cpp b/src/client/render/secondstage.cpp index da6536b97..0a03011c8 100644 --- a/src/client/render/secondstage.cpp +++ b/src/client/render/secondstage.cpp @@ -25,6 +25,65 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/tile.h" #include "settings.h" +class NoiseStep : public RenderStep { +public: + NoiseStep(u32 shader_id, u8 texture_id) : + shader_id(shader_id), texture_id(texture_id) + { + material.UseMipMaps = false; + material.ZBuffer = true; + material.ZWriteEnable = video::EZW_ON; + } + + void setRenderSource(RenderSource* _source) override { + source = _source; + } + + void setRenderTarget(RenderTarget* _target) override { + target = _target; + } + + void reset(PipelineContext& context) override {} + + void run(PipelineContext& context) override { + video::ITexture* texture = source->getTexture(texture_id); + if (texture != last_texture) { + last_texture = texture; + + if (target) + target->activate(context); + + // attach the shader + material.MaterialType = context.client->getShaderSource()->getShaderInfo(shader_id).material; + + auto driver = context.device->getVideoDriver(); + + static const video::SColor color = video::SColor(0, 0, 0, 255); + static const video::S3DVertex vertices[4] = { + video::S3DVertex(1.0, -1.0, 0.0, 0.0, 0.0, -1.0, + color, 1.0, 0.0), + video::S3DVertex(-1.0, -1.0, 0.0, 0.0, 0.0, -1.0, + color, 0.0, 0.0), + video::S3DVertex(-1.0, 1.0, 0.0, 0.0, 0.0, -1.0, + color, 0.0, 1.0), + video::S3DVertex(1.0, 1.0, 0.0, 0.0, 0.0, -1.0, + color, 1.0, 1.0), + }; + static const u16 indices[6] = { 0, 1, 2, 2, 3, 0 }; + driver->setMaterial(material); + driver->drawVertexPrimitiveList(&vertices, 4, &indices, 2); + } + } + +private: + u32 shader_id; + u8 texture_id; + video::SMaterial material; + video::ITexture* last_texture = nullptr; + RenderSource* source{ nullptr }; + RenderTarget* target{ nullptr }; +}; + PostProcessingStep::PostProcessingStep(u32 _shader_id, const std::vector &_texture_map) : shader_id(_shader_id), texture_map(_texture_map) { @@ -65,7 +124,6 @@ void PostProcessingStep::run(PipelineContext &context) if (target) target->activate(context); - // attach the shader material.MaterialType = context.client->getShaderSource()->getShaderInfo(shader_id).material; auto driver = context.device->getVideoDriver(); @@ -96,6 +154,12 @@ void PostProcessingStep::setBilinearFilter(u8 index, bool value) material.TextureLayers[index].MagFilter = value ? video::ETMAGF_LINEAR : video::ETMAGF_NEAREST; } +void PostProcessingStep::setWrapRepeat(u8 index, bool value) { + assert(index < video::MATERIAL_MAX_TEXTURES); + material.TextureLayers[index].TextureWrapU = value ? video::ETC_REPEAT : video::ETC_CLAMP_TO_EDGE; + material.TextureLayers[index].TextureWrapV = value ? video::ETC_REPEAT : video::ETC_CLAMP_TO_EDGE; +} + RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep, v2f scale, Client *client) { auto buffer = pipeline->createOwned(); @@ -121,8 +185,13 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep static const u8 TEXTURE_EXPOSURE_2 = 4; static const u8 TEXTURE_FXAA = 5; static const u8 TEXTURE_VOLUME = 6; - static const u8 TEXTURE_SCALE_DOWN = 10; - static const u8 TEXTURE_SCALE_UP = 20; + static const u8 TEXTURE_CLOUDS_1 = 7; + static const u8 TEXTURE_CLOUDS_2 = 8; + static const u8 TEXTURE_CLOUD_DENSITY = 9; + static const u8 TEXTURE_NOISE = 10; + static const u8 TEXTURE_NOISE_COARSE = 11; + static const u8 TEXTURE_SCALE_DOWN = 20; + static const u8 TEXTURE_SCALE_UP = 30; // Super-sampling is simply rendering into a larger texture. // Downscaling is done by the final step when rendering to the screen. @@ -132,6 +201,8 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep const bool enable_ssaa = antialiasing == "ssaa"; const bool enable_fxaa = antialiasing == "fxaa"; const bool enable_volumetric_light = g_settings->getBool("enable_volumetric_lighting") && enable_bloom; + const bool enable_volumetric_clouds = true; + // TODO: Add clouds setting if (enable_ssaa) { u16 ssaa_scale = MYMAX(2, g_settings->getU16("fsaa")); @@ -152,10 +223,47 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep // Number of mipmap levels of the bloom downsampling texture const u8 MIPMAP_LEVELS = 4; - // post-processing stage u8 source = TEXTURE_COLOR; + + if (enable_volumetric_clouds) { + buffer->setTexture(TEXTURE_NOISE, core::dimension2du(256, 256), "noise", color_format); + + shader_id = client->getShaderSource()->getShader("noise_shader", TILE_MATERIAL_PLAIN, NDT_MESH); + RenderStep *noise_step = pipeline->addStep(shader_id, TEXTURE_NOISE); + noise_step->setRenderSource(buffer); + noise_step->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_NOISE)); + + buffer->setTexture(TEXTURE_NOISE_COARSE, core::dimension2du(256, 256), "noise", color_format); + + shader_id = client->getShaderSource()->getShader("coarse_noise_shader", TILE_MATERIAL_PLAIN, NDT_MESH); + noise_step = pipeline->addStep(shader_id, std::vector()); + noise_step->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_NOISE_COARSE)); + + buffer->setTexture(TEXTURE_CLOUDS_1, scale * 0.25f, "clouds_1", color_format, /*clear:*/ true); + buffer->setTexture(TEXTURE_CLOUDS_2, scale, "clouds_2", color_format); + buffer->setTexture(TEXTURE_CLOUD_DENSITY, scale, "cloud_density", color_format); + + shader_id = client->getShaderSource()->getShader("volumetric_clouds", TILE_MATERIAL_PLAIN, NDT_MESH); + PostProcessingStep *volumetric_clouds = pipeline->addStep(shader_id, std::vector { TEXTURE_DEPTH, TEXTURE_NOISE, TEXTURE_NOISE_COARSE }); + volumetric_clouds->setRenderSource(buffer); + volumetric_clouds->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_CLOUDS_1)); + volumetric_clouds->setBilinearFilter(1, true); + volumetric_clouds->setBilinearFilter(2, true); + volumetric_clouds->setWrapRepeat(1, true); + volumetric_clouds->setWrapRepeat(2, true); + + source = TEXTURE_CLOUDS_1; + + shader_id = client->getShaderSource()->getShader("clouds_merge", TILE_MATERIAL_PLAIN, NDT_MESH); + PostProcessingStep* blend_clouds = pipeline->addStep(shader_id, std::vector { TEXTURE_CLOUDS_1, TEXTURE_COLOR }); + blend_clouds->setRenderSource(buffer); + blend_clouds->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_CLOUDS_2)); + blend_clouds->setBilinearFilter(0, true); + + source = TEXTURE_CLOUDS_2; + } // common downsampling step for bloom or autoexposure if (enable_bloom || enable_auto_exposure) { @@ -173,7 +281,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep // get bright spots u32 shader_id = client->getShaderSource()->getShader("extract_bloom", TILE_MATERIAL_PLAIN, NDT_MESH); - RenderStep *extract_bloom = pipeline->addStep(shader_id, std::vector { source, TEXTURE_EXPOSURE_1 }); + auto extract_bloom = pipeline->addStep(shader_id, std::vector { source, TEXTURE_EXPOSURE_1 }); extract_bloom->setRenderSource(buffer); extract_bloom->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_BLOOM)); source = TEXTURE_BLOOM; @@ -224,7 +332,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep } // FXAA - u8 final_stage_source = TEXTURE_COLOR; + u8 final_stage_source = TEXTURE_CLOUDS_2; if (enable_fxaa) { final_stage_source = TEXTURE_FXAA; diff --git a/src/client/render/secondstage.h b/src/client/render/secondstage.h index 9e3640927..04705f3ae 100644 --- a/src/client/render/secondstage.h +++ b/src/client/render/secondstage.h @@ -49,6 +49,9 @@ public: * @param value true to enable the bilinear filter, false to disable */ void setBilinearFilter(u8 index, bool value); + + void setWrapRepeat(u8 index, bool value); + private: u32 shader_id; std::vector texture_map; From e6752008e0ac7e5afa0d86593d9ffd8ebe33541b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 18 Aug 2024 15:13:26 +0200 Subject: [PATCH 06/40] Update volumetrics --- builtin/settingtypes.txt | 25 ++- .../shaders/clouds_merge/opengl_fragment.glsl | 49 ++++- .../shaders/clouds_merge/opengl_vertex.glsl | 41 ++++ .../coarse_noise_shader/opengl_fragment.glsl | 17 -- .../coarse_noise_shader/opengl_vertex.glsl | 4 - .../shaders/noise_shader/opengl_fragment.glsl | 15 -- .../shaders/noise_shader/opengl_vertex.glsl | 4 - .../volumetric_clouds/opengl_fragment.glsl | 121 +++++++----- .../volumetric_clouds/opengl_vertex.glsl | 22 ++- src/client/clouds.cpp | 61 ++++-- src/client/clouds.h | 16 ++ src/client/game.cpp | 26 ++- src/client/render/pipeline.cpp | 14 ++ src/client/render/pipeline.h | 3 + src/client/render/secondstage.cpp | 178 ++++++++++++------ src/client/render/secondstage.h | 4 + src/defaultsettings.cpp | 1 + 17 files changed, 420 insertions(+), 181 deletions(-) delete mode 100644 client/shaders/coarse_noise_shader/opengl_fragment.glsl delete mode 100644 client/shaders/coarse_noise_shader/opengl_vertex.glsl delete mode 100644 client/shaders/noise_shader/opengl_fragment.glsl delete mode 100644 client/shaders/noise_shader/opengl_vertex.glsl diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index ebf42f971..936ce74d1 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -610,14 +610,15 @@ enable_auto_exposure (Enable Automatic Exposure) bool false # Requires: shaders, enable_post_processing, enable_auto_exposure exposure_compensation (Exposure compensation) float 0.0 -1.0 1.0 -# Set the gamma value. +# Set the post processing gamma value. # Higher values give lower contrast and vice versa. # Range: from 1.0 to 5.0 +# Default: 1.6 # # Requires: shaders, enable_post_processing, tone_mapping gamma (Gamma) float 1.6 1.0 5.0 -# Apply color grading to make brighter colors warmer and darker colors cooler. +# Apply ASL CDL color grading to make brighter colors warmer and darker colors cooler. # # Requires: shaders, enable_post_processing enable_color_grading (Color grading) bool false @@ -674,10 +675,28 @@ bloom_strength_factor (Bloom Strength Factor) float 1.0 0.1 10.0 # Requires: shaders, enable_post_processing, enable_bloom bloom_radius (Bloom Radius) float 1 0.1 8 +[**Volumetric Effects] + # Set to true to enable volumetric lighting effect (a.k.a. "Godrays"). # # Requires: shaders, enable_post_processing, enable_bloom -enable_volumetric_lighting (Volumetric lighting) bool false +enable_volumetric_lighting (Volumetric Lighting) bool false + +# Set to true to render clouds as scatter volumes. +# +# Requires: shaders, enable_post_processing, enable_clouds +enable_volumetric_clouds (Volumetric Clouds) bool false + +# Higher values reduce visual quality and may introduce artifacts, but improve performance of volumetric cloud/aurora effects. +# Range: from 1 to 4, default: 2 +# +# Requires: shaders, enable_post_processing +volumetrics_undersampling (Volumetric Undersampling) int 2 1 4 + +# Set to true to render volumetric auroras ("Northern Lights"). +# +# Requires: shaders, enable_post_processing +enable_volumetric_auroras (Volumetric Auroras) bool false [**Other Effects] diff --git a/client/shaders/clouds_merge/opengl_fragment.glsl b/client/shaders/clouds_merge/opengl_fragment.glsl index c88f0d95a..a3c597a66 100644 --- a/client/shaders/clouds_merge/opengl_fragment.glsl +++ b/client/shaders/clouds_merge/opengl_fragment.glsl @@ -1,24 +1,49 @@ #define cloudsTexture texture0 #define sceneTexture texture1 +#define depthmap texture2 uniform sampler2D cloudsTexture; uniform sampler2D sceneTexture; +uniform sampler2D depthmap; uniform vec2 texelSize0; uniform vec3 dayLight; +uniform vec3 cloudColor; varying vec2 screenspaceCoordinate; +varying vec3 relativePosition; +varying vec3 viewDirection; +varying vec3 sunTint; +varying float auroraFactor; + +uniform vec3 cameraOffset; +uniform vec3 cameraPosition; + +uniform float cameraNear; +uniform float cameraFar; + +uniform float cloudHeight; +uniform float cloudThickness; + +float getDepth(vec2 screenspacePosition) { + float depth = texture2D(depthmap, screenspacePosition * 0.5 + 0.5).r; + return cameraNear * cameraFar / (cameraFar + depth * (cameraNear - cameraFar)); +} vec4 sampleClouds(vec2 uv) { vec4 cloudsKey = texture2D(cloudsTexture, uv); - const vec3 darkColor = vec3(0.05, 0.1, 0.2); + //const vec3 darkColor = vec3(0.05, 0.1, 0.2); + vec3 darkColor = vec3(0.2, 0.4, 0.8) * dayLight; const vec3 auroraDark = vec3(0., 0.5, 0.5); const vec3 auroraBright = vec3(0., 0.5, .0); + //const vec3 auroraDark = vec3(0.); + //const vec3 auroraBright = vec3(0.); + return vec4( - mix(auroraDark, auroraBright, cloudsKey.b) * cloudsKey.b * max(0., 1. - cloudsKey.r) + - cloudsKey.r * (darkColor * max(0., 1. - cloudsKey.g) + dayLight * cloudsKey.g), + mix(auroraDark, auroraBright, cloudsKey.b) * cloudsKey.b * auroraFactor + + cloudsKey.r * cloudColor * (darkColor * max(0., 1. - cloudsKey.g) + dayLight * sunTint * cloudsKey.g), cloudsKey.r); } @@ -37,8 +62,22 @@ vec4 getClouds(vec2 uv) { void main(void) { - vec4 cloudsColor = getClouds(screenspaceCoordinate * 0.5 + 0.5); + vec3 viewVec = normalize(relativePosition); + + vec3 position = cameraOffset + cameraPosition; + + float depth = getDepth(screenspaceCoordinate) / normalize(viewDirection).z; + float bottomPlaneIntersect = max((cloudHeight - cameraPosition.y) / viewVec.y, 0.); + float topPlaneIntersect = max((cloudHeight + cloudThickness - cameraPosition.y) / viewVec.y, 0.); + float minPlane = min(bottomPlaneIntersect, topPlaneIntersect); + vec4 sceneColor = texture2D(sceneTexture, screenspaceCoordinate * 0.5 + 0.5); - gl_FragColor = vec4(sceneColor.rgb * (1. - cloudsColor.a) + cloudsColor.rgb, 1.); + if (depth > minPlane) { + vec4 finalColor = getClouds(screenspaceCoordinate * 0.5 + 0.5); + + gl_FragColor = vec4(sceneColor.rgb * (1. - finalColor.a) + finalColor.rgb, 1.); + } else { + gl_FragColor = sceneColor; + } } diff --git a/client/shaders/clouds_merge/opengl_vertex.glsl b/client/shaders/clouds_merge/opengl_vertex.glsl index 5487edeb6..dc0516dfb 100644 --- a/client/shaders/clouds_merge/opengl_vertex.glsl +++ b/client/shaders/clouds_merge/opengl_vertex.glsl @@ -1,7 +1,48 @@ +uniform mat4 mCameraProjInv; +uniform mat4 mCameraView; +uniform vec3 v_LightDirection; +uniform float f_timeofday; + +varying vec3 relativePosition; +varying vec3 viewDirection; varying vec2 screenspaceCoordinate; +varying vec3 sunTint; +varying float auroraFactor; + +vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) +{ + // Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham + const float beta_r0 = 1e-5; // Rayleigh scattering beta + + // These factors are calculated based on expected value of scattering factor of 1e-5 + // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere + const vec3 beta_r0_l = vec3(3.3362176e-01, 8.75378289198826e-01, 1.95342379700656) * beta_r0; // wavelength-dependent scattering + + const float atmosphere_height = 15000.; // height of the atmosphere in meters + // sun/moon light at the ground level, after going through the atmosphere + return exp(-beta_r0_l * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); +} + +// 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) +{ + float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t); +} void main(void) { + vec4 p = mCameraProjInv * inVertexPosition; + viewDirection = p.xyz / p.w; + relativePosition = (p.xyz / p.w) * mat3(mCameraView); screenspaceCoordinate = inVertexPosition.xy; + + auroraFactor = 1. - mtsmoothstep(0.13, 0.15, f_timeofday) * mtsmoothstep(0.87, 0.85, f_timeofday); + + float tintFactor = mtsmoothstep(0.21, 0.24, f_timeofday) * mtsmoothstep(0.793, 0.753, f_timeofday); + + sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), tintFactor); + gl_Position = inVertexPosition; } diff --git a/client/shaders/coarse_noise_shader/opengl_fragment.glsl b/client/shaders/coarse_noise_shader/opengl_fragment.glsl deleted file mode 100644 index c0cfecc9a..000000000 --- a/client/shaders/coarse_noise_shader/opengl_fragment.glsl +++ /dev/null @@ -1,17 +0,0 @@ -uniform float cloudDensity; - -// Pseudorandom number generator -float rand(vec2 n) { - return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); -} - -// More random pseudorandom number generator; -float noise(vec2 p){ - vec2 p2 = p + vec2(rand(p), rand(p.yx)); - return rand(p2); -} - -void main(void) -{ - gl_FragColor = vec4(vec3(step(noise(floor(gl_FragCoord.xy * 0.25)), cloudDensity)), 1.); -} diff --git a/client/shaders/coarse_noise_shader/opengl_vertex.glsl b/client/shaders/coarse_noise_shader/opengl_vertex.glsl deleted file mode 100644 index 9182a208a..000000000 --- a/client/shaders/coarse_noise_shader/opengl_vertex.glsl +++ /dev/null @@ -1,4 +0,0 @@ -void main(void) -{ - gl_Position = inVertexPosition; -} diff --git a/client/shaders/noise_shader/opengl_fragment.glsl b/client/shaders/noise_shader/opengl_fragment.glsl deleted file mode 100644 index 3a8081b8f..000000000 --- a/client/shaders/noise_shader/opengl_fragment.glsl +++ /dev/null @@ -1,15 +0,0 @@ -// Pseudorandom number generator -float rand(vec2 n) { - return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); -} - -// More random pseudorandom number generator; -float noise(vec2 p){ - vec2 p2 = p + vec2(rand(p), rand(p.yx)); - return rand(p2); -} - -void main(void) -{ - gl_FragColor = vec4(vec3(noise(gl_FragCoord.xy)), 1.); -} diff --git a/client/shaders/noise_shader/opengl_vertex.glsl b/client/shaders/noise_shader/opengl_vertex.glsl deleted file mode 100644 index 9182a208a..000000000 --- a/client/shaders/noise_shader/opengl_vertex.glsl +++ /dev/null @@ -1,4 +0,0 @@ -void main(void) -{ - gl_Position = inVertexPosition; -} diff --git a/client/shaders/volumetric_clouds/opengl_fragment.glsl b/client/shaders/volumetric_clouds/opengl_fragment.glsl index af24765be..397a7fbc3 100644 --- a/client/shaders/volumetric_clouds/opengl_fragment.glsl +++ b/client/shaders/volumetric_clouds/opengl_fragment.glsl @@ -2,10 +2,13 @@ #define noiseTexture texture1 #define noiseTextureCoarse texture2 +#define PROBING_ITERATIONS 30 #define ITERATIONS 50 -#define LIGHT_ITERATIONS 10 -#define LIGHT_DISTANCE 100. -#define AURORA_ITERATIONS 100 +#define LIGHT_ITERATIONS 3 +#define AURORA_ITERATIONS 80 + +// See clouds.cpp +#define CLOUD_SIZE 640.0 uniform sampler2D depthmap; uniform sampler2D noiseTexture; @@ -19,17 +22,17 @@ uniform float cloudDensity; varying vec3 relativePosition; varying vec3 viewDirection; -uniform vec3 eyePosition; uniform vec3 cameraOffset; uniform vec3 cameraPosition; -uniform mat4 mCameraView; -uniform mat4 mCameraProjInv; - uniform float cameraNear; uniform float cameraFar; +uniform vec2 cloudOffset; +uniform float cloudRadius; + varying vec2 screenspaceCoordinate; +varying float sunStrength; uniform float fogDistance; uniform float fogShadingParameter; @@ -41,7 +44,8 @@ uniform float animationTimer; // Derived From http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf // and https://www.shadertoy.com/view/MslGR8 (5th one starting from the bottom) // NOTE: `frag_coord` is in pixels (i.e. not normalized UV). -float screenSpaceDither(highp vec2 frag_coord) { +float screenSpaceDither(highp vec2 frag_coord) +{ // Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR. highp float dither = dot(vec2(171.0, 231.0), frag_coord); dither = fract(dither / 103.0); @@ -57,38 +61,47 @@ float mtsmoothstep(in float edge0, in float edge1, in float x) return t * t * (3.0 - 2.0 * t); } -float getDepth(vec2 screenspacePosition) { - float depth = texture2D(depthmap, screenspacePosition * 0.5 + 0.5).r; +float toLinearDepth(float depth) +{ return cameraNear * cameraFar / (cameraFar + depth * (cameraNear - cameraFar)); } -float getRawDepth(vec2 screenspacePosition) { +float getDepth(vec2 screenspacePosition) +{ return texture2D(depthmap, screenspacePosition * 0.5 + 0.5).r; } -float noise(vec3 p){ - //p.y *= 1.; +float noise(vec3 p) +{ float y = floor(p.y); float f1 = texture2D(noiseTexture, p.xz / 256. + y * 0.2).r; float f2 = texture2D(noiseTexture, p.xz / 256. + y * 0.2 + 0.2).r; return mix(f1, f2, fract(p.y)); } -float fnoise(vec3 p) { +float fnoise(vec3 p) +{ return noise(p * 4.) * 0.5 + noise(p * 8.) * 0.25; } -float fnoise3(vec3 p) { +float fnoise3(vec3 p) +{ return noise(p * 4.) * 0.5 + noise(p * 8.) * 0.25 + noise(p * 16.) * 0.125; } -float getAuroraDensity(vec3 position) { +float getAuroraDensity(vec3 position) +{ float density = pow(max(0., 1. - 10. * abs(fnoise3(vec3(position.x * 0.25, animationTimer, position.z * 0.25)) - 0.5)), 4.); - return 1.0 * density * mtsmoothstep(0.0, 0.05, position.y - 1.) * pow(1. - mtsmoothstep(0.05, 2.0, position.y - 1.), 4.); + return 0.7 * density * mtsmoothstep(0.0, 0.05, position.y - 1.) * pow(1. - mtsmoothstep(0.05, 2.0, position.y - 1.), 4.); } -float getDensity(vec3 position) { - float density = texture2D(noiseTextureCoarse, position.xz / 2560. / 16.).r * +float getCoarse(vec3 position) { + return texture2D(noiseTextureCoarse, (position.xz - cloudOffset) * 0.5 / CLOUD_SIZE / cloudRadius).r; +} + +float getDensity(vec3 position) +{ + float density = texture2D(noiseTextureCoarse, (position.xz - cloudOffset) * 0.5 / CLOUD_SIZE / cloudRadius).r * mtsmoothstep(0.0, cloudThickness * 0.2, position.y - cloudHeight) * (1.0 - mtsmoothstep(cloudThickness * 0.5, cloudThickness, position.y - cloudHeight)); @@ -97,17 +110,19 @@ float getDensity(vec3 position) { return 0.04 * density; } -float getBrightness(vec3 position, float bias) { +float getBrightness(vec3 position, float lightDistance) +{ float density = 0.; - for (int i = 0; i < LIGHT_ITERATIONS; i++) { - vec3 rayPosition = position - v_LightDirection * LIGHT_DISTANCE * (float(i) + bias) / float(LIGHT_ITERATIONS); + for (int i = 1; i <= LIGHT_ITERATIONS; i++) { + vec3 rayPosition = position - v_LightDirection * lightDistance * float(i) / float(LIGHT_ITERATIONS); - density += getDensity(rayPosition) * float(LIGHT_DISTANCE) / float(LIGHT_ITERATIONS); + density += getDensity(rayPosition) * float(lightDistance) / float(LIGHT_ITERATIONS); } return exp(-density); } -float blend(float A, float B, float alphaA, float alphaB) { +float blend(float A, float B, float alphaA, float alphaB) +{ float alphaC = alphaA + (1. - alphaA) * alphaB; return (alphaA * A + (1. - alphaA) * alphaB * B) / alphaC; } @@ -116,11 +131,16 @@ void main(void) { vec3 viewVec = normalize(relativePosition); - vec3 position = cameraOffset + eyePosition; + vec3 position = cameraOffset + cameraPosition; - float depth = getDepth(screenspaceCoordinate) / normalize(viewDirection).z; - float bottomPlaneIntersect = clamp(min((cloudHeight - eyePosition.y) / viewVec.y, depth), 0., 4. * fogDistance); - float topPlaneIntersect = clamp(min((cloudHeight + cloudThickness - eyePosition.y) / viewVec.y, depth), 0., 4. * fogDistance); + float depth = toLinearDepth(getDepth(screenspaceCoordinate)) / normalize(viewDirection).z; + float bottomPlaneIntersect = clamp((cloudHeight - cameraPosition.y) / viewVec.y, 0., 4. * fogDistance); + float topPlaneIntersect = clamp((cloudHeight + cloudThickness - cameraPosition.y) / viewVec.y, 0., 4. * fogDistance); + + if ((bottomPlaneIntersect > depth + 5.0) != (topPlaneIntersect > depth + 5.0)) { + bottomPlaneIntersect = min(depth, bottomPlaneIntersect); + topPlaneIntersect = min(depth, topPlaneIntersect); + } float startDepth = min(bottomPlaneIntersect, topPlaneIntersect); float endDepth = max(bottomPlaneIntersect, topPlaneIntersect); @@ -129,17 +149,15 @@ void main(void) vec3 color = vec3(0.); - float dx = (endDepth - startDepth) / float(ITERATIONS); - float density = 0.; float auroraStartDepth = min(max(0., 1.0 / viewVec.y), 8.); float auroraEndDepth = min(max(0., 3.0 / viewVec.y), 8.); - float rawDepth = getRawDepth(screenspaceCoordinate); + float rawDepth = getDepth(screenspaceCoordinate); if (auroraEndDepth - auroraStartDepth > 0.1 && rawDepth >= 1.0) { - for (int i = 0; i < ITERATIONS; i++) { - vec3 rayPosition = viewVec * (auroraStartDepth + (auroraEndDepth - auroraStartDepth) * (float(i) + bias) / float(ITERATIONS)); + for (int i = 0; i < AURORA_ITERATIONS; i++) { + vec3 rayPosition = viewVec * (auroraStartDepth + (auroraEndDepth - auroraStartDepth) * (float(i) + bias) / float(AURORA_ITERATIONS)); float localDensity = getAuroraDensity(rayPosition); @@ -150,33 +168,42 @@ void main(void) } color.b = density * (auroraEndDepth - auroraStartDepth) / float(AURORA_ITERATIONS); - + float sunlightContribution = 0.; float alpha = 0.; float outScatter = 2. * (dot(v_LightDirection, viewVec) * 0.5 + 0.5); + float forwardScatter = 1. + 2. * pow(min(dot(v_LightDirection, viewVec), 0.), 4.); density = 0.; - for (int i = 0; i < ITERATIONS; i++) { - vec3 rayPosition = eyePosition + viewVec * (startDepth + (endDepth - startDepth) * (float(i) + bias) / float(ITERATIONS)); + float fogDepth = min(4. * fogDistance, startDepth + 2000.); + endDepth = min(endDepth, fogDepth); - float localDensity = getDensity(rayPosition) * dx; + float dx = (endDepth - startDepth) / float(ITERATIONS); + float lightDistance = cloudThickness * 0.5; - if (localDensity < 0.0001) continue; + if (endDepth - startDepth > 0.1) { + for (int i = 0; i < ITERATIONS; i++) { + vec3 rayPosition = cameraPosition + viewVec * (startDepth + (endDepth - startDepth) * (float(i) + bias) / float(ITERATIONS)); - float clarity = clamp(fogShadingParameter - fogShadingParameter * length(rayPosition - eyePosition) / (4. * fogDistance), 0.0, 1.0); - float brightness = getBrightness(rayPosition, bias) * exp(-outScatter * localDensity); - sunlightContribution = blend(sunlightContribution, brightness, 1. - exp(-density), 1. - exp(-localDensity)); - alpha = blend(alpha, clarity, 1. - exp(-density), 1. - exp(-localDensity)); + float localDensity = getDensity(rayPosition) * dx; - density += localDensity; + if (localDensity < 0.0001) continue; - if (density > 10.0) break; + float clarity = clamp(fogShadingParameter - fogShadingParameter * length(rayPosition - cameraPosition) / (fogDepth), 0.0, 1.0); + float outScatterContribution = exp(-0.5 * outScatter * localDensity); + float brightness = getBrightness(rayPosition, lightDistance) * forwardScatter * outScatterContribution * sunStrength + (1. - outScatterContribution); + sunlightContribution = blend(sunlightContribution, brightness, 1. - exp(-density), 1. - exp(-localDensity)); + alpha = blend(alpha, clarity, 1. - exp(-density), 1. - exp(-localDensity)); + + density += localDensity; + + if (density > 10.0) break; + } } - float forwardScatter = 1. + 4. * pow(min(dot(v_LightDirection, viewVec), 0.), 4.); - color.r = (1. - exp(-density)) * alpha; - color.g = sunlightContribution * forwardScatter; + color.g = sunlightContribution; + color.b *= exp(-density); gl_FragColor = vec4(color, 1.0); } diff --git a/client/shaders/volumetric_clouds/opengl_vertex.glsl b/client/shaders/volumetric_clouds/opengl_vertex.glsl index 33ee9edf6..3b1d247a9 100644 --- a/client/shaders/volumetric_clouds/opengl_vertex.glsl +++ b/client/shaders/volumetric_clouds/opengl_vertex.glsl @@ -1,11 +1,18 @@ uniform mat4 mCameraProjInv; uniform mat4 mCameraView; -uniform vec3 eyePosition; +uniform float f_timeofday; varying vec3 relativePosition; varying vec3 viewDirection; varying vec2 screenspaceCoordinate; +varying float sunStrength; + +float mtsmoothstep(in float edge0, in float edge1, in float x) +{ + float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t); +} void main(void) { @@ -13,5 +20,18 @@ void main(void) vec4 p = mCameraProjInv * inVertexPosition; viewDirection = p.xyz / p.w; relativePosition = (p.xyz / p.w) * mat3(mCameraView); + + if (f_timeofday < 0.21) { + sunStrength = + (1.0 - mtsmoothstep(0.18, 0.21, f_timeofday)); + } else if (f_timeofday >= 0.793) { + sunStrength = + mtsmoothstep(0.793, 0.823, f_timeofday); + } else { + sunStrength = + mtsmoothstep(0.21, 0.26, f_timeofday) * + (1.0 - mtsmoothstep(0.743, 0.793, f_timeofday)); + } + gl_Position = inVertexPosition; } diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 81b4086c4..5d9f6c1da 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -45,7 +45,7 @@ Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc, s32 id, u32 seed ): - scene::ISceneNode(mgr->getRootSceneNode(), mgr, id), + scene::ISceneNode(g_settings->getBool("enable_volumetric_clouds") ? nullptr : mgr->getRootSceneNode(), mgr, id), m_seed(seed) { m_enable_shaders = g_settings->getBool("enable_shaders"); @@ -106,6 +106,14 @@ void Clouds::updateMesh() std::floor(center_of_drawing_in_noise_f.Y / cloud_size) ); + // The world position of the integer center point of drawing in the noise + v2f world_center_of_drawing_in_noise_f = v2f( + center_of_drawing_in_noise_i.X * cloud_size, + center_of_drawing_in_noise_i.Y * cloud_size + ) + m_origin; + + m_noise_position = world_center_of_drawing_in_noise_f - ((float)m_cloud_radius_i + 0.5f) * cloud_size; + // Only update mesh if it has moved enough, this saves lots of GPU buffer uploads. constexpr float max_d = 5 * BS; @@ -128,12 +136,6 @@ void Clouds::updateMesh() const u32 num_faces_to_draw = m_enable_3d ? 6 : 1; - // The world position of the integer center point of drawing in the noise - v2f world_center_of_drawing_in_noise_f = v2f( - center_of_drawing_in_noise_i.X * cloud_size, - center_of_drawing_in_noise_i.Y * cloud_size - ) + m_origin; - // Colors with primitive shading video::SColorf c_top_f(m_color); @@ -160,7 +162,7 @@ void Clouds::updateMesh() // Read noise - std::vector grid(m_cloud_radius_i * 2 * m_cloud_radius_i * 2); + m_grid.resize(m_cloud_radius_i * 2 * m_cloud_radius_i * 2); for(s16 zi = -m_cloud_radius_i; zi < m_cloud_radius_i; zi++) { u32 si = (zi + m_cloud_radius_i) * m_cloud_radius_i * 2 + m_cloud_radius_i; @@ -168,7 +170,7 @@ void Clouds::updateMesh() for (s16 xi = -m_cloud_radius_i; xi < m_cloud_radius_i; xi++) { u32 i = si + xi; - grid[i] = gridFilled( + m_grid[i] = gridFilled( xi + center_of_drawing_in_noise_i.X, zi + center_of_drawing_in_noise_i.Y ); @@ -205,7 +207,7 @@ void Clouds::updateMesh() u32 i = GETINDEX(xi, zi, m_cloud_radius_i); - if (!grid[i]) + if (!m_grid[i]) continue; v2f p0 = v2f(xi,zi)*cloud_size + world_center_of_drawing_in_noise_f; @@ -238,7 +240,7 @@ void Clouds::updateMesh() case 1: // back if (INAREA(xi, zi - 1, m_cloud_radius_i)) { u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); - if(grid[j]) + if(m_grid[j]) continue; } for (video::S3DVertex &vertex : v) { @@ -253,7 +255,7 @@ void Clouds::updateMesh() case 2: //right if (INAREA(xi + 1, zi, m_cloud_radius_i)) { u32 j = GETINDEX(xi+1, zi, m_cloud_radius_i); - if(grid[j]) + if(m_grid[j]) continue; } for (video::S3DVertex &vertex : v) { @@ -268,7 +270,7 @@ void Clouds::updateMesh() case 3: // front if (INAREA(xi, zi + 1, m_cloud_radius_i)) { u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i); - if(grid[j]) + if(m_grid[j]) continue; } for (video::S3DVertex &vertex : v) { @@ -283,7 +285,7 @@ void Clouds::updateMesh() case 4: // left if (INAREA(xi-1, zi, m_cloud_radius_i)) { u32 j = GETINDEX(xi-1, zi, m_cloud_radius_i); - if(grid[j]) + if(m_grid[j]) continue; } for (video::S3DVertex &vertex : v) { @@ -343,7 +345,6 @@ void Clouds::updateMesh() void Clouds::render() { -#if 0 if (m_params.density <= 0.0f) return; // no need to do anything @@ -389,12 +390,38 @@ void Clouds::render() cloud_full_radius*1.2, fog_density, fog_pixelfog, fog_rangefog); } +//#if 0 driver->drawMeshBuffer(m_meshbuffer.get()); - +//#endif // Restore fog settings driver->setFog(fog_color, fog_type, fog_start, fog_end, fog_density, fog_pixelfog, fog_rangefog); -#endif +} + +void Clouds::renderDepth() { + if (m_params.density <= 0.0f) + return; // no need to do anything + + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + + updateMesh(); + + // Update position + { + v2f off_origin = m_origin - m_mesh_origin; + v3f rel(off_origin.X, 0, off_origin.Y); + rel -= intToFloat(m_camera_offset, BS); + setPosition(rel); + updateAbsolutePosition(); + } + + video::SMaterial material = m_material; + material.MaterialType = video::EMT_SOLID; + material.ZWriteEnable = video::EZW_ON; + + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + driver->setMaterial(material); + driver->drawMeshBuffer(m_meshbuffer.get()); } void Clouds::step(float dtime) diff --git a/src/client/clouds.h b/src/client/clouds.h index 100f3fcbe..75b0f2a36 100644 --- a/src/client/clouds.h +++ b/src/client/clouds.h @@ -52,6 +52,8 @@ public: virtual void render(); + void renderDepth(); + virtual const aabb3f &getBoundingBox() const { return m_box; @@ -140,6 +142,16 @@ public: const video::SColor getColor() const { return m_color.toSColor(); } + bool getGrid(int x, int y) + { + int index = x + y * m_cloud_radius_i * 2; + if (index < 0 || index >= m_grid.size()) + return false; + return m_grid[index]; + } + + v2f getCloudOffset() const { return m_noise_position; } + private: void updateBox() { @@ -173,6 +185,7 @@ private: u16 m_cloud_radius_i; u32 m_seed; v3f m_camera_pos; + v2f m_noise_position; v3s16 m_camera_offset; bool m_camera_inside_cloud = false; @@ -180,4 +193,7 @@ private: bool m_enable_shaders, m_enable_3d; video::SColorf m_color = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); CloudParams m_params; + + std::vector m_grid; + }; diff --git a/src/client/game.cpp b/src/client/game.cpp index 252a59a0e..8a8fc29a4 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -383,11 +383,10 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter m_animation_timer_delta_pixel{"animationTimerDelta"}; CachedPixelShaderSetting m_artificial_light{ "artificialLight" }; CachedPixelShaderSetting m_day_light{"dayLight"}; - CachedPixelShaderSetting m_eye_position_pixel{ "eyePosition" }; - CachedVertexShaderSetting m_eye_position_vertex{ "eyePosition" }; CachedPixelShaderSetting m_minimap_yaw{"yawVec"}; - CachedPixelShaderSetting m_camera_offset_pixel{"cameraOffset"}; CachedVertexShaderSetting m_camera_offset_vertex{"cameraOffset"}; + CachedPixelShaderSetting m_camera_offset_pixel{ "cameraOffset" }; + CachedVertexShaderSetting m_camera_position_vertex{"cameraPosition"}; CachedPixelShaderSetting m_camera_position_pixel{"cameraPosition"}; CachedVertexShaderSetting m_camera_projinv_vertex{"mCameraProjInv"}; CachedPixelShaderSetting m_camera_projinv_pixel{"mCameraProjInv"}; @@ -420,6 +419,8 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_cloud_height_pixel{"cloudHeight"}; CachedPixelShaderSetting m_cloud_thickness_pixel{"cloudThickness"}; CachedPixelShaderSetting m_cloud_density_pixel{"cloudDensity"}; + CachedPixelShaderSetting m_cloud_offset_pixel{"cloudOffset"}; + CachedPixelShaderSetting m_cloud_radius_pixel{"cloudRadius"}; CachedPixelShaderSetting m_saturation_pixel{"saturation"}; float m_gamma; CachedPixelShaderSetting m_gamma_pixel{"gamma"}; @@ -432,6 +433,8 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_moon_brightness_pixel{"moonBrightness"}; CachedPixelShaderSetting m_volumetric_light_strength_pixel{"volumetricLightStrength"}; + CachedPixelShaderSetting + m_volumetric_cloud_color{"cloudColor"}; static constexpr std::array SETTING_CALLBACKS = { "exposure_compensation", @@ -501,20 +504,17 @@ public: m_animation_timer_delta_vertex.set(&animation_timer_delta_f, services); m_animation_timer_delta_pixel.set(&animation_timer_delta_f, services); - v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition(); - m_eye_position_pixel.set(epos, services); - m_eye_position_vertex.set(epos, services); - if (m_client->getMinimap()) { v3f minimap_yaw = m_client->getMinimap()->getYawVec(); m_minimap_yaw.set(minimap_yaw, services); } v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS); - m_camera_offset_pixel.set(offset, services); m_camera_offset_vertex.set(offset, services); + m_camera_offset_pixel.set(offset, services); v3f camera_position = m_client->getCamera()->getPosition(); + m_camera_position_vertex.set(camera_position, services); m_camera_position_pixel.set(camera_position, services); core::matrix4 camera_proj = m_client->getCamera()->getCameraNode()->getProjectionMatrix(); @@ -573,13 +573,19 @@ public: // TODO: settings Clouds* clouds = m_client->getClouds(); - if (m_client->getClouds()) { + if (clouds && g_settings->getBool("enable_volumetric_clouds")) { float cloud_height = clouds->getHeight() * 10.0f; m_cloud_height_pixel.set(&cloud_height, services); float cloud_thickness = clouds->getThickness() * 10.0f; m_cloud_thickness_pixel.set(&cloud_thickness, services); float cloud_density = clouds->getDensity(); m_cloud_density_pixel.set(&cloud_density, services); + v2f cloud_offset = clouds->getCloudOffset(); + m_cloud_offset_pixel.set(cloud_offset, services); + float cloud_radius = g_settings->getU16("cloud_radius"); + m_cloud_radius_pixel.set(&cloud_radius, services); + video::SColor cloud_color = clouds->getColor(); + m_volumetric_cloud_color.set(cloud_color, services); } if (m_volumetric_light_enabled) { @@ -4294,7 +4300,7 @@ void Game::updateClouds(float dtime) camera_node_position.Y = camera_node_position.Y + camera_offset.Y * BS; camera_node_position.Z = camera_node_position.Z + camera_offset.Z * BS; this->clouds->update(camera_node_position, this->sky->getCloudColor()); - if (this->clouds->isCameraInsideCloud() && this->fogEnabled()) { + if (this->clouds->isCameraInsideCloud() && this->fogEnabled() && !g_settings->getBool("enable_volumetric_clouds")) { // If camera is inside cloud and fog is enabled, use cloud's colors as sky colors. video::SColor clouds_dark = this->clouds->getColor().getInterpolated( video::SColor(255, 0, 0, 0), 0.9); diff --git a/src/client/render/pipeline.cpp b/src/client/render/pipeline.cpp index 8fccc7808..7700e8aeb 100644 --- a/src/client/render/pipeline.cpp +++ b/src/client/render/pipeline.cpp @@ -113,6 +113,18 @@ void TextureBuffer::swapTextures(u8 texture_a, u8 texture_b) m_textures[texture_b] = temp; } +void TextureBuffer::setTextureImage(u8 id, video::IImage* image) { + assert(m_definitions[id].valid); + + auto &definition = m_definitions[id]; + + if (m_textures[id]) m_driver->removeTexture(m_textures[id]); + + m_textures[id] = m_driver->addTexture(definition.name.c_str(), image); + definition.fixed_size = true; + definition.size = image->getDimension(); + definition.dirty = false; +} bool TextureBuffer::ensureTexture(video::ITexture **texture, const TextureDefinition& definition, PipelineContext &context) { @@ -183,6 +195,8 @@ void TextureBufferOutput::activate(PipelineContext &context) if (!render_target) render_target = driver->addRenderTarget(); + if (disable_clear) m_clear = false; + core::array textures; core::dimension2du size(0, 0); for (size_t i = 0; i < texture_map.size(); i++) { diff --git a/src/client/render/pipeline.h b/src/client/render/pipeline.h index abb108652..836b6c9b9 100644 --- a/src/client/render/pipeline.h +++ b/src/client/render/pipeline.h @@ -141,6 +141,7 @@ public: virtual video::ITexture *getTexture(u8 index) override; virtual void reset(PipelineContext &context) override; void swapTextures(u8 texture_a, u8 texture_b); + void setTextureImage(u8 id, video::IImage* image); private: static const u8 NO_DEPTH_TEXTURE = 255; @@ -182,6 +183,7 @@ public: TextureBufferOutput(TextureBuffer *buffer, const std::vector &texture_map, u8 depth_stencil); virtual ~TextureBufferOutput() override; void activate(PipelineContext &context) override; + void disableClearing() { disable_clear = true; } private: static const u8 NO_DEPTH_TEXTURE = 255; @@ -190,6 +192,7 @@ private: u8 depth_stencil { NO_DEPTH_TEXTURE }; video::IRenderTarget* render_target { nullptr }; video::IVideoDriver* driver { nullptr }; + bool disable_clear = false; }; /** diff --git a/src/client/render/secondstage.cpp b/src/client/render/secondstage.cpp index 0a03011c8..0e8b4f15b 100644 --- a/src/client/render/secondstage.cpp +++ b/src/client/render/secondstage.cpp @@ -24,64 +24,114 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/shader.h" #include "client/tile.h" #include "settings.h" +#include "noise.h" class NoiseStep : public RenderStep { public: - NoiseStep(u32 shader_id, u8 texture_id) : - shader_id(shader_id), texture_id(texture_id) + NoiseStep(TextureBuffer* buffer, u8 id, u32 size) : + buffer(buffer), id(id), size(size) { - material.UseMipMaps = false; - material.ZBuffer = true; - material.ZWriteEnable = video::EZW_ON; } - void setRenderSource(RenderSource* _source) override { - source = _source; + void setRenderSource(RenderSource* _source) override {} + + void setRenderTarget(RenderTarget* _target) override {} + + void reset(PipelineContext& context) override {} + + void run(PipelineContext& context) override + { + if (!needs_run) return; + + needs_run = false; + + video::IImage* noise_image = context.device->getVideoDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(256, 256)); + PseudoRandom random; + for (u32 i = 0; i < size * size; ++i) { + noise_image->setPixel(i % size, i / size, video::SColor(0, random.next() % 256, 0, 0)); + } + buffer->setTextureImage(id, noise_image); + noise_image->drop(); } - void setRenderTarget(RenderTarget* _target) override { +private: + u32 size; + u8 id; + TextureBuffer* buffer = nullptr; + bool needs_run = true; +}; + +class CloudDensityStep : public RenderStep { +public: + CloudDensityStep(TextureBuffer* buffer, u8 id, Clouds* clouds) : + buffer(buffer), id(id), clouds(clouds) + { + } + + void setRenderSource(RenderSource* _source) override {} + + void setRenderTarget(RenderTarget* _target) override {} + + void reset(PipelineContext& context) override {} + + void run(PipelineContext& context) override + { + u16 cloud_radius = g_settings->getU16("cloud_radius"); + if (cloud_radius < 1) cloud_radius = 1; + + video::IImage* image = context.device->getVideoDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(8 * cloud_radius, 8 * cloud_radius)); + + for (int x = 0; x < 2 * cloud_radius; ++x) { + for (int y = 0; y < 2 * cloud_radius; ++y) { + bool isFilled = clouds->getGrid(x, y); + + for (int i = 0; i < 16; ++i) { + int xp = x * 4 + i % 4; + int yp = y * 4 + i / 4; + + image->setPixel(xp, yp, video::SColor(255, isFilled * 255, 0, 0)); + } + } + } + + buffer->setTextureImage(id, image); + + image->drop(); + } + +private: + Clouds* clouds = nullptr; + u8 id = 0; + TextureBuffer* buffer = nullptr; +}; + +class CloudDepthStep : public RenderStep { +public: + CloudDepthStep(Clouds* clouds) : + clouds(clouds) + { + } + + void setRenderSource(RenderSource* _source) override {} + + void setRenderTarget(RenderTarget* _target) override + { target = _target; } void reset(PipelineContext& context) override {} - void run(PipelineContext& context) override { - video::ITexture* texture = source->getTexture(texture_id); - if (texture != last_texture) { - last_texture = texture; + void run(PipelineContext& context) override + { + if (target) + target->activate(context); - if (target) - target->activate(context); - - // attach the shader - material.MaterialType = context.client->getShaderSource()->getShaderInfo(shader_id).material; - - auto driver = context.device->getVideoDriver(); - - static const video::SColor color = video::SColor(0, 0, 0, 255); - static const video::S3DVertex vertices[4] = { - video::S3DVertex(1.0, -1.0, 0.0, 0.0, 0.0, -1.0, - color, 1.0, 0.0), - video::S3DVertex(-1.0, -1.0, 0.0, 0.0, 0.0, -1.0, - color, 0.0, 0.0), - video::S3DVertex(-1.0, 1.0, 0.0, 0.0, 0.0, -1.0, - color, 0.0, 1.0), - video::S3DVertex(1.0, 1.0, 0.0, 0.0, 0.0, -1.0, - color, 1.0, 1.0), - }; - static const u16 indices[6] = { 0, 1, 2, 2, 3, 0 }; - driver->setMaterial(material); - driver->drawVertexPrimitiveList(&vertices, 4, &indices, 2); - } + clouds->renderDepth(); } private: - u32 shader_id; - u8 texture_id; - video::SMaterial material; - video::ITexture* last_texture = nullptr; - RenderSource* source{ nullptr }; - RenderTarget* target{ nullptr }; + Clouds* clouds = nullptr; + RenderTarget* target = nullptr; }; PostProcessingStep::PostProcessingStep(u32 _shader_id, const std::vector &_texture_map) : @@ -160,6 +210,11 @@ void PostProcessingStep::setWrapRepeat(u8 index, bool value) { material.TextureLayers[index].TextureWrapV = value ? video::ETC_REPEAT : video::ETC_CLAMP_TO_EDGE; } +void PostProcessingStep::disableDepthTest() { + material.ZBuffer = video::ECFN_DISABLED; + material.ZWriteEnable = video::EZW_OFF; +} + RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep, v2f scale, Client *client) { auto buffer = pipeline->createOwned(); @@ -201,8 +256,8 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep const bool enable_ssaa = antialiasing == "ssaa"; const bool enable_fxaa = antialiasing == "fxaa"; const bool enable_volumetric_light = g_settings->getBool("enable_volumetric_lighting") && enable_bloom; - const bool enable_volumetric_clouds = true; - // TODO: Add clouds setting + // TODO: Proper constraints + const bool enable_volumetric_clouds = g_settings->getBool("enable_volumetric_clouds") && client->getClouds(); if (enable_ssaa) { u16 ssaa_scale = MYMAX(2, g_settings->getU16("fsaa")); @@ -226,22 +281,21 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep // post-processing stage u8 source = TEXTURE_COLOR; + + u8 final_color_source = TEXTURE_COLOR; if (enable_volumetric_clouds) { + const u16 cloud_radius = g_settings->getU16("cloud_radius"); + buffer->setTexture(TEXTURE_NOISE, core::dimension2du(256, 256), "noise", color_format); + pipeline->addStep(buffer, TEXTURE_NOISE, 256); - shader_id = client->getShaderSource()->getShader("noise_shader", TILE_MATERIAL_PLAIN, NDT_MESH); - RenderStep *noise_step = pipeline->addStep(shader_id, TEXTURE_NOISE); - noise_step->setRenderSource(buffer); - noise_step->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_NOISE)); + buffer->setTexture(TEXTURE_NOISE_COARSE, core::dimension2du(cloud_radius * 8, cloud_radius * 8), "noise_coarse", color_format); + pipeline->addStep(buffer, TEXTURE_NOISE_COARSE, client->getClouds()); - buffer->setTexture(TEXTURE_NOISE_COARSE, core::dimension2du(256, 256), "noise", color_format); + u32 undersampling = core::clamp(g_settings->getU32("volumetrics_undersampling"), (u32)1, (u32)4); - shader_id = client->getShaderSource()->getShader("coarse_noise_shader", TILE_MATERIAL_PLAIN, NDT_MESH); - noise_step = pipeline->addStep(shader_id, std::vector()); - noise_step->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_NOISE_COARSE)); - - buffer->setTexture(TEXTURE_CLOUDS_1, scale * 0.25f, "clouds_1", color_format, /*clear:*/ true); + buffer->setTexture(TEXTURE_CLOUDS_1, scale / (float)undersampling, "clouds_1", color_format, /*clear:*/ true); buffer->setTexture(TEXTURE_CLOUDS_2, scale, "clouds_2", color_format); buffer->setTexture(TEXTURE_CLOUD_DENSITY, scale, "cloud_density", color_format); @@ -253,16 +307,24 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep volumetric_clouds->setBilinearFilter(2, true); volumetric_clouds->setWrapRepeat(1, true); volumetric_clouds->setWrapRepeat(2, true); + volumetric_clouds->disableDepthTest(); source = TEXTURE_CLOUDS_1; shader_id = client->getShaderSource()->getShader("clouds_merge", TILE_MATERIAL_PLAIN, NDT_MESH); - PostProcessingStep* blend_clouds = pipeline->addStep(shader_id, std::vector { TEXTURE_CLOUDS_1, TEXTURE_COLOR }); + PostProcessingStep* blend_clouds = pipeline->addStep(shader_id, std::vector { TEXTURE_CLOUDS_1, TEXTURE_COLOR, TEXTURE_DEPTH }); blend_clouds->setRenderSource(buffer); blend_clouds->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_CLOUDS_2)); blend_clouds->setBilinearFilter(0, true); + blend_clouds->disableDepthTest(); + + CloudDepthStep* cloud_depth = pipeline->addStep(client->getClouds()); + TextureBufferOutput* cloud_depth_output = pipeline->createOwned(buffer, std::vector{ TEXTURE_COLOR }, TEXTURE_DEPTH); + cloud_depth_output->disableClearing(); + cloud_depth->setRenderTarget(cloud_depth_output); source = TEXTURE_CLOUDS_2; + final_color_source = TEXTURE_CLOUDS_2; } // common downsampling step for bloom or autoexposure @@ -281,7 +343,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep // get bright spots u32 shader_id = client->getShaderSource()->getShader("extract_bloom", TILE_MATERIAL_PLAIN, NDT_MESH); - auto extract_bloom = pipeline->addStep(shader_id, std::vector { source, TEXTURE_EXPOSURE_1 }); + RenderStep* extract_bloom = pipeline->addStep(shader_id, std::vector { source, TEXTURE_EXPOSURE_1 }); extract_bloom->setRenderSource(buffer); extract_bloom->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_BLOOM)); source = TEXTURE_BLOOM; @@ -332,14 +394,14 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep } // FXAA - u8 final_stage_source = TEXTURE_CLOUDS_2; + u8 final_stage_source = final_color_source; if (enable_fxaa) { final_stage_source = TEXTURE_FXAA; buffer->setTexture(TEXTURE_FXAA, scale, "fxaa", color_format); shader_id = client->getShaderSource()->getShader("fxaa", TILE_MATERIAL_PLAIN); - PostProcessingStep *effect = pipeline->createOwned(shader_id, std::vector { TEXTURE_COLOR }); + PostProcessingStep* effect = pipeline->createOwned(shader_id, std::vector { final_color_source }); pipeline->addStep(effect); effect->setBilinearFilter(0, true); effect->setRenderSource(buffer); @@ -348,7 +410,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep // final merge shader_id = client->getShaderSource()->getShader("second_stage", TILE_MATERIAL_PLAIN, NDT_MESH); - PostProcessingStep *effect = pipeline->createOwned(shader_id, std::vector { final_stage_source, TEXTURE_SCALE_UP, TEXTURE_EXPOSURE_2 }); + PostProcessingStep* effect = pipeline->createOwned(shader_id, std::vector { final_stage_source, TEXTURE_SCALE_UP, TEXTURE_EXPOSURE_2 }); pipeline->addStep(effect); if (enable_ssaa) effect->setBilinearFilter(0, true); diff --git a/src/client/render/secondstage.h b/src/client/render/secondstage.h index 04705f3ae..224b27e33 100644 --- a/src/client/render/secondstage.h +++ b/src/client/render/secondstage.h @@ -52,6 +52,10 @@ public: void setWrapRepeat(u8 index, bool value); + void setColor(video::SColor color); + + void disableDepthTest(); + private: u32 shader_id; std::vector texture_map; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index b0f651d85..baf1b1417 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -342,6 +342,7 @@ void set_default_settings() settings->setDefault("bloom_intensity", "0.05"); settings->setDefault("bloom_radius", "1"); settings->setDefault("enable_volumetric_lighting", "false"); + settings->setDefault("enable_volumetric_clouds", "false"); settings->setDefault("enable_bumpmaps", "false"); // Effects Shadows From e5afca89f783931370827d2113ff069917e93f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 18 Aug 2024 16:11:30 +0200 Subject: [PATCH 07/40] Minor changes --- .../shaders/clouds_merge/opengl_fragment.glsl | 4 ++++ .../shaders/nodes_shader/opengl_fragment.glsl | 4 +++- client/shaders/nodes_shader/opengl_vertex.glsl | 14 ++++++++++++++ .../shaders/object_shader/opengl_fragment.glsl | 3 ++- client/shaders/object_shader/opengl_vertex.glsl | 17 +++++++++++++++++ .../volumetric_clouds/opengl_fragment.glsl | 5 +++++ src/client/render/secondstage.cpp | 1 + src/client/shader.cpp | 4 ++++ 8 files changed, 50 insertions(+), 2 deletions(-) diff --git a/client/shaders/clouds_merge/opengl_fragment.glsl b/client/shaders/clouds_merge/opengl_fragment.glsl index a3c597a66..cc78de2b6 100644 --- a/client/shaders/clouds_merge/opengl_fragment.glsl +++ b/client/shaders/clouds_merge/opengl_fragment.glsl @@ -48,6 +48,9 @@ vec4 sampleClouds(vec2 uv) { } vec4 getClouds(vec2 uv) { +#if (VOLUMETRICS_UNDERSAMPLING <= 1) + return sampleClouds(uv); +#else return sampleClouds(uv - texelSize0 * vec2(-1.0, -1.0)) / 9.0 + sampleClouds(uv - texelSize0 * vec2( 0.0, -1.0)) / 9.0 + @@ -58,6 +61,7 @@ vec4 getClouds(vec2 uv) { sampleClouds(uv - texelSize0 * vec2(-1.0, 1.0)) / 9.0 + sampleClouds(uv - texelSize0 * vec2( 0.0, 1.0)) / 9.0 + sampleClouds(uv - texelSize0 * vec2( 1.0, 1.0)) / 9.0; +#endif } void main(void) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index cc3af027c..4c591d4e0 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -8,6 +8,8 @@ uniform sampler2D baseTexture; uniform vec2 texelSize0; +varying vec3 sunTint; + uniform vec3 dayLight; uniform lowp vec4 fogColor; uniform float fogDistance; @@ -485,7 +487,7 @@ void main(void) // calculate fragment color from components: col.rgb = adjusted_night_ratio * col.rgb + // artificial light - (1.0 - adjusted_night_ratio) * ( // natural light + sunTint * (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 } diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 415c51c29..4d13f1142 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -45,6 +45,7 @@ varying float area_enable_parallax; varying highp vec3 eyeVec; varying float nightRatio; +varying vec3 sunTint; // Color of the light emitted by the light sources. uniform vec3 artificialLight; const float e = 2.718281828459; @@ -145,8 +146,19 @@ float snoise(vec3 p) #endif +vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) +{ + // Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham + const float beta_r0 = 1e-5; // Rayleigh scattering beta + // These factors are calculated based on expected value of scattering factor of 1e-5 + // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere + const vec3 beta_r0_l = vec3(3.3362176e-01, 8.75378289198826e-01, 1.95342379700656) * beta_r0; // wavelength-dependent scattering + const float atmosphere_height = 15000.; // height of the atmosphere in meters + // sun/moon light at the ground level, after going through the atmosphere + return exp(-beta_r0_l * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); +} void main(void) { @@ -259,6 +271,7 @@ void main(void) shadow_position.z -= z_bias; perspective_factor = pFactor; + sunTint = vec3(1.0); if (f_timeofday < 0.21) { adj_shadow_strength = f_shadow_strength * 0.5 * (1.0 - mtsmoothstep(0.18, 0.21, f_timeofday)); @@ -269,6 +282,7 @@ void main(void) adj_shadow_strength = f_shadow_strength * mtsmoothstep(0.21, 0.26, f_timeofday) * (1.0 - mtsmoothstep(0.743, 0.793, f_timeofday)); + sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), min(1.0, 4.0 * adj_shadow_strength)); } } #endif diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 2b8af3fa9..db58d174f 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -1,5 +1,6 @@ uniform sampler2D baseTexture; +varying vec3 sunTint; uniform vec3 dayLight; uniform lowp vec4 fogColor; uniform float fogDistance; @@ -431,7 +432,7 @@ void main(void) // calculate fragment color from components: col.rgb = adjusted_night_ratio * col.rgb + // artificial light - (1.0 - adjusted_night_ratio) * ( // natural light + sunTint * (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 } diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index 1cefb13fa..fe55f2bad 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -32,6 +32,7 @@ centroid varying vec2 varTexCoord; varying highp vec3 eyeVec; varying float nightRatio; +varying vec3 sunTint; // Color of the light emitted by the light sources. uniform vec3 artificialLight; varying float vIDiff; @@ -89,6 +90,20 @@ float directional_ambient(vec3 normal) return dot(v, vec3(0.670820, 1.000000, 0.836660)); } +vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) +{ + // Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham + const float beta_r0 = 1e-5; // Rayleigh scattering beta + + // These factors are calculated based on expected value of scattering factor of 1e-5 + // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere + const vec3 beta_r0_l = vec3(3.3362176e-01, 8.75378289198826e-01, 1.95342379700656) * beta_r0; // wavelength-dependent scattering + + const float atmosphere_height = 15000.; // height of the atmosphere in meters + // sun/moon light at the ground level, after going through the atmosphere + return exp(-beta_r0_l * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); +} + void main(void) { varTexCoord = (mTexture * inTexCoord0).st; @@ -162,6 +177,7 @@ void main(void) shadow_position.z -= z_bias; perspective_factor = pFactor; + sunTint = vec3(1.0); if (f_timeofday < 0.21) { adj_shadow_strength = f_shadow_strength * 0.5 * (1.0 - mtsmoothstep(0.18, 0.21, f_timeofday)); @@ -172,6 +188,7 @@ void main(void) adj_shadow_strength = f_shadow_strength * mtsmoothstep(0.21, 0.26, f_timeofday) * (1.0 - mtsmoothstep(0.743, 0.793, f_timeofday)); + sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), min(1.0, 4.0 * adj_shadow_strength)); } } #endif diff --git a/client/shaders/volumetric_clouds/opengl_fragment.glsl b/client/shaders/volumetric_clouds/opengl_fragment.glsl index 397a7fbc3..7f7e69ab4 100644 --- a/client/shaders/volumetric_clouds/opengl_fragment.glsl +++ b/client/shaders/volumetric_clouds/opengl_fragment.glsl @@ -137,10 +137,15 @@ void main(void) float bottomPlaneIntersect = clamp((cloudHeight - cameraPosition.y) / viewVec.y, 0., 4. * fogDistance); float topPlaneIntersect = clamp((cloudHeight + cloudThickness - cameraPosition.y) / viewVec.y, 0., 4. * fogDistance); +#if (VOLUMETRICS_UNDERSAMPLING <= 1) + bottomPlaneIntersect = min(depth, bottomPlaneIntersect); + topPlaneIntersect = min(depth, topPlaneIntersect); +#else if ((bottomPlaneIntersect > depth + 5.0) != (topPlaneIntersect > depth + 5.0)) { bottomPlaneIntersect = min(depth, bottomPlaneIntersect); topPlaneIntersect = min(depth, topPlaneIntersect); } +#endif float startDepth = min(bottomPlaneIntersect, topPlaneIntersect); float endDepth = max(bottomPlaneIntersect, topPlaneIntersect); diff --git a/src/client/render/secondstage.cpp b/src/client/render/secondstage.cpp index 0e8b4f15b..082c4c11c 100644 --- a/src/client/render/secondstage.cpp +++ b/src/client/render/secondstage.cpp @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "noise.h" +// TODO: Probably this could still be improved, having a step for this seems silly class NoiseStep : public RenderStep { public: NoiseStep(TextureBuffer* buffer, u8 id, u32 size) : diff --git a/src/client/shader.cpp b/src/client/shader.cpp index c4ba54d2b..2493001e5 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -728,6 +728,10 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, shaders_header << "#define VOLUMETRIC_LIGHT 1\n"; } + if (g_settings->getBool("enable_volumetric_clouds")) { + shaders_header << "#define VOLUMETRICS_UNDERSAMPLING " << g_settings->getU32("volumetrics_undersampling") << '\n'; + } + shaders_header << "#line 0\n"; // reset the line counter for meaningful diagnostics std::string common_header = shaders_header.str(); From ed4cc81c23e594c89d17cac3c4a1e3649894a398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Thu, 29 Aug 2024 17:35:35 +0200 Subject: [PATCH 08/40] Minimap shenanigans Half broken lol --- .../minimap_shader/opengl_fragment.glsl | 21 +++++++++++-------- src/client/game.cpp | 3 +++ src/client/minimap.cpp | 5 +++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/client/shaders/minimap_shader/opengl_fragment.glsl b/client/shaders/minimap_shader/opengl_fragment.glsl index 3f6b041da..88c827138 100644 --- a/client/shaders/minimap_shader/opengl_fragment.glsl +++ b/client/shaders/minimap_shader/opengl_fragment.glsl @@ -1,16 +1,17 @@ uniform sampler2D baseTexture; uniform sampler2D normalTexture; uniform vec3 yawVec; +uniform float mapSize; varying lowp vec4 varColor; varying mediump vec2 varTexCoord; void main (void) { - vec2 uv = varTexCoord.st; + vec2 uv = varTexCoord; //texture sampling rate - const float step = 1.0 / 256.0; + float step = 1.0 / mapSize; float tl = texture2D(normalTexture, vec2(uv.x - step, uv.y + step)).r; float t = texture2D(normalTexture, vec2(uv.x, uv.y + step)).r; float tr = texture2D(normalTexture, vec2(uv.x + step, uv.y + step)).r; @@ -19,17 +20,19 @@ void main (void) float b = texture2D(normalTexture, vec2(uv.x, uv.y - step)).r; float bl = texture2D(normalTexture, vec2(uv.x - step, uv.y - step)).r; float l = texture2D(normalTexture, vec2(uv.x - step, uv.y )).r; - float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl); - float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr); - vec4 bump = vec4 (normalize(vec3 (dX, dY, 0.1)),1.0); + float c = texture2D(normalTexture, vec2(uv.x , uv.y )).r; + float AO = 50.0 * (clamp(t - c, -0.001, 0.001) + clamp(b - c, -0.001, 0.001) + clamp(r - c, -0.001, 0.001) + clamp(l - c, -0.001, 0.001)); + float dX = 4.0 * (l - r); + float dY = 4.0 * (t - b); + vec3 bump = normalize(vec3 (dX, dY, 0.1)); float height = 2.0 * texture2D(normalTexture, vec2(uv.x, uv.y)).r - 1.0; vec4 base = texture2D(baseTexture, uv).rgba; - vec3 L = normalize(vec3(0.0, 0.75, 1.0)); + vec3 L = normalize(vec3(0.0, 0.0, 1.0)); float specular = pow(clamp(dot(reflect(L, bump.xyz), yawVec), 0.0, 1.0), 1.0); - float diffuse = dot(yawVec, bump.xyz); + float diffuse = dot(yawVec, bump); - vec3 color = (1.1 * diffuse + 0.05 * height + 0.5 * specular) * base.rgb; - vec4 col = vec4(color.rgb, base.a); + vec3 color = (1.1 * diffuse + 0.05 * height + 0.5 * specular + AO) * base.rgb; + vec4 col = vec4(color, base.a); col *= varColor; gl_FragColor = vec4(col.rgb, base.a); } diff --git a/src/client/game.cpp b/src/client/game.cpp index 8a8fc29a4..0de80dfbb 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -384,6 +384,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_artificial_light{ "artificialLight" }; CachedPixelShaderSetting m_day_light{"dayLight"}; CachedPixelShaderSetting m_minimap_yaw{"yawVec"}; + CachedPixelShaderSetting m_minimap_size{"mapSize"}; CachedVertexShaderSetting m_camera_offset_vertex{"cameraOffset"}; CachedPixelShaderSetting m_camera_offset_pixel{ "cameraOffset" }; CachedVertexShaderSetting m_camera_position_vertex{"cameraPosition"}; @@ -507,6 +508,8 @@ public: if (m_client->getMinimap()) { v3f minimap_yaw = m_client->getMinimap()->getYawVec(); m_minimap_yaw.set(minimap_yaw, services); + float minimap_size = m_client->getMinimap()->getModeDef().map_size; + m_minimap_size.set(&minimap_size, services); } v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS); diff --git a/src/client/minimap.cpp b/src/client/minimap.cpp index afac89843..bc43b7221 100644 --- a/src/client/minimap.cpp +++ b/src/client/minimap.cpp @@ -607,8 +607,8 @@ void Minimap::drawMinimap(core::rect rect) video::SMaterial &material = m_meshbuffer->getMaterial(); material.forEachTexture([] (auto &tex) { - tex.MinFilter = video::ETMINF_LINEAR_MIPMAP_LINEAR; - tex.MagFilter = video::ETMAGF_LINEAR; + tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; + tex.MagFilter = video::ETMAGF_NEAREST; }); material.Lighting = false; material.TextureLayers[0].Texture = minimap_texture; @@ -648,6 +648,7 @@ void Minimap::drawMinimap(core::rect rect) driver->setTransform(video::ETS_WORLD, matrix); driver->setMaterial(material); driver->drawMeshBuffer(m_meshbuffer); + driver->drawMeshBuffer(m_meshbuffer); // Reset transformations driver->setTransform(video::ETS_VIEW, oldViewMat); From da1a688493e9e6685c99f6a6b4d86cc2d22eba57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Wed, 25 Sep 2024 21:45:13 +0200 Subject: [PATCH 09/40] Fix stuff and slight changes --- .../shaders/nodes_shader/opengl_fragment.glsl | 42 ++++--------------- src/client/clouds.cpp | 8 ++-- src/client/game.cpp | 6 +-- 3 files changed, 12 insertions(+), 44 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index c42e87a1b..f06f92f0a 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -59,7 +59,7 @@ varying highp vec3 eyeVec; varying float nightRatio; #ifdef ENABLE_DYNAMIC_SHADOWS -#if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS) && ENABLE_WAVING_WATER) +#if ((defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS) && ENABLE_WAVING_WATER) || defined(ENABLE_BUMPMAPS)) vec4 perm(vec4 x) { return mod(((x * 34.0) + 1.0) * x, 289.0); @@ -103,36 +103,6 @@ vec2 wave_noise(vec3 p, float off) { } #endif -#ifdef ENABLE_BUMPMAPS -vec4 perm(vec4 x) -{ - return mod(((x * 34.0) + 1.0) * x, 289.0); -} - -float snoise(vec3 p) -{ - vec3 a = floor(p); - vec3 d = p - a; - d = d * d * (3.0 - 2.0 * d); - - vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0); - vec4 k1 = perm(b.xyxy); - vec4 k2 = perm(k1.xyxy + b.zzww); - - vec4 c = k2 + a.zzzz; - vec4 k3 = perm(c); - vec4 k4 = perm(c + 1.0); - - vec4 o1 = fract(k3 * (1.0 / 41.0)); - vec4 o2 = fract(k4 * (1.0 / 41.0)); - - vec4 o3 = o2 * d.z + o1 * (1.0 - d.z); - vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x); - - return o4.y * d.y + o4.x * (1.0 - d.y); -} -#endif - // assuming near is always 1.0 float getLinearDepth() { @@ -474,17 +444,19 @@ void main(void) // Fragment normal, can differ from vNormal which is derived from vertex normals. vec3 fNormal = vNormal; +#if ((defined(ENABLE_DYNAMIC_SHADOWS) && defined(ENABLE_BUMPMAPS)) && !defined(MATERIAL_LIQUID)) vec2 dr = vec2(0.25) * texelSize0; - // Sample the texture to then compute the derivative + // Sample the texture to then compute the gradient float fx0y0 = texture2D(baseTexture, uv).r; float fx1y0 = texture2D(baseTexture, uv + vec2(dr.x, 0.0)).r; float fx0y1 = texture2D(baseTexture, uv + vec2(0.0, dr.y)).r; + vec2 gradient = 0.2 * vec2((fx1y0 - fx0y0) / dr.x, (fx0y1 - fx0y0) / dr.y) + 0.1 * gnoise(vec3(2.0 * uv / texelSize0, 0.0)).xy; // Compute a set of orthogonal basis vectors representing the node's surface plane. vec3 orth1 = normalize(cross(vNormal, mix(vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, -1.0), step(0.9, abs(vNormal.y))))); vec3 orth2 = normalize(cross(vNormal, orth1)); // The normal is computed using the partial derivatives along the texture space x and y axes. // These axes in world space are assumed to be parallel to the basis vectors we defined before. - fNormal = normalize(vNormal + (orth1 * (fx1y0 - fx0y0) / dr.x + orth2 * (fx0y1 - fx0y0) / dr.y) * 0.25 * snoise(vec3(uv / texelSize0, 0.0))); + fNormal = normalize(vNormal + orth1 * gradient.x + orth2 * gradient.y); float adj_cosLight = max(1e-5, dot(fNormal, -v_LightDirection)); #else float adj_cosLight = cosLight; @@ -578,7 +550,7 @@ void main(void) // Sky reflection col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.5 * brightness_factor; - vec3 water_reflect_color = 12.0 * dayLight * fresnel_factor * mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)) * max(1.0 - shadow_uncorrected, 0.0); + vec3 water_reflect_color = 12.0 * sunTint * dayLight * fresnel_factor * mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)) * max(1.0 - shadow_uncorrected, 0.0); // This line exists to prevent ridiculously bright reflection colors. water_reflect_color /= clamp(max(water_reflect_color.r, max(water_reflect_color.g, water_reflect_color.b)) * 0.375, 1.0, 400.0); @@ -593,7 +565,7 @@ void main(void) const float fresnel_exponent = 4.0; col.rgb += - intensity * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) * f_adj_shadow_strength * + sunTint * intensity * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) * f_adj_shadow_strength * pow(max(dot(reflect_ray, viewVec), 0.0), fresnel_exponent) * pow(1.0 - abs(dot(viewVec, fNormal)), specular_exponent); } #endif diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index ebea5aaeb..1bbd5f206 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -247,7 +247,7 @@ void Clouds::updateMesh() case 1: // back if (INAREA(xi, zi - 1, m_cloud_radius_i)) { u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); - if (grid[j]) + if (m_grid[j]) continue; } if (soft_clouds_enabled) { @@ -270,7 +270,7 @@ void Clouds::updateMesh() case 2: //right if (INAREA(xi + 1, zi, m_cloud_radius_i)) { u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i); - if (grid[j]) + if (m_grid[j]) continue; } if (soft_clouds_enabled) { @@ -294,7 +294,7 @@ void Clouds::updateMesh() case 3: // front if (INAREA(xi, zi + 1, m_cloud_radius_i)) { u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i); - if (grid[j]) + if (m_grid[j]) continue; } if (soft_clouds_enabled) { @@ -317,7 +317,7 @@ void Clouds::updateMesh() case 4: // left if (INAREA(xi - 1, zi, m_cloud_radius_i)) { u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i); - if (grid[j]) + if (m_grid[j]) continue; } if (soft_clouds_enabled) { diff --git a/src/client/game.cpp b/src/client/game.cpp index 0761f700f..3c4f42031 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -536,10 +536,6 @@ public: float camera_far = m_client->getCamera()->getCameraNode()->getFarValue(); m_camera_far_pixel.set(&camera_far, services); - v3f camera_position = m_client->getCamera()->getPosition(); - m_camera_position_pixel.set(camera_position, services); - m_camera_position_pixel.set(camera_position, services); - SamplerLayer_t tex_id; tex_id = 0; m_texture0.set(&tex_id, services); @@ -1592,7 +1588,7 @@ bool Game::createClient(const GameStartData &start_data) */ if (m_cache_enable_clouds) clouds = make_irr(smgr, shader_src, -1, rand()); - client->setClouds(clouds); + client->setClouds(clouds.get()); /* Skybox */ From 1bf1d0b2ff756b15453ebcc9daa9bd4c418d0360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Tue, 1 Oct 2024 20:00:24 +0200 Subject: [PATCH 10/40] Remove volumetrics stuff and some changes --- builtin/settingtypes.txt | 31 +- .../shaders/clouds_merge/opengl_fragment.glsl | 87 ---- .../shaders/clouds_merge/opengl_vertex.glsl | 48 --- .../shaders/nodes_shader/opengl_fragment.glsl | 22 +- .../object_shader/opengl_fragment.glsl | 15 +- .../shaders/soft_clouds/opengl_fragment.glsl | 22 + client/shaders/soft_clouds/opengl_vertex.glsl | 24 ++ .../volumetric_clouds/opengl_fragment.glsl | 214 ---------- .../volumetric_clouds/opengl_vertex.glsl | 37 -- src/client/client.h | 5 - src/client/clouds.cpp | 385 ++++++++++-------- src/client/clouds.h | 28 -- src/client/game.cpp | 22 +- src/client/render/pipeline.cpp | 15 - src/client/render/pipeline.h | 2 - src/client/render/secondstage.cpp | 187 +-------- src/client/render/secondstage.h | 7 - src/client/shader.cpp | 7 +- src/defaultsettings.cpp | 2 +- src/network/clientpackethandler.cpp | 4 +- src/server.cpp | 4 +- 21 files changed, 311 insertions(+), 857 deletions(-) delete mode 100644 client/shaders/clouds_merge/opengl_fragment.glsl delete mode 100644 client/shaders/clouds_merge/opengl_vertex.glsl create mode 100644 client/shaders/soft_clouds/opengl_fragment.glsl create mode 100644 client/shaders/soft_clouds/opengl_vertex.glsl delete mode 100644 client/shaders/volumetric_clouds/opengl_fragment.glsl delete mode 100644 client/shaders/volumetric_clouds/opengl_vertex.glsl diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 187e1f45f..da3a23324 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -510,9 +510,10 @@ water_wave_length (Waving liquids wavelength) float 20.0 0.1 # Requires: shaders, enable_waving_water water_wave_speed (Waving liquids wave speed) float 5.0 -# When enabled, liquid reflections are simulated. +# When enabled, crude liquid reflections are simulated. +# When waving liquids are enabled, the wave parameters will affect these reflections. # -# Requires: shaders, enable_waving_water, enable_dynamic_shadows +# Requires: shaders, enable_dynamic_shadows enable_water_reflections (Liquid reflections) bool false [**Dynamic shadows] @@ -684,39 +685,25 @@ bloom_strength_factor (Bloom Strength Factor) float 1.0 0.1 10.0 # Requires: shaders, enable_post_processing, enable_bloom bloom_radius (Bloom Radius) float 1 0.1 8 -[**Volumetric Effects] - # Set to true to enable volumetric lighting effect (a.k.a. "Godrays"). # # Requires: shaders, enable_post_processing, enable_bloom enable_volumetric_lighting (Volumetric Lighting) bool false -# Set to true to render clouds as scatter volumes. -# -# Requires: shaders, enable_post_processing, enable_clouds -enable_volumetric_clouds (Volumetric Clouds) bool false - -# Higher values reduce visual quality and may introduce artifacts, but improve performance of volumetric cloud/aurora effects. -# Range: from 1 to 4, default: 2 -# -# Requires: shaders, enable_post_processing -volumetrics_undersampling (Volumetric Undersampling) int 2 1 4 - -# Set to true to render volumetric auroras ("Northern Lights"). -# -# Requires: shaders, enable_post_processing -enable_volumetric_auroras (Volumetric Auroras) bool false - [**Other Effects] +# Makes the color of light fog more saturated. +# +# Requires: shaders +enable_tinted_fog (Tinted fog) bool false + # Apply bump maps to nodes based on their textures. It is recommended to use a tilted sun orbit to go with this (Sky Body Orbit Tilt). # # Requires: shaders, enable_dynamic_shadows enable_bumpmaps (Bump maps) bool false -[**Other Effects] - # Simulate translucency when looking at foliage in the sunlight. +# It is recommended to use this with the leaves style set to fancy. # # Requires: shaders, enable_dynamic_shadows enable_translucent_foliage (Translucent foliage) bool false diff --git a/client/shaders/clouds_merge/opengl_fragment.glsl b/client/shaders/clouds_merge/opengl_fragment.glsl deleted file mode 100644 index cc78de2b6..000000000 --- a/client/shaders/clouds_merge/opengl_fragment.glsl +++ /dev/null @@ -1,87 +0,0 @@ -#define cloudsTexture texture0 -#define sceneTexture texture1 -#define depthmap texture2 - -uniform sampler2D cloudsTexture; -uniform sampler2D sceneTexture; -uniform sampler2D depthmap; -uniform vec2 texelSize0; - -uniform vec3 dayLight; -uniform vec3 cloudColor; - -varying vec2 screenspaceCoordinate; -varying vec3 relativePosition; -varying vec3 viewDirection; -varying vec3 sunTint; -varying float auroraFactor; - -uniform vec3 cameraOffset; -uniform vec3 cameraPosition; - -uniform float cameraNear; -uniform float cameraFar; - -uniform float cloudHeight; -uniform float cloudThickness; - -float getDepth(vec2 screenspacePosition) { - float depth = texture2D(depthmap, screenspacePosition * 0.5 + 0.5).r; - return cameraNear * cameraFar / (cameraFar + depth * (cameraNear - cameraFar)); -} - -vec4 sampleClouds(vec2 uv) { - vec4 cloudsKey = texture2D(cloudsTexture, uv); - - //const vec3 darkColor = vec3(0.05, 0.1, 0.2); - vec3 darkColor = vec3(0.2, 0.4, 0.8) * dayLight; - const vec3 auroraDark = vec3(0., 0.5, 0.5); - const vec3 auroraBright = vec3(0., 0.5, .0); - - //const vec3 auroraDark = vec3(0.); - //const vec3 auroraBright = vec3(0.); - - return vec4( - mix(auroraDark, auroraBright, cloudsKey.b) * cloudsKey.b * auroraFactor + - cloudsKey.r * cloudColor * (darkColor * max(0., 1. - cloudsKey.g) + dayLight * sunTint * cloudsKey.g), - cloudsKey.r); -} - -vec4 getClouds(vec2 uv) { -#if (VOLUMETRICS_UNDERSAMPLING <= 1) - return sampleClouds(uv); -#else - return - sampleClouds(uv - texelSize0 * vec2(-1.0, -1.0)) / 9.0 + - sampleClouds(uv - texelSize0 * vec2( 0.0, -1.0)) / 9.0 + - sampleClouds(uv - texelSize0 * vec2( 1.0, -1.0)) / 9.0 + - sampleClouds(uv - texelSize0 * vec2(-1.0, 0.0)) / 9.0 + - sampleClouds(uv - texelSize0 * vec2( 0.0, 0.0)) / 9.0 + - sampleClouds(uv - texelSize0 * vec2( 1.0, 0.0)) / 9.0 + - sampleClouds(uv - texelSize0 * vec2(-1.0, 1.0)) / 9.0 + - sampleClouds(uv - texelSize0 * vec2( 0.0, 1.0)) / 9.0 + - sampleClouds(uv - texelSize0 * vec2( 1.0, 1.0)) / 9.0; -#endif -} - -void main(void) -{ - vec3 viewVec = normalize(relativePosition); - - vec3 position = cameraOffset + cameraPosition; - - float depth = getDepth(screenspaceCoordinate) / normalize(viewDirection).z; - float bottomPlaneIntersect = max((cloudHeight - cameraPosition.y) / viewVec.y, 0.); - float topPlaneIntersect = max((cloudHeight + cloudThickness - cameraPosition.y) / viewVec.y, 0.); - float minPlane = min(bottomPlaneIntersect, topPlaneIntersect); - - vec4 sceneColor = texture2D(sceneTexture, screenspaceCoordinate * 0.5 + 0.5); - - if (depth > minPlane) { - vec4 finalColor = getClouds(screenspaceCoordinate * 0.5 + 0.5); - - gl_FragColor = vec4(sceneColor.rgb * (1. - finalColor.a) + finalColor.rgb, 1.); - } else { - gl_FragColor = sceneColor; - } -} diff --git a/client/shaders/clouds_merge/opengl_vertex.glsl b/client/shaders/clouds_merge/opengl_vertex.glsl deleted file mode 100644 index dc0516dfb..000000000 --- a/client/shaders/clouds_merge/opengl_vertex.glsl +++ /dev/null @@ -1,48 +0,0 @@ -uniform mat4 mCameraProjInv; -uniform mat4 mCameraView; -uniform vec3 v_LightDirection; -uniform float f_timeofday; - -varying vec3 relativePosition; -varying vec3 viewDirection; -varying vec2 screenspaceCoordinate; -varying vec3 sunTint; -varying float auroraFactor; - -vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) -{ - // Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham - const float beta_r0 = 1e-5; // Rayleigh scattering beta - - // These factors are calculated based on expected value of scattering factor of 1e-5 - // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere - const vec3 beta_r0_l = vec3(3.3362176e-01, 8.75378289198826e-01, 1.95342379700656) * beta_r0; // wavelength-dependent scattering - - const float atmosphere_height = 15000.; // height of the atmosphere in meters - // sun/moon light at the ground level, after going through the atmosphere - return exp(-beta_r0_l * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); -} - -// 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) -{ - float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); - return t * t * (3.0 - 2.0 * t); -} - -void main(void) -{ - vec4 p = mCameraProjInv * inVertexPosition; - viewDirection = p.xyz / p.w; - relativePosition = (p.xyz / p.w) * mat3(mCameraView); - screenspaceCoordinate = inVertexPosition.xy; - - auroraFactor = 1. - mtsmoothstep(0.13, 0.15, f_timeofday) * mtsmoothstep(0.87, 0.85, f_timeofday); - - float tintFactor = mtsmoothstep(0.21, 0.24, f_timeofday) * mtsmoothstep(0.793, 0.753, f_timeofday); - - sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), tintFactor); - - gl_Position = inVertexPosition; -} diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index f06f92f0a..6be928538 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -59,7 +59,7 @@ varying highp vec3 eyeVec; varying float nightRatio; #ifdef ENABLE_DYNAMIC_SHADOWS -#if ((defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS) && ENABLE_WAVING_WATER) || defined(ENABLE_BUMPMAPS)) +#if ((defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS)) || defined(ENABLE_BUMPMAPS)) vec4 perm(vec4 x) { return mod(((x * 34.0) + 1.0) * x, 289.0); @@ -450,7 +450,7 @@ void main(void) float fx0y0 = texture2D(baseTexture, uv).r; float fx1y0 = texture2D(baseTexture, uv + vec2(dr.x, 0.0)).r; float fx0y1 = texture2D(baseTexture, uv + vec2(0.0, dr.y)).r; - vec2 gradient = 0.2 * vec2((fx1y0 - fx0y0) / dr.x, (fx0y1 - fx0y0) / dr.y) + 0.1 * gnoise(vec3(2.0 * uv / texelSize0, 0.0)).xy; + vec2 gradient = 0.1 * vec2((fx1y0 - fx0y0) / dr.x, (fx0y1 - fx0y0) / dr.y) + 0.05 * gnoise(vec3(2.0 * uv / texelSize0, 0.0)).xy; // Compute a set of orthogonal basis vectors representing the node's surface plane. vec3 orth1 = normalize(cross(vNormal, mix(vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, -1.0), step(0.9, abs(vNormal.y))))); vec3 orth2 = normalize(cross(vNormal, orth1)); @@ -529,7 +529,14 @@ void main(void) vec3 viewVec = normalize(worldPosition + cameraOffset - cameraPosition); // Water reflections -#if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS) && ENABLE_WAVING_WATER) +#if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS)) + +#if !ENABLE_WAVING_WATER +#define WATER_WAVE_HEIGHT 0.5 +#define WATER_WAVE_SPEED 5.0 +#define WATER_WAVE_LENGTH 10.0 +#endif + vec3 wavePos = worldPosition * vec3(2.0, 0.0, 2.0); float off = animationTimer * WATER_WAVE_SPEED * 10.0; wavePos.x /= WATER_WAVE_LENGTH * 3.0; @@ -560,7 +567,8 @@ void main(void) #if (defined(ENABLE_NODE_SPECULAR) && !defined(MATERIAL_WAVING_LIQUID)) // Apply specular to blocks. if (dot(v_LightDirection, vNormal) < 0.0) { - float intensity = 2.0 * (1.0 - (base.r * varColor.r)); + // This intensity is a placeholder and should be replaced by proper specular maps. + float intensity = 4.0 * min(1.0, length(varColor.rgb * base.rgb)); const float specular_exponent = 5.0; const float fresnel_exponent = 4.0; @@ -588,6 +596,8 @@ void main(void) // Note: clarity = (1 - fogginess) float clarity = clamp(fogShadingParameter - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); + +#ifdef ENABLE_TINTED_FOG float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b); // Prevent zero division. if (fogColorMax < 0.0000001) fogColorMax = 1.0; @@ -595,6 +605,10 @@ void main(void) // For this to not make the fog color artificially dark we need to normalize using the // fog color's brightest value. We then blend our base color with this to make the fog. col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity); +#else + col = mix(fogColor, col, clarity); +#endif + col = vec4(col.rgb, base.a); gl_FragData[0] = col; diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 1ac05dfed..b963b1ed5 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -21,7 +21,6 @@ uniform float animationTimer; uniform vec4 CameraPos; uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias1; - uniform vec3 shadow_tint; varying float adj_shadow_strength; varying float cosLight; @@ -433,8 +432,8 @@ void main(void) // calculate fragment color from components: col.rgb = adjusted_night_ratio * col.rgb + // artificial light - sunTint * (1.0 - adjusted_night_ratio) * ( // natural light - col.rgb * (1.0 - shadow_int * (1.0 - shadow_color) * (1.0 - shadow_tint)) + // filtered texture color + (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 @@ -450,13 +449,9 @@ void main(void) // Note: clarity = (1 - fogginess) float clarity = clamp(fogShadingParameter - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b); - // Prevent zero division. - if (fogColorMax < 0.0000001) fogColorMax = 1.0; - // For high clarity (light fog) we tint the fog color. - // For this to not make the fog color artificially dark we need to normalize using the - // fog color's brightest value. We then blend our base color with this to make the fog. - col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity); + + col = mix(fogColor, col, clarity); + col = vec4(col.rgb, base.a); gl_FragData[0] = col; diff --git a/client/shaders/soft_clouds/opengl_fragment.glsl b/client/shaders/soft_clouds/opengl_fragment.glsl new file mode 100644 index 000000000..1cf0ef0bb --- /dev/null +++ b/client/shaders/soft_clouds/opengl_fragment.glsl @@ -0,0 +1,22 @@ +uniform lowp vec4 fogColor; +uniform float fogDistance; +uniform float fogShadingParameter; +varying highp vec3 eyeVec; + +varying lowp vec4 varColor; +varying lowp vec3 normal; +uniform vec3 v_LightDirection; + +void main(void) +{ + float brightness = max(dot(-v_LightDirection, normal), 0.0); + vec4 col = varColor; + + col.rgb *= brightness; + + float clarity = clamp(fogShadingParameter + - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); + col.rgb = mix(fogColor.rgb, col.rgb, clarity); + + gl_FragColor = col; +} diff --git a/client/shaders/soft_clouds/opengl_vertex.glsl b/client/shaders/soft_clouds/opengl_vertex.glsl new file mode 100644 index 000000000..72f747b87 --- /dev/null +++ b/client/shaders/soft_clouds/opengl_vertex.glsl @@ -0,0 +1,24 @@ +uniform lowp vec4 materialColor; + +varying lowp vec4 varColor; + +varying highp vec3 eyeVec; + +varying lowp vec3 normal; + +void main(void) +{ + gl_Position = mWorldViewProj * inVertexPosition; + +#ifdef GL_ES + vec4 color = inVertexColor.bgra; +#else + vec4 color = inVertexColor; +#endif + + color *= materialColor; + varColor = color; + normal = inVertexNormal; + + eyeVec = -(mWorldView * inVertexPosition).xyz; +} diff --git a/client/shaders/volumetric_clouds/opengl_fragment.glsl b/client/shaders/volumetric_clouds/opengl_fragment.glsl deleted file mode 100644 index 7f7e69ab4..000000000 --- a/client/shaders/volumetric_clouds/opengl_fragment.glsl +++ /dev/null @@ -1,214 +0,0 @@ -#define depthmap texture0 -#define noiseTexture texture1 -#define noiseTextureCoarse texture2 - -#define PROBING_ITERATIONS 30 -#define ITERATIONS 50 -#define LIGHT_ITERATIONS 3 -#define AURORA_ITERATIONS 80 - -// See clouds.cpp -#define CLOUD_SIZE 640.0 - -uniform sampler2D depthmap; -uniform sampler2D noiseTexture; -uniform sampler2D noiseTextureCoarse; - -uniform vec2 texelSize0; - -uniform float cloudHeight; -uniform float cloudThickness; -uniform float cloudDensity; - -varying vec3 relativePosition; -varying vec3 viewDirection; -uniform vec3 cameraOffset; -uniform vec3 cameraPosition; - -uniform float cameraNear; -uniform float cameraFar; - -uniform vec2 cloudOffset; -uniform float cloudRadius; - -varying vec2 screenspaceCoordinate; -varying float sunStrength; - -uniform float fogDistance; -uniform float fogShadingParameter; - -uniform vec3 v_LightDirection; - -uniform float animationTimer; - -// Derived From http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf -// and https://www.shadertoy.com/view/MslGR8 (5th one starting from the bottom) -// NOTE: `frag_coord` is in pixels (i.e. not normalized UV). -float screenSpaceDither(highp vec2 frag_coord) -{ - // Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR. - highp float dither = dot(vec2(171.0, 231.0), frag_coord); - dither = fract(dither / 103.0); - - return dither; -} - -// 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) -{ - float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); - return t * t * (3.0 - 2.0 * t); -} - -float toLinearDepth(float depth) -{ - return cameraNear * cameraFar / (cameraFar + depth * (cameraNear - cameraFar)); -} - -float getDepth(vec2 screenspacePosition) -{ - return texture2D(depthmap, screenspacePosition * 0.5 + 0.5).r; -} - -float noise(vec3 p) -{ - float y = floor(p.y); - float f1 = texture2D(noiseTexture, p.xz / 256. + y * 0.2).r; - float f2 = texture2D(noiseTexture, p.xz / 256. + y * 0.2 + 0.2).r; - return mix(f1, f2, fract(p.y)); -} - -float fnoise(vec3 p) -{ - return noise(p * 4.) * 0.5 + noise(p * 8.) * 0.25; -} - -float fnoise3(vec3 p) -{ - return noise(p * 4.) * 0.5 + noise(p * 8.) * 0.25 + noise(p * 16.) * 0.125; -} - -float getAuroraDensity(vec3 position) -{ - float density = pow(max(0., 1. - 10. * abs(fnoise3(vec3(position.x * 0.25, animationTimer, position.z * 0.25)) - 0.5)), 4.); - return 0.7 * density * mtsmoothstep(0.0, 0.05, position.y - 1.) * pow(1. - mtsmoothstep(0.05, 2.0, position.y - 1.), 4.); -} - -float getCoarse(vec3 position) { - return texture2D(noiseTextureCoarse, (position.xz - cloudOffset) * 0.5 / CLOUD_SIZE / cloudRadius).r; -} - -float getDensity(vec3 position) -{ - float density = texture2D(noiseTextureCoarse, (position.xz - cloudOffset) * 0.5 / CLOUD_SIZE / cloudRadius).r * - mtsmoothstep(0.0, cloudThickness * 0.2, position.y - cloudHeight) * - (1.0 - mtsmoothstep(cloudThickness * 0.5, cloudThickness, position.y - cloudHeight)); - - density = max(0., density - 0.5 * fnoise(position * 0.005)); - - return 0.04 * density; -} - -float getBrightness(vec3 position, float lightDistance) -{ - float density = 0.; - for (int i = 1; i <= LIGHT_ITERATIONS; i++) { - vec3 rayPosition = position - v_LightDirection * lightDistance * float(i) / float(LIGHT_ITERATIONS); - - density += getDensity(rayPosition) * float(lightDistance) / float(LIGHT_ITERATIONS); - } - return exp(-density); -} - -float blend(float A, float B, float alphaA, float alphaB) -{ - float alphaC = alphaA + (1. - alphaA) * alphaB; - return (alphaA * A + (1. - alphaA) * alphaB * B) / alphaC; -} - -void main(void) -{ - vec3 viewVec = normalize(relativePosition); - - vec3 position = cameraOffset + cameraPosition; - - float depth = toLinearDepth(getDepth(screenspaceCoordinate)) / normalize(viewDirection).z; - float bottomPlaneIntersect = clamp((cloudHeight - cameraPosition.y) / viewVec.y, 0., 4. * fogDistance); - float topPlaneIntersect = clamp((cloudHeight + cloudThickness - cameraPosition.y) / viewVec.y, 0., 4. * fogDistance); - -#if (VOLUMETRICS_UNDERSAMPLING <= 1) - bottomPlaneIntersect = min(depth, bottomPlaneIntersect); - topPlaneIntersect = min(depth, topPlaneIntersect); -#else - if ((bottomPlaneIntersect > depth + 5.0) != (topPlaneIntersect > depth + 5.0)) { - bottomPlaneIntersect = min(depth, bottomPlaneIntersect); - topPlaneIntersect = min(depth, topPlaneIntersect); - } -#endif - - float startDepth = min(bottomPlaneIntersect, topPlaneIntersect); - float endDepth = max(bottomPlaneIntersect, topPlaneIntersect); - - float bias = screenSpaceDither(gl_FragCoord.xy + animationTimer * 2400.0); - - vec3 color = vec3(0.); - - float density = 0.; - - float auroraStartDepth = min(max(0., 1.0 / viewVec.y), 8.); - float auroraEndDepth = min(max(0., 3.0 / viewVec.y), 8.); - float rawDepth = getDepth(screenspaceCoordinate); - - if (auroraEndDepth - auroraStartDepth > 0.1 && rawDepth >= 1.0) { - for (int i = 0; i < AURORA_ITERATIONS; i++) { - vec3 rayPosition = viewVec * (auroraStartDepth + (auroraEndDepth - auroraStartDepth) * (float(i) + bias) / float(AURORA_ITERATIONS)); - - float localDensity = getAuroraDensity(rayPosition); - - localDensity *= 1.0 - mtsmoothstep(4.0, 8.0, length(rayPosition)); - - density += localDensity; - } - } - - color.b = density * (auroraEndDepth - auroraStartDepth) / float(AURORA_ITERATIONS); - - float sunlightContribution = 0.; - float alpha = 0.; - float outScatter = 2. * (dot(v_LightDirection, viewVec) * 0.5 + 0.5); - float forwardScatter = 1. + 2. * pow(min(dot(v_LightDirection, viewVec), 0.), 4.); - density = 0.; - - float fogDepth = min(4. * fogDistance, startDepth + 2000.); - endDepth = min(endDepth, fogDepth); - - float dx = (endDepth - startDepth) / float(ITERATIONS); - float lightDistance = cloudThickness * 0.5; - - if (endDepth - startDepth > 0.1) { - for (int i = 0; i < ITERATIONS; i++) { - vec3 rayPosition = cameraPosition + viewVec * (startDepth + (endDepth - startDepth) * (float(i) + bias) / float(ITERATIONS)); - - float localDensity = getDensity(rayPosition) * dx; - - if (localDensity < 0.0001) continue; - - float clarity = clamp(fogShadingParameter - fogShadingParameter * length(rayPosition - cameraPosition) / (fogDepth), 0.0, 1.0); - float outScatterContribution = exp(-0.5 * outScatter * localDensity); - float brightness = getBrightness(rayPosition, lightDistance) * forwardScatter * outScatterContribution * sunStrength + (1. - outScatterContribution); - sunlightContribution = blend(sunlightContribution, brightness, 1. - exp(-density), 1. - exp(-localDensity)); - alpha = blend(alpha, clarity, 1. - exp(-density), 1. - exp(-localDensity)); - - density += localDensity; - - if (density > 10.0) break; - } - } - - color.r = (1. - exp(-density)) * alpha; - color.g = sunlightContribution; - color.b *= exp(-density); - - gl_FragColor = vec4(color, 1.0); -} diff --git a/client/shaders/volumetric_clouds/opengl_vertex.glsl b/client/shaders/volumetric_clouds/opengl_vertex.glsl deleted file mode 100644 index 3b1d247a9..000000000 --- a/client/shaders/volumetric_clouds/opengl_vertex.glsl +++ /dev/null @@ -1,37 +0,0 @@ -uniform mat4 mCameraProjInv; -uniform mat4 mCameraView; -uniform float f_timeofday; - -varying vec3 relativePosition; -varying vec3 viewDirection; - -varying vec2 screenspaceCoordinate; -varying float sunStrength; - -float mtsmoothstep(in float edge0, in float edge1, in float x) -{ - float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); - return t * t * (3.0 - 2.0 * t); -} - -void main(void) -{ - screenspaceCoordinate = inVertexPosition.xy; - vec4 p = mCameraProjInv * inVertexPosition; - viewDirection = p.xyz / p.w; - relativePosition = (p.xyz / p.w) * mat3(mCameraView); - - if (f_timeofday < 0.21) { - sunStrength = - (1.0 - mtsmoothstep(0.18, 0.21, f_timeofday)); - } else if (f_timeofday >= 0.793) { - sunStrength = - mtsmoothstep(0.793, 0.823, f_timeofday); - } else { - sunStrength = - mtsmoothstep(0.21, 0.26, f_timeofday) * - (1.0 - mtsmoothstep(0.743, 0.793, f_timeofday)); - } - - gl_Position = inVertexPosition; -} diff --git a/src/client/client.h b/src/client/client.h index 8fba92fad..f9f77ede4 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -35,7 +35,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gameparams.h" #include "script/common/c_types.h" // LuaError #include "util/numeric.h" -#include "clouds.h" #ifdef SERVER #error Do not include in server builds @@ -373,9 +372,6 @@ public: Camera* getCamera () { return m_camera; } scene::ISceneManager *getSceneManager(); - Clouds* getClouds() { return m_clouds; } - void setClouds(Clouds* clouds) { m_clouds = clouds; } - // IGameDef interface IItemDefManager* getItemDefManager() override; const NodeDefManager* getNodeDefManager() override; @@ -501,7 +497,6 @@ private: ELoginRegister m_allow_login_or_register = ELoginRegister::Any; Camera *m_camera = nullptr; Minimap *m_minimap = nullptr; - Clouds *m_clouds = nullptr; // Server serialization version u8 m_server_ser_ver; diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 1bbd5f206..9d4d28300 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include -class Clouds; scene::ISceneManager *g_menucloudsmgr = nullptr; Clouds *g_menuclouds = nullptr; @@ -44,7 +43,7 @@ Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc, s32 id, u32 seed ): - scene::ISceneNode(g_settings->getBool("enable_volumetric_clouds") ? nullptr : mgr->getRootSceneNode(), mgr, id), + scene::ISceneNode(mgr->getRootSceneNode(), mgr, id), m_seed(seed) { assert(ssrc); @@ -54,7 +53,8 @@ Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc, m_material.FogEnable = true; m_material.AntiAliasing = video::EAAM_SIMPLE; if (m_enable_shaders) { - auto sid = ssrc->getShader("cloud_shader", TILE_MATERIAL_ALPHA); + bool shaded_clouds = g_settings->getBool("soft_clouds") && g_settings->getBool("enable_dynamic_shadows"); + auto sid = ssrc->getShader(shaded_clouds ? "soft_clouds" : "cloud_shader", TILE_MATERIAL_ALPHA); m_material.MaterialType = ssrc->getShaderInfo(sid).material; } else { m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; @@ -107,14 +107,6 @@ void Clouds::updateMesh() std::floor(center_of_drawing_in_noise_f.Y / cloud_size) ); - // The world position of the integer center point of drawing in the noise - v2f world_center_of_drawing_in_noise_f = v2f( - center_of_drawing_in_noise_i.X * cloud_size, - center_of_drawing_in_noise_i.Y * cloud_size - ) + m_origin; - - m_noise_position = world_center_of_drawing_in_noise_f - ((float)m_cloud_radius_i + 0.5f) * cloud_size; - // Only update mesh if it has moved enough, this saves lots of GPU buffer uploads. constexpr float max_d = 5 * BS; @@ -137,6 +129,12 @@ void Clouds::updateMesh() const u32 num_faces_to_draw = is3D() ? 6 : 1; + // The world position of the integer center point of drawing in the noise + v2f world_center_of_drawing_in_noise_f = v2f( + center_of_drawing_in_noise_i.X * cloud_size, + center_of_drawing_in_noise_i.Y * cloud_size + ) + m_origin; + // Colors with primitive shading video::SColorf c_top_f(m_color); @@ -166,7 +164,7 @@ void Clouds::updateMesh() // Read noise - m_grid.resize(m_cloud_radius_i * 2 * m_cloud_radius_i * 2); + std::vector grid(m_cloud_radius_i * 2 * m_cloud_radius_i * 2); for(s16 zi = -m_cloud_radius_i; zi < m_cloud_radius_i; zi++) { u32 si = (zi + m_cloud_radius_i) * m_cloud_radius_i * 2 + m_cloud_radius_i; @@ -174,7 +172,7 @@ void Clouds::updateMesh() for (s16 xi = -m_cloud_radius_i; xi < m_cloud_radius_i; xi++) { u32 i = si + xi; - m_grid[i] = gridFilled( + grid[i] = gridFilled( xi + center_of_drawing_in_noise_i.X, zi + center_of_drawing_in_noise_i.Y ); @@ -213,147 +211,225 @@ void Clouds::updateMesh() u32 i = GETINDEX(xi, zi, m_cloud_radius_i); - if (!m_grid[i]) + if (!grid[i]) continue; v2f p0 = v2f(xi,zi)*cloud_size + world_center_of_drawing_in_noise_f; - video::S3DVertex v[4] = { - video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 1), - video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 1), - video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 0), - video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0) - }; - const f32 rx = cloud_size / 2.0f; // if clouds are flat, the top layer should be at the given height const f32 ry = is3D() ? m_params.thickness * BS : 0.0f; const f32 rz = cloud_size / 2; bool soft_clouds_enabled = g_settings->getBool("soft_clouds"); - for (u32 i = 0; i < num_faces_to_draw; i++) - { - switch (i) - { - case 0: // top - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(0, 1, 0); - } - v[0].Pos.set(-rx, ry,-rz); - v[1].Pos.set(-rx, ry, rz); - v[2].Pos.set( rx, ry, rz); - v[3].Pos.set( rx, ry,-rz); - break; - case 1: // back - if (INAREA(xi, zi - 1, m_cloud_radius_i)) { - u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); - if (m_grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(0, 0, -1); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_1; - vertex.Normal.set(0, 0, -1); - } - } - v[0].Pos.set(-rx, ry,-rz); - v[1].Pos.set( rx, ry,-rz); - v[2].Pos.set( rx, 0,-rz); - v[3].Pos.set(-rx, 0,-rz); - break; - case 2: //right - if (INAREA(xi + 1, zi, m_cloud_radius_i)) { - u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i); - if (m_grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(1, 0, 0); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_2; - vertex.Normal.set(1, 0, 0); - } - } - v[0].Pos.set(rx, ry,-rz); - v[1].Pos.set(rx, ry, rz); - v[2].Pos.set(rx, 0, rz); - v[3].Pos.set(rx, 0,-rz); - break; - case 3: // front - if (INAREA(xi, zi + 1, m_cloud_radius_i)) { - u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i); - if (m_grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(0, 0, -1); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_1; - vertex.Normal.set(0, 0, -1); - } - } - v[0].Pos.set( rx, ry, rz); - v[1].Pos.set(-rx, ry, rz); - v[2].Pos.set(-rx, 0, rz); - v[3].Pos.set( rx, 0, rz); - break; - case 4: // left - if (INAREA(xi - 1, zi, m_cloud_radius_i)) { - u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i); - if (m_grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(-1, 0, 0); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_2; - vertex.Normal.set(-1, 0, 0); - } - } - v[0].Pos.set(-rx, ry, rz); - v[1].Pos.set(-rx, ry,-rz); - v[2].Pos.set(-rx, 0,-rz); - v[3].Pos.set(-rx, 0, rz); - break; - case 5: // bottom - for (video::S3DVertex& vertex : v) { - vertex.Color = c_bottom; - vertex.Normal.set(0, -1, 0); - } - v[0].Pos.set( rx, 0, rz); - v[1].Pos.set(-rx, 0, rz); - v[2].Pos.set(-rx, 0,-rz); - v[3].Pos.set( rx, 0,-rz); - break; + bool shaded_clouds_enabled = soft_clouds_enabled && g_settings->getBool("enable_dynamic_shadows") && g_settings->getBool("enable_3d_clouds"); + + v3f pos(p0.X, m_params.height * BS, p0.Y); + + if (shaded_clouds_enabled) { + bool neighbours[4] = {false, false, false, false}; + if (INAREA(xi - 1, zi, m_cloud_radius_i)) + neighbours[0] = grid[GETINDEX(xi - 1, zi, m_cloud_radius_i)]; + if (INAREA(xi, zi - 1, m_cloud_radius_i)) + neighbours[1] = grid[GETINDEX(xi, zi - 1, m_cloud_radius_i)]; + if (INAREA(xi + 1, zi, m_cloud_radius_i)) + neighbours[2] = grid[GETINDEX(xi + 1, zi, m_cloud_radius_i)]; + if (INAREA(xi, zi + 1, m_cloud_radius_i)) + neighbours[3] = grid[GETINDEX(xi, zi + 1, m_cloud_radius_i)]; + + video::S3DVertex v[32]; + v[ 0].Pos = core::vector3df( -rx, ry, -rz); + v[ 1].Pos = core::vector3df(-0.75 * rx, ry, -rz); + v[ 2].Pos = core::vector3df( 0.75 * rx, ry, -rz); + v[ 3].Pos = core::vector3df( rx, ry, -rz); + v[ 4].Pos = core::vector3df( -rx, ry, -0.75 * rz); + v[ 5].Pos = core::vector3df(-0.75 * rx, ry, -0.75 * rz); + v[ 6].Pos = core::vector3df( 0.75 * rx, ry, -0.75 * rz); + v[ 7].Pos = core::vector3df( rx, ry, -0.75 * rz); + v[ 8].Pos = core::vector3df( -rx, ry, 0.75 * rz); + v[ 9].Pos = core::vector3df(-0.75 * rx, ry, 0.75 * rz); + v[10].Pos = core::vector3df( 0.75 * rx, ry, 0.75 * rz); + v[11].Pos = core::vector3df( rx, ry, 0.75 * rz); + v[12].Pos = core::vector3df( -rx, ry, rz); + v[13].Pos = core::vector3df(-0.75 * rx, ry, rz); + v[14].Pos = core::vector3df( 0.75 * rx, ry, rz); + v[15].Pos = core::vector3df( rx, ry, rz); + + // These normals are intentionally left unnormalized + if (neighbours[0]) { + v[ 0].Normal.X -= 1.0; + v[ 4].Normal.X -= 1.0; + v[ 8].Normal.X -= 1.0; + v[12].Normal.X -= 1.0; + } + if (neighbours[1]) { + v[0].Normal.Z -= 1.0; + v[1].Normal.Z -= 1.0; + v[2].Normal.Z -= 1.0; + v[3].Normal.Z -= 1.0; + } + if (neighbours[2]) { + v[ 3].Normal.X += 1.0; + v[ 7].Normal.X += 1.0; + v[11].Normal.X += 1.0; + v[15].Normal.X += 1.0; + } + if (neighbours[3]) { + v[12].Normal.Z += 1.0; + v[13].Normal.Z += 1.0; + v[14].Normal.Z += 1.0; + v[15].Normal.Z += 1.0; } - v3f pos(p0.X, m_params.height * BS, p0.Y); + for (int i = 0; i < 16; ++i) { + v[i + 32] = v[i]; + v[i + 32].Pos.Y = -ry; - for (video::S3DVertex &vertex : v) { + v[i].Normal = core::vector3df(0.0, 1.0, 0.0); + v[i + 32].Normal = core::vector3df(0.0, -1.0, 0.0); + } + + for (video::S3DVertex& vertex : v) { + vertex.Color = shadow.toSColor(); vertex.Pos += pos; - vertices.push_back(vertex); + } + + //top + + } + else { + video::S3DVertex v[4] = { + video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 1), + video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 1), + video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 0), + video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0) + }; + + for (u32 i = 0; i < num_faces_to_draw; i++) + { + switch (i) + { + case 0: // top + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(0, 1, 0); + } + v[0].Pos.set(-rx, ry, -rz); + v[1].Pos.set(-rx, ry, rz); + v[2].Pos.set(rx, ry, rz); + v[3].Pos.set(rx, ry, -rz); + break; + case 1: // back + if (INAREA(xi, zi - 1, m_cloud_radius_i)) { + u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(0, 0, -1); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_1; + vertex.Normal.set(0, 0, -1); + } + } + v[0].Pos.set(-rx, ry, -rz); + v[1].Pos.set(rx, ry, -rz); + v[2].Pos.set(rx, 0, -rz); + v[3].Pos.set(-rx, 0, -rz); + break; + case 2: //right + if (INAREA(xi + 1, zi, m_cloud_radius_i)) { + u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(1, 0, 0); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_2; + vertex.Normal.set(1, 0, 0); + } + } + v[0].Pos.set(rx, ry, -rz); + v[1].Pos.set(rx, ry, rz); + v[2].Pos.set(rx, 0, rz); + v[3].Pos.set(rx, 0, -rz); + break; + case 3: // front + if (INAREA(xi, zi + 1, m_cloud_radius_i)) { + u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(0, 0, -1); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_1; + vertex.Normal.set(0, 0, -1); + } + } + v[0].Pos.set(rx, ry, rz); + v[1].Pos.set(-rx, ry, rz); + v[2].Pos.set(-rx, 0, rz); + v[3].Pos.set(rx, 0, rz); + break; + case 4: // left + if (INAREA(xi - 1, zi, m_cloud_radius_i)) { + u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(-1, 0, 0); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_2; + vertex.Normal.set(-1, 0, 0); + } + } + v[0].Pos.set(-rx, ry, rz); + v[1].Pos.set(-rx, ry, -rz); + v[2].Pos.set(-rx, 0, -rz); + v[3].Pos.set(-rx, 0, rz); + break; + case 5: // bottom + for (video::S3DVertex& vertex : v) { + vertex.Color = c_bottom; + vertex.Normal.set(0, -1, 0); + } + v[0].Pos.set(rx, 0, rz); + v[1].Pos.set(-rx, 0, rz); + v[2].Pos.set(-rx, 0, -rz); + v[3].Pos.set(rx, 0, -rz); + break; + } + + for (video::S3DVertex& vertex : v) { + vertex.Pos += pos; + vertices.push_back(vertex); + } } } } @@ -430,40 +506,13 @@ void Clouds::render() cloud_full_radius*1.2, fog_density, fog_pixelfog, fog_rangefog); } -//#if 0 driver->drawMeshBuffer(m_meshbuffer.get()); -//#endif + // Restore fog settings driver->setFog(fog_color, fog_type, fog_start, fog_end, fog_density, fog_pixelfog, fog_rangefog); } -void Clouds::renderDepth() { - if (m_params.density <= 0.0f) - return; // no need to do anything - - video::IVideoDriver* driver = SceneManager->getVideoDriver(); - - updateMesh(); - - // Update position - { - v2f off_origin = m_origin - m_mesh_origin; - v3f rel(off_origin.X, 0, off_origin.Y); - rel -= intToFloat(m_camera_offset, BS); - setPosition(rel); - updateAbsolutePosition(); - } - - video::SMaterial material = m_material; - material.MaterialType = video::EMT_SOLID; - material.ZWriteEnable = video::EZW_ON; - - driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); - driver->setMaterial(material); - driver->drawMeshBuffer(m_meshbuffer.get()); -} - void Clouds::step(float dtime) { m_origin = m_origin + dtime * BS * m_params.speed; diff --git a/src/client/clouds.h b/src/client/clouds.h index 67a2aed28..7193c03f9 100644 --- a/src/client/clouds.h +++ b/src/client/clouds.h @@ -60,8 +60,6 @@ public: virtual void render(); - void renderDepth(); - virtual const aabb3f &getBoundingBox() const { return m_box; @@ -101,10 +99,6 @@ public: invalidateMesh(); } - float getDensity() const { - return m_params.density; - } - void setColorBright(video::SColor color_bright) { m_params.color_bright = color_bright; @@ -132,10 +126,6 @@ public: invalidateMesh(); } - float getHeight() const { - return m_params.height; - } - void setSpeed(v2f speed) { m_params.speed = speed; @@ -150,24 +140,10 @@ public: invalidateMesh(); } - float getThickness() const { - return m_params.thickness; - } - bool isCameraInsideCloud() const { return m_camera_inside_cloud; } const video::SColor getColor() const { return m_color.toSColor(); } - bool getGrid(int x, int y) - { - int index = x + y * m_cloud_radius_i * 2; - if (index < 0 || index >= m_grid.size()) - return false; - return m_grid[index]; - } - - v2f getCloudOffset() const { return m_noise_position; } - private: void updateBox() { @@ -204,7 +180,6 @@ private: u16 m_cloud_radius_i; u32 m_seed; v3f m_camera_pos; - v2f m_noise_position; v3s16 m_camera_offset; bool m_camera_inside_cloud = false; @@ -212,7 +187,4 @@ private: bool m_enable_shaders, m_enable_3d; video::SColorf m_color = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); CloudParams m_params; - - std::vector m_grid; - }; diff --git a/src/client/game.cpp b/src/client/game.cpp index 3c4f42031..faf0ef65d 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -435,8 +435,6 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_moon_brightness_pixel{"moonBrightness"}; CachedPixelShaderSetting m_volumetric_light_strength_pixel{"volumetricLightStrength"}; - CachedPixelShaderSetting - m_volumetric_cloud_color{"cloudColor"}; static constexpr std::array SETTING_CALLBACKS = { "exposure_compensation", @@ -575,23 +573,6 @@ public: video::SColorf artificial_light = lighting.artificial_light_color; m_artificial_light.set(artificial_light, services); - // TODO: settings - Clouds* clouds = m_client->getClouds(); - if (clouds && g_settings->getBool("enable_volumetric_clouds")) { - float cloud_height = clouds->getHeight() * 10.0f; - m_cloud_height_pixel.set(&cloud_height, services); - float cloud_thickness = clouds->getThickness() * 10.0f; - m_cloud_thickness_pixel.set(&cloud_thickness, services); - float cloud_density = clouds->getDensity(); - m_cloud_density_pixel.set(&cloud_density, services); - v2f cloud_offset = clouds->getCloudOffset(); - m_cloud_offset_pixel.set(cloud_offset, services); - float cloud_radius = g_settings->getU16("cloud_radius"); - m_cloud_radius_pixel.set(&cloud_radius, services); - video::SColor cloud_color = clouds->getColor(); - m_volumetric_cloud_color.set(cloud_color, services); - } - if (m_volumetric_light_enabled) { // Map directional light to screen space auto camera_node = m_client->getCamera()->getCameraNode(); @@ -1588,7 +1569,6 @@ bool Game::createClient(const GameStartData &start_data) */ if (m_cache_enable_clouds) clouds = make_irr(smgr, shader_src, -1, rand()); - client->setClouds(clouds.get()); /* Skybox */ @@ -4334,7 +4314,7 @@ void Game::updateClouds(float dtime) camera_node_position.Y = camera_node_position.Y + camera_offset.Y * BS; camera_node_position.Z = camera_node_position.Z + camera_offset.Z * BS; this->clouds->update(camera_node_position, this->sky->getCloudColor()); - if (this->clouds->isCameraInsideCloud() && this->fogEnabled() && !g_settings->getBool("enable_volumetric_clouds")) { + if (this->clouds->isCameraInsideCloud() && this->fogEnabled()) { // If camera is inside cloud and fog is enabled, use cloud's colors as sky colors. video::SColor clouds_dark = this->clouds->getColor().getInterpolated( video::SColor(255, 0, 0, 0), 0.9); diff --git a/src/client/render/pipeline.cpp b/src/client/render/pipeline.cpp index 7700e8aeb..37adcbaf2 100644 --- a/src/client/render/pipeline.cpp +++ b/src/client/render/pipeline.cpp @@ -113,19 +113,6 @@ void TextureBuffer::swapTextures(u8 texture_a, u8 texture_b) m_textures[texture_b] = temp; } -void TextureBuffer::setTextureImage(u8 id, video::IImage* image) { - assert(m_definitions[id].valid); - - auto &definition = m_definitions[id]; - - if (m_textures[id]) m_driver->removeTexture(m_textures[id]); - - m_textures[id] = m_driver->addTexture(definition.name.c_str(), image); - definition.fixed_size = true; - definition.size = image->getDimension(); - definition.dirty = false; -} - bool TextureBuffer::ensureTexture(video::ITexture **texture, const TextureDefinition& definition, PipelineContext &context) { bool modify; @@ -195,8 +182,6 @@ void TextureBufferOutput::activate(PipelineContext &context) if (!render_target) render_target = driver->addRenderTarget(); - if (disable_clear) m_clear = false; - core::array textures; core::dimension2du size(0, 0); for (size_t i = 0; i < texture_map.size(); i++) { diff --git a/src/client/render/pipeline.h b/src/client/render/pipeline.h index 31ceabe20..8a6b55c07 100644 --- a/src/client/render/pipeline.h +++ b/src/client/render/pipeline.h @@ -190,7 +190,6 @@ public: TextureBufferOutput(TextureBuffer *buffer, const std::vector &texture_map, u8 depth_stencil); virtual ~TextureBufferOutput() override; void activate(PipelineContext &context) override; - void disableClearing() { disable_clear = true; } private: static const u8 NO_DEPTH_TEXTURE = 255; @@ -199,7 +198,6 @@ private: u8 depth_stencil { NO_DEPTH_TEXTURE }; video::IRenderTarget* render_target { nullptr }; video::IVideoDriver* driver { nullptr }; - bool disable_clear = false; }; /** diff --git a/src/client/render/secondstage.cpp b/src/client/render/secondstage.cpp index 082c4c11c..da6536b97 100644 --- a/src/client/render/secondstage.cpp +++ b/src/client/render/secondstage.cpp @@ -24,116 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/shader.h" #include "client/tile.h" #include "settings.h" -#include "noise.h" - -// TODO: Probably this could still be improved, having a step for this seems silly -class NoiseStep : public RenderStep { -public: - NoiseStep(TextureBuffer* buffer, u8 id, u32 size) : - buffer(buffer), id(id), size(size) - { - } - - void setRenderSource(RenderSource* _source) override {} - - void setRenderTarget(RenderTarget* _target) override {} - - void reset(PipelineContext& context) override {} - - void run(PipelineContext& context) override - { - if (!needs_run) return; - - needs_run = false; - - video::IImage* noise_image = context.device->getVideoDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(256, 256)); - PseudoRandom random; - for (u32 i = 0; i < size * size; ++i) { - noise_image->setPixel(i % size, i / size, video::SColor(0, random.next() % 256, 0, 0)); - } - buffer->setTextureImage(id, noise_image); - noise_image->drop(); - } - -private: - u32 size; - u8 id; - TextureBuffer* buffer = nullptr; - bool needs_run = true; -}; - -class CloudDensityStep : public RenderStep { -public: - CloudDensityStep(TextureBuffer* buffer, u8 id, Clouds* clouds) : - buffer(buffer), id(id), clouds(clouds) - { - } - - void setRenderSource(RenderSource* _source) override {} - - void setRenderTarget(RenderTarget* _target) override {} - - void reset(PipelineContext& context) override {} - - void run(PipelineContext& context) override - { - u16 cloud_radius = g_settings->getU16("cloud_radius"); - if (cloud_radius < 1) cloud_radius = 1; - - video::IImage* image = context.device->getVideoDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(8 * cloud_radius, 8 * cloud_radius)); - - for (int x = 0; x < 2 * cloud_radius; ++x) { - for (int y = 0; y < 2 * cloud_radius; ++y) { - bool isFilled = clouds->getGrid(x, y); - - for (int i = 0; i < 16; ++i) { - int xp = x * 4 + i % 4; - int yp = y * 4 + i / 4; - - image->setPixel(xp, yp, video::SColor(255, isFilled * 255, 0, 0)); - } - } - } - - buffer->setTextureImage(id, image); - - image->drop(); - } - -private: - Clouds* clouds = nullptr; - u8 id = 0; - TextureBuffer* buffer = nullptr; -}; - -class CloudDepthStep : public RenderStep { -public: - CloudDepthStep(Clouds* clouds) : - clouds(clouds) - { - } - - void setRenderSource(RenderSource* _source) override {} - - void setRenderTarget(RenderTarget* _target) override - { - target = _target; - } - - void reset(PipelineContext& context) override {} - - void run(PipelineContext& context) override - { - if (target) - target->activate(context); - - clouds->renderDepth(); - } - -private: - Clouds* clouds = nullptr; - RenderTarget* target = nullptr; -}; PostProcessingStep::PostProcessingStep(u32 _shader_id, const std::vector &_texture_map) : shader_id(_shader_id), texture_map(_texture_map) @@ -175,6 +65,7 @@ void PostProcessingStep::run(PipelineContext &context) if (target) target->activate(context); + // attach the shader material.MaterialType = context.client->getShaderSource()->getShaderInfo(shader_id).material; auto driver = context.device->getVideoDriver(); @@ -205,17 +96,6 @@ void PostProcessingStep::setBilinearFilter(u8 index, bool value) material.TextureLayers[index].MagFilter = value ? video::ETMAGF_LINEAR : video::ETMAGF_NEAREST; } -void PostProcessingStep::setWrapRepeat(u8 index, bool value) { - assert(index < video::MATERIAL_MAX_TEXTURES); - material.TextureLayers[index].TextureWrapU = value ? video::ETC_REPEAT : video::ETC_CLAMP_TO_EDGE; - material.TextureLayers[index].TextureWrapV = value ? video::ETC_REPEAT : video::ETC_CLAMP_TO_EDGE; -} - -void PostProcessingStep::disableDepthTest() { - material.ZBuffer = video::ECFN_DISABLED; - material.ZWriteEnable = video::EZW_OFF; -} - RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep, v2f scale, Client *client) { auto buffer = pipeline->createOwned(); @@ -241,13 +121,8 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep static const u8 TEXTURE_EXPOSURE_2 = 4; static const u8 TEXTURE_FXAA = 5; static const u8 TEXTURE_VOLUME = 6; - static const u8 TEXTURE_CLOUDS_1 = 7; - static const u8 TEXTURE_CLOUDS_2 = 8; - static const u8 TEXTURE_CLOUD_DENSITY = 9; - static const u8 TEXTURE_NOISE = 10; - static const u8 TEXTURE_NOISE_COARSE = 11; - static const u8 TEXTURE_SCALE_DOWN = 20; - static const u8 TEXTURE_SCALE_UP = 30; + static const u8 TEXTURE_SCALE_DOWN = 10; + static const u8 TEXTURE_SCALE_UP = 20; // Super-sampling is simply rendering into a larger texture. // Downscaling is done by the final step when rendering to the screen. @@ -257,8 +132,6 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep const bool enable_ssaa = antialiasing == "ssaa"; const bool enable_fxaa = antialiasing == "fxaa"; const bool enable_volumetric_light = g_settings->getBool("enable_volumetric_lighting") && enable_bloom; - // TODO: Proper constraints - const bool enable_volumetric_clouds = g_settings->getBool("enable_volumetric_clouds") && client->getClouds(); if (enable_ssaa) { u16 ssaa_scale = MYMAX(2, g_settings->getU16("fsaa")); @@ -279,55 +152,11 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep // Number of mipmap levels of the bloom downsampling texture const u8 MIPMAP_LEVELS = 4; + // post-processing stage u8 source = TEXTURE_COLOR; - u8 final_color_source = TEXTURE_COLOR; - - if (enable_volumetric_clouds) { - const u16 cloud_radius = g_settings->getU16("cloud_radius"); - - buffer->setTexture(TEXTURE_NOISE, core::dimension2du(256, 256), "noise", color_format); - pipeline->addStep(buffer, TEXTURE_NOISE, 256); - - buffer->setTexture(TEXTURE_NOISE_COARSE, core::dimension2du(cloud_radius * 8, cloud_radius * 8), "noise_coarse", color_format); - pipeline->addStep(buffer, TEXTURE_NOISE_COARSE, client->getClouds()); - - u32 undersampling = core::clamp(g_settings->getU32("volumetrics_undersampling"), (u32)1, (u32)4); - - buffer->setTexture(TEXTURE_CLOUDS_1, scale / (float)undersampling, "clouds_1", color_format, /*clear:*/ true); - buffer->setTexture(TEXTURE_CLOUDS_2, scale, "clouds_2", color_format); - buffer->setTexture(TEXTURE_CLOUD_DENSITY, scale, "cloud_density", color_format); - - shader_id = client->getShaderSource()->getShader("volumetric_clouds", TILE_MATERIAL_PLAIN, NDT_MESH); - PostProcessingStep *volumetric_clouds = pipeline->addStep(shader_id, std::vector { TEXTURE_DEPTH, TEXTURE_NOISE, TEXTURE_NOISE_COARSE }); - volumetric_clouds->setRenderSource(buffer); - volumetric_clouds->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_CLOUDS_1)); - volumetric_clouds->setBilinearFilter(1, true); - volumetric_clouds->setBilinearFilter(2, true); - volumetric_clouds->setWrapRepeat(1, true); - volumetric_clouds->setWrapRepeat(2, true); - volumetric_clouds->disableDepthTest(); - - source = TEXTURE_CLOUDS_1; - - shader_id = client->getShaderSource()->getShader("clouds_merge", TILE_MATERIAL_PLAIN, NDT_MESH); - PostProcessingStep* blend_clouds = pipeline->addStep(shader_id, std::vector { TEXTURE_CLOUDS_1, TEXTURE_COLOR, TEXTURE_DEPTH }); - blend_clouds->setRenderSource(buffer); - blend_clouds->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_CLOUDS_2)); - blend_clouds->setBilinearFilter(0, true); - blend_clouds->disableDepthTest(); - - CloudDepthStep* cloud_depth = pipeline->addStep(client->getClouds()); - TextureBufferOutput* cloud_depth_output = pipeline->createOwned(buffer, std::vector{ TEXTURE_COLOR }, TEXTURE_DEPTH); - cloud_depth_output->disableClearing(); - cloud_depth->setRenderTarget(cloud_depth_output); - - source = TEXTURE_CLOUDS_2; - final_color_source = TEXTURE_CLOUDS_2; - } - // common downsampling step for bloom or autoexposure if (enable_bloom || enable_auto_exposure) { @@ -344,7 +173,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep // get bright spots u32 shader_id = client->getShaderSource()->getShader("extract_bloom", TILE_MATERIAL_PLAIN, NDT_MESH); - RenderStep* extract_bloom = pipeline->addStep(shader_id, std::vector { source, TEXTURE_EXPOSURE_1 }); + RenderStep *extract_bloom = pipeline->addStep(shader_id, std::vector { source, TEXTURE_EXPOSURE_1 }); extract_bloom->setRenderSource(buffer); extract_bloom->setRenderTarget(pipeline->createOwned(buffer, TEXTURE_BLOOM)); source = TEXTURE_BLOOM; @@ -395,14 +224,14 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep } // FXAA - u8 final_stage_source = final_color_source; + u8 final_stage_source = TEXTURE_COLOR; if (enable_fxaa) { final_stage_source = TEXTURE_FXAA; buffer->setTexture(TEXTURE_FXAA, scale, "fxaa", color_format); shader_id = client->getShaderSource()->getShader("fxaa", TILE_MATERIAL_PLAIN); - PostProcessingStep* effect = pipeline->createOwned(shader_id, std::vector { final_color_source }); + PostProcessingStep *effect = pipeline->createOwned(shader_id, std::vector { TEXTURE_COLOR }); pipeline->addStep(effect); effect->setBilinearFilter(0, true); effect->setRenderSource(buffer); @@ -411,7 +240,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep // final merge shader_id = client->getShaderSource()->getShader("second_stage", TILE_MATERIAL_PLAIN, NDT_MESH); - PostProcessingStep* effect = pipeline->createOwned(shader_id, std::vector { final_stage_source, TEXTURE_SCALE_UP, TEXTURE_EXPOSURE_2 }); + PostProcessingStep *effect = pipeline->createOwned(shader_id, std::vector { final_stage_source, TEXTURE_SCALE_UP, TEXTURE_EXPOSURE_2 }); pipeline->addStep(effect); if (enable_ssaa) effect->setBilinearFilter(0, true); diff --git a/src/client/render/secondstage.h b/src/client/render/secondstage.h index 224b27e33..9e3640927 100644 --- a/src/client/render/secondstage.h +++ b/src/client/render/secondstage.h @@ -49,13 +49,6 @@ public: * @param value true to enable the bilinear filter, false to disable */ void setBilinearFilter(u8 index, bool value); - - void setWrapRepeat(u8 index, bool value); - - void setColor(video::SColor color); - - void disableDepthTest(); - private: u32 shader_id; std::vector texture_map; diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 39730463f..f75d48d53 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -681,6 +681,9 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, shaders_header << "#define ENABLE_WAVING_PLANTS " << g_settings->getBool("enable_waving_plants") << "\n"; shaders_header << "#define ENABLE_TONE_MAPPING " << g_settings->getBool("tone_mapping") << "\n"; + if (g_settings->getBool("enable_tinted_fog")) + shaders_header << "#define ENABLE_TINTED_FOG 1\n"; + if (g_settings->getBool("enable_dynamic_shadows")) { shaders_header << "#define ENABLE_DYNAMIC_SHADOWS 1\n"; if (g_settings->getBool("shadow_map_color")) @@ -738,10 +741,6 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, shaders_header << "#define VOLUMETRIC_LIGHT 1\n"; } - if (g_settings->getBool("enable_volumetric_clouds")) { - shaders_header << "#define VOLUMETRICS_UNDERSAMPLING " << g_settings->getU32("volumetrics_undersampling") << '\n'; - } - shaders_header << "#line 0\n"; // reset the line counter for meaningful diagnostics std::string common_header = shaders_header.str(); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 5ac62534e..6625dfb03 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -339,11 +339,11 @@ void set_default_settings() settings->setDefault("bloom_intensity", "0.05"); settings->setDefault("bloom_radius", "1"); settings->setDefault("enable_volumetric_lighting", "false"); - settings->setDefault("enable_volumetric_clouds", "false"); settings->setDefault("enable_bumpmaps", "false"); settings->setDefault("enable_water_reflections", "false"); settings->setDefault("enable_translucent_foliage", "false"); settings->setDefault("enable_node_specular", "false"); + settings->setDefault("enable_tinted_fog", "false"); // Effects Shadows settings->setDefault("enable_dynamic_shadows", "false"); diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index d5c9067e9..40d11f73c 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1817,8 +1817,8 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt) } if (pkt->getRemainingBytes() >= 4) *pkt >> lighting.volumetric_light_strength; - if (pkt->getRemainingBytes() >= 4) - *pkt >> lighting.artificial_light_color; if (pkt->getRemainingBytes() >= 4) *pkt >> lighting.shadow_tint; + if (pkt->getRemainingBytes() >= 4) + *pkt >> lighting.artificial_light_color; } diff --git a/src/server.cpp b/src/server.cpp index d624c5f5c..1a2d8cf4f 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1861,9 +1861,7 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) << lighting.exposure.speed_bright_dark << lighting.exposure.center_weight_power; - pkt << lighting.volumetric_light_strength << lighting.shadow_tint; - - pkt << lighting.artificial_light_color; + pkt << lighting.volumetric_light_strength << lighting.shadow_tint << lighting.artificial_light_color; Send(&pkt); } From 4b88a32c1c14ef1be1ef28bd7fcc84c6cc752e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 27 Oct 2024 21:36:40 +0100 Subject: [PATCH 11/40] Various changes, fixes and features --- builtin/settingtypes.txt | 12 +- .../minimap_shader/opengl_fragment.glsl | 20 +- .../shaders/nodes_shader/opengl_fragment.glsl | 88 +++-- .../shaders/nodes_shader/opengl_vertex.glsl | 12 +- .../object_shader/opengl_fragment.glsl | 2 +- .../shaders/second_stage/opengl_fragment.glsl | 18 +- .../volumetric_light/opengl_fragment.glsl | 16 +- doc/lua_api.md | 15 + src/client/clouds.cpp | 328 +++++++----------- src/client/game.cpp | 48 ++- src/client/shader.cpp | 7 + src/defaultsettings.cpp | 4 +- src/lighting.h | 33 ++ src/network/clientpackethandler.cpp | 8 + src/network/networkprotocol.cpp | 1 + src/script/lua_api/l_object.cpp | 49 +++ src/server.cpp | 9 +- 17 files changed, 409 insertions(+), 261 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 02420eb05..9b62ee152 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -584,6 +584,11 @@ shadow_soft_radius (Soft shadow radius) float 5.0 1.0 15.0 # Requires: shaders, enable_dynamic_shadows, opengl shadow_sky_body_orbit_tilt (Sky Body Orbit Tilt) float 0.0 -60.0 60.0 +# Tint sunlight during sunrise/sunset. +# +# Requires: shaders, enable_dynamic_shadows, opengl +enable_sun_tint (Tinted sunlight) bool false + [**Post Processing] # Enables the post processing pipeline. @@ -620,7 +625,7 @@ exposure_compensation (Exposure compensation) float 0.0 -1.0 1.0 # Default: 1.6 # # Requires: shaders, enable_post_processing, tone_mapping -gamma (Gamma) float 1.6 1.0 5.0 +secondstage_gamma (Gamma) float 1.6 1.0 5.0 # Apply ASL CDL color grading to make brighter colors warmer and darker colors cooler. # @@ -654,6 +659,11 @@ enable_bloom (Enable Bloom) bool false # Requires: shaders, enable_post_processing, enable_bloom enable_volumetric_lighting (Volumetric Lighting) bool false +# Make volumetrics weaker against closer objects to emulate physical volumetrics. +# +# Requires: shaders, enable_post_processing, enable_bloom, enable_volumetric_lighting +enable_volumetric_depth_attenuation (Volumetric Depth Attenuation) bool false + [**Other Effects] # Makes the color of light fog more saturated. diff --git a/client/shaders/minimap_shader/opengl_fragment.glsl b/client/shaders/minimap_shader/opengl_fragment.glsl index 88c827138..d1b7291af 100644 --- a/client/shaders/minimap_shader/opengl_fragment.glsl +++ b/client/shaders/minimap_shader/opengl_fragment.glsl @@ -8,7 +8,7 @@ varying mediump vec2 varTexCoord; void main (void) { - vec2 uv = varTexCoord; + vec2 uv = varTexCoord.st; //texture sampling rate float step = 1.0 / mapSize; @@ -20,19 +20,17 @@ void main (void) float b = texture2D(normalTexture, vec2(uv.x, uv.y - step)).r; float bl = texture2D(normalTexture, vec2(uv.x - step, uv.y - step)).r; float l = texture2D(normalTexture, vec2(uv.x - step, uv.y )).r; - float c = texture2D(normalTexture, vec2(uv.x , uv.y )).r; - float AO = 50.0 * (clamp(t - c, -0.001, 0.001) + clamp(b - c, -0.001, 0.001) + clamp(r - c, -0.001, 0.001) + clamp(l - c, -0.001, 0.001)); - float dX = 4.0 * (l - r); - float dY = 4.0 * (t - b); - vec3 bump = normalize(vec3 (dX, dY, 0.1)); + float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl); + float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr); + vec4 bump = vec4 (normalize(vec3 (dX, dY, 0.1)),1.0); float height = 2.0 * texture2D(normalTexture, vec2(uv.x, uv.y)).r - 1.0; vec4 base = texture2D(baseTexture, uv).rgba; - vec3 L = normalize(vec3(0.0, 0.0, 1.0)); + vec3 L = normalize(vec3(0.0, 0.75, 1.0)); float specular = pow(clamp(dot(reflect(L, bump.xyz), yawVec), 0.0, 1.0), 1.0); - float diffuse = dot(yawVec, bump); + float diffuse = dot(yawVec, bump.xyz); - vec3 color = (1.1 * diffuse + 0.05 * height + 0.5 * specular + AO) * base.rgb; - vec4 col = vec4(color, base.a); + vec3 color = (1.1 * diffuse + 0.05 * height + 0.5 * specular) * base.rgb; + vec4 col = vec4(color.rgb, base.a); col *= varColor; gl_FragColor = vec4(col.rgb, base.a); -} +} \ No newline at end of file diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 6be928538..e345a7e88 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -40,6 +40,8 @@ uniform float animationTimer; varying float perspective_factor; #endif +uniform vec2 windowSize; +uniform float fov; varying vec3 vNormal; varying vec3 vPosition; @@ -98,6 +100,36 @@ vec3 gnoise(vec3 p){ ); } +float snoise(vec3 p) +{ + vec3 a = floor(p); + vec3 d = p - a; + d = d * d * (3.0 - 2.0 * d); + + vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0); + vec4 k1 = perm(b.xyxy); + vec4 k2 = perm(k1.xyxy + b.zzww); + + vec4 c = k2 + a.zzzz; + vec4 k3 = perm(c); + vec4 k4 = perm(c + 1.0); + + vec4 o1 = fract(k3 * (1.0 / 41.0)); + vec4 o2 = fract(k4 * (1.0 / 41.0)); + + vec4 o3 = o2 * d.z + o1 * (1.0 - d.z); + vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x); + + return o4.y * d.y + o4.x * (1.0 - d.y); +} + +vec3 hnoise(vec3 p) { + vec3 g = gnoise(p); + float s = snoise(p); + g *= 3.0 / (1.0 + exp(-16.0 * (s - 0.5))) - 1.5; + return g; +} + vec2 wave_noise(vec3 p, float off) { return (gnoise(p + vec3(0.0, 0.0, off)) * 0.4 + gnoise(2.0 * p + vec3(0.0, off, off)) * 0.2 + gnoise(3.0 * p + vec3(0.0, off, off)) * 0.225 + gnoise(4.0 * p + vec3(-off, off, 0.0)) * 0.2).xz; } @@ -123,7 +155,7 @@ float mtsmoothstep(in float edge0, in float edge1, in float x) float shadowCutoff(float x) { #if defined(ENABLE_TRANSLUCENT_FOLIAGE) && MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES - return mtsmoothstep(0.0, 0.002, x); + return mtsmoothstep(0.0, 3.0 / f_shadowfar, x); #else return step(0.0, x); #endif @@ -415,8 +447,26 @@ float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance) } #endif - #endif + +#if (defined(ENABLE_BUMPMAPS) && !defined(MATERIAL_LIQUID)) +//This is mostly a placeholder and probably should use proper textures eventually... +vec3 getBumpMap(vec2 uv) { + vec2 dr = vec2(0.25) * texelSize0; + // Sample the texture to then compute the gradient + float fx0y0 = texture2D(baseTexture, uv).r; + float fx1y0 = texture2D(baseTexture, uv + vec2(dr.x, 0.0)).r; + float fx0y1 = texture2D(baseTexture, uv + vec2(0.0, dr.y)).r; + vec2 gradient = 0.1 * vec2((fx1y0 - fx0y0) / dr.x, (fx0y1 - fx0y0) / dr.y) + 0.05 * gnoise(vec3(2.0 * uv / texelSize0, 0.0)).xy; + // Compute a set of orthonormal basis vectors representing the node's surface plane. + vec3 orth1 = normalize(cross(vNormal, mix(vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, -1.0), step(0.9, abs(vNormal.y))))); + vec3 orth2 = normalize(cross(vNormal, orth1)); + // The normal is computed using the partial derivatives along the texture space x and y axes. + // These axes in world space are assumed to be parallel to the basis vectors we defined before. + return orth1 * gradient.x + orth2 * gradient.y; +} +#endif + #endif void main(void) @@ -444,19 +494,15 @@ void main(void) // Fragment normal, can differ from vNormal which is derived from vertex normals. vec3 fNormal = vNormal; + vec3 viewVec = normalize(worldPosition + cameraOffset - cameraPosition); + #if ((defined(ENABLE_DYNAMIC_SHADOWS) && defined(ENABLE_BUMPMAPS)) && !defined(MATERIAL_LIQUID)) - vec2 dr = vec2(0.25) * texelSize0; - // Sample the texture to then compute the gradient - float fx0y0 = texture2D(baseTexture, uv).r; - float fx1y0 = texture2D(baseTexture, uv + vec2(dr.x, 0.0)).r; - float fx0y1 = texture2D(baseTexture, uv + vec2(0.0, dr.y)).r; - vec2 gradient = 0.1 * vec2((fx1y0 - fx0y0) / dr.x, (fx0y1 - fx0y0) / dr.y) + 0.05 * gnoise(vec3(2.0 * uv / texelSize0, 0.0)).xy; - // Compute a set of orthogonal basis vectors representing the node's surface plane. - vec3 orth1 = normalize(cross(vNormal, mix(vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, -1.0), step(0.9, abs(vNormal.y))))); - vec3 orth2 = normalize(cross(vNormal, orth1)); - // The normal is computed using the partial derivatives along the texture space x and y axes. - // These axes in world space are assumed to be parallel to the basis vectors we defined before. - fNormal = normalize(vNormal + orth1 * gradient.x + orth2 * gradient.y); + vec3 bump_normal = getBumpMap(uv); + // When applied to all blocks, these bump maps produce irritating Moiré effects. + // So we hide the bump maps when close up. + float moire_factor = abs(dot(vNormal, viewVec)); + bump_normal *= mtsmoothstep(0.4 * moire_factor, 0.2 * moire_factor, length(eyeVec) * fov / windowSize.x); + fNormal = normalize(vNormal + bump_normal); float adj_cosLight = max(1e-5, dot(fNormal, -v_LightDirection)); #else float adj_cosLight = cosLight; @@ -526,8 +572,6 @@ void main(void) vec3 reflect_ray = -normalize(v_LightDirection - fNormal * dot(v_LightDirection, fNormal) * 2.0); - vec3 viewVec = normalize(worldPosition + cameraOffset - cameraPosition); - // Water reflections #if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS)) @@ -548,7 +592,7 @@ void main(void) reflect_ray = -normalize(v_LightDirection - fNormal * dot(v_LightDirection, fNormal) * 2.0); float fresnel_factor = dot(fNormal, viewVec); - float brightness_factor = 1.0 - adjusted_night_ratio; + float brightness_factor = (1.0 - adjusted_night_ratio) / base.a; // A little trig hack. We go from the dot product of viewVec and normal to the dot product of viewVec and tangent to apply a fresnel effect. fresnel_factor = clamp(pow(1.0 - fresnel_factor * fresnel_factor, 8.0), 0.0, 1.0) * 0.8 + 0.2; @@ -557,10 +601,12 @@ void main(void) // Sky reflection col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.5 * brightness_factor; - vec3 water_reflect_color = 12.0 * sunTint * dayLight * fresnel_factor * mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)) * max(1.0 - shadow_uncorrected, 0.0); - // This line exists to prevent ridiculously bright reflection colors. - water_reflect_color /= clamp(max(water_reflect_color.r, max(water_reflect_color.g, water_reflect_color.b)) * 0.375, 1.0, 400.0); + // We clip the reflection color if it gets too bright + vec3 water_reflect_color = 6.0 * sunTint * dayLight * fresnel_factor * mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)) * max(1.0 - shadow_uncorrected, 0.0); + water_reflect_color /= max(0.4 * length(water_reflect_color), 1.0); + + // Sun reflection col.rgb += water_reflect_color * f_adj_shadow_strength * brightness_factor; #endif @@ -580,7 +626,7 @@ void main(void) #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES) && defined(ENABLE_TRANSLUCENT_FOLIAGE) // Simulate translucent foliage. - col.rgb += 4.0 * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) * f_adj_shadow_strength * pow(max(-dot(v_LightDirection, viewVec), 0.0), 4.0) * max(1.0 - shadow_uncorrected, 0.0); + col.rgb += 4.0 * sunTint * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) * f_adj_shadow_strength * pow(max(-dot(v_LightDirection, viewVec), 0.0), 4.0) * max(1.0 - shadow_uncorrected, 0.0); #endif } #endif diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 62de02aef..8f48cb30b 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -54,6 +54,8 @@ uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias1; uniform float zPerspectiveBias; +uniform vec3 beta_r0_l; + #ifdef ENABLE_DYNAMIC_SHADOWS vec4 getRelativePosition(in vec4 position) @@ -146,19 +148,17 @@ float snoise(vec3 p) #endif +#ifdef ENABLE_TINTED_SUNLIGHT vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) { // Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham const float beta_r0 = 1e-5; // Rayleigh scattering beta - // These factors are calculated based on expected value of scattering factor of 1e-5 - // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere - const vec3 beta_r0_l = vec3(3.3362176e-01, 8.75378289198826e-01, 1.95342379700656) * beta_r0; // wavelength-dependent scattering - const float atmosphere_height = 15000.; // height of the atmosphere in meters // sun/moon light at the ground level, after going through the atmosphere - return exp(-beta_r0_l * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); + return exp(-beta_r0_l * beta_r0 * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); } +#endif void main(void) { @@ -280,7 +280,9 @@ void main(void) adj_shadow_strength = f_shadow_strength * mtsmoothstep(0.21, 0.26, f_timeofday) * (1.0 - mtsmoothstep(0.743, 0.793, f_timeofday)); +#ifdef ENABLE_TINTED_SUNLIGHT sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), min(1.0, 4.0 * adj_shadow_strength)); +#endif } } #endif diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index b963b1ed5..b41e234e1 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -432,7 +432,7 @@ void main(void) // calculate fragment color from components: col.rgb = adjusted_night_ratio * col.rgb + // artificial light - (1.0 - adjusted_night_ratio) * ( // natural light + sunTint * (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 } diff --git a/client/shaders/second_stage/opengl_fragment.glsl b/client/shaders/second_stage/opengl_fragment.glsl index 0c39d1e94..e15e26803 100644 --- a/client/shaders/second_stage/opengl_fragment.glsl +++ b/client/shaders/second_stage/opengl_fragment.glsl @@ -12,6 +12,14 @@ struct ExposureParams { float compensationFactor; }; +uniform vec3 cdl_slope; +uniform vec3 cdl_offset; +uniform vec3 cdl_power; + +uniform float vignette_dark; +uniform float vignette_bright; +uniform float vignette_power; + uniform sampler2D rendered; uniform sampler2D bloom; @@ -148,7 +156,7 @@ void main(void) { #ifdef ENABLE_VIGNETTE - color.rgb *= 0.8 * pow(1.0 - length(uv - vec2(0.5)) * 1.4, 0.9) + 0.3; + color.rgb *= (vignette_bright - vignette_dark) * (1.0 - pow(length(uv - vec2(0.5)) * 1.4, vignette_power)) + vignette_dark; #endif #if ENABLE_TONE_MAPPING @@ -157,13 +165,7 @@ void main(void) #ifdef ENABLE_COLOR_GRADING // ASC CDL color grading - const vec3 slope = vec3(1.2, 1.0, 0.8); - const vec3 power = vec3(1.25, 1.0, 0.9); - - // Filter out blue pixels, because the color grading tends to wash them out. - float blue_factor = clamp((color.b - max(color.r, color.g)) / max(0.01, min(color.r, color.g)), 0.0, 1.0); - - color.rgb = mix(color.rgb, pow(color.rgb * slope, power), 1.); + color.rgb = mix(color.rgb, pow(max(color.rgb * cdl_slope + cdl_offset, 0.0), cdl_power), 1.); #endif color.rgb = applySaturation(color.rgb, saturation); } diff --git a/client/shaders/volumetric_light/opengl_fragment.glsl b/client/shaders/volumetric_light/opengl_fragment.glsl index 001f59465..86f012551 100644 --- a/client/shaders/volumetric_light/opengl_fragment.glsl +++ b/client/shaders/volumetric_light/opengl_fragment.glsl @@ -24,6 +24,8 @@ varying mediump vec2 varTexCoord; centroid varying vec2 varTexCoord; #endif +uniform vec3 beta_r0_l; + const float far = 1000.; float mapDepth(float depth) { @@ -46,9 +48,16 @@ float sampleVolumetricLight(vec2 uv, vec3 lightVec, float rawDepth) if (min(samplepos.x, samplepos.y) > 0. && max(samplepos.x, samplepos.y) < 1.) result += texture2D(depthmap, samplepos).r < 1. ? 0.0 : 1.0; } + +#ifdef VOLUMETRIC_DEPTH_ATTENUATION // We use the depth map to approximate the effect of depth on the light intensity. // The exponent was chosen based on aesthetic preference. + // To make this phsyically accurate, the brightness here should scale linearly with depth, + // but this would make the godrays either too faint or too strong in many cases. return result / samples * pow(texture2D(depthmap, uv).r, 128.0); +#else + return result / samples; +#endif } vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) @@ -56,13 +65,10 @@ vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) // Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham const float beta_r0 = 1e-5; // Rayleigh scattering beta - // These factors are calculated based on expected value of scattering factor of 1e-5 - // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere - const vec3 beta_r0_l = vec3(3.3362176e-01, 8.75378289198826e-01, 1.95342379700656) * beta_r0; // wavelength-dependent scattering - const float atmosphere_height = 15000.; // height of the atmosphere in meters // sun/moon light at the ground level, after going through the atmosphere - return exp(-beta_r0_l * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); + + return exp(-beta_r0_l * beta_r0 * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); } vec3 applyVolumetricLight(vec3 color, vec2 uv, float rawDepth) diff --git a/doc/lua_api.md b/doc/lua_api.md index f2f0a5ba3..499810a46 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8706,6 +8706,21 @@ child will follow movement and rotation of that bone. * Currently, bloom `intensity` and `strength_factor` affect volumetric lighting `strength` and vice versa. This behavior is to be changed in the future, do not rely on it. + * `beta_r0`: the scattering coefficient that controls the tint of sunlight during sunrise and sunset. + * Defaults to { x = 3.3362176e-01, y = 8.75378289198826e-01, z = 1.95342379700656} which is physically accurate. + * This may be used to create effects like differently colored sunsets on alien planets. + * Setting all components to zero effectively disables tinted sunlight. + * `vignette`: is a table that controls the vignette post-processing effect. + * This has no effect on clients who have the "Vignette" effects disabled. + * `dark`: brightness of the vignette's darkest part (default: `0.3`) + * `bright`: brightness of the vignette's brightest part (default: `1.1`) + * `power`: the higher this is set, the more the vignette "retreats" to the edges of the screen (default: `1.1`) + * `cdl`: is a table that controls the ASL CDL color grading effect. + * This has no effect on clients who have the "Color grading" effect disabled. + * The output color follows the equation: `out = pow(in*slope+offset, power)` + * `slope`: "Tints" the scene, affects brighter colors more (default: `{x=1.2, y=1.0, z=0.8}`) + * `offset`: This can be used to brighten or darken the scene (default: `{x=0.0, y=0.0, z=0.0}`) + * `power`: Tints mostly the darker parts of the scene (default: `{x=1.25, y=1.0, z=0.9}`) * `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`. diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 9d4d28300..f156305f0 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -53,8 +53,7 @@ Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc, m_material.FogEnable = true; m_material.AntiAliasing = video::EAAM_SIMPLE; if (m_enable_shaders) { - bool shaded_clouds = g_settings->getBool("soft_clouds") && g_settings->getBool("enable_dynamic_shadows"); - auto sid = ssrc->getShader(shaded_clouds ? "soft_clouds" : "cloud_shader", TILE_MATERIAL_ALPHA); + auto sid = ssrc->getShader("cloud_shader", TILE_MATERIAL_ALPHA); m_material.MaterialType = ssrc->getShaderInfo(sid).material; } else { m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; @@ -226,210 +225,137 @@ void Clouds::updateMesh() v3f pos(p0.X, m_params.height * BS, p0.Y); - if (shaded_clouds_enabled) { - bool neighbours[4] = {false, false, false, false}; - if (INAREA(xi - 1, zi, m_cloud_radius_i)) - neighbours[0] = grid[GETINDEX(xi - 1, zi, m_cloud_radius_i)]; - if (INAREA(xi, zi - 1, m_cloud_radius_i)) - neighbours[1] = grid[GETINDEX(xi, zi - 1, m_cloud_radius_i)]; - if (INAREA(xi + 1, zi, m_cloud_radius_i)) - neighbours[2] = grid[GETINDEX(xi + 1, zi, m_cloud_radius_i)]; - if (INAREA(xi, zi + 1, m_cloud_radius_i)) - neighbours[3] = grid[GETINDEX(xi, zi + 1, m_cloud_radius_i)]; + video::S3DVertex v[4] = { + video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 1), + video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 1), + video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 0), + video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0) + }; - video::S3DVertex v[32]; - v[ 0].Pos = core::vector3df( -rx, ry, -rz); - v[ 1].Pos = core::vector3df(-0.75 * rx, ry, -rz); - v[ 2].Pos = core::vector3df( 0.75 * rx, ry, -rz); - v[ 3].Pos = core::vector3df( rx, ry, -rz); - v[ 4].Pos = core::vector3df( -rx, ry, -0.75 * rz); - v[ 5].Pos = core::vector3df(-0.75 * rx, ry, -0.75 * rz); - v[ 6].Pos = core::vector3df( 0.75 * rx, ry, -0.75 * rz); - v[ 7].Pos = core::vector3df( rx, ry, -0.75 * rz); - v[ 8].Pos = core::vector3df( -rx, ry, 0.75 * rz); - v[ 9].Pos = core::vector3df(-0.75 * rx, ry, 0.75 * rz); - v[10].Pos = core::vector3df( 0.75 * rx, ry, 0.75 * rz); - v[11].Pos = core::vector3df( rx, ry, 0.75 * rz); - v[12].Pos = core::vector3df( -rx, ry, rz); - v[13].Pos = core::vector3df(-0.75 * rx, ry, rz); - v[14].Pos = core::vector3df( 0.75 * rx, ry, rz); - v[15].Pos = core::vector3df( rx, ry, rz); - - // These normals are intentionally left unnormalized - if (neighbours[0]) { - v[ 0].Normal.X -= 1.0; - v[ 4].Normal.X -= 1.0; - v[ 8].Normal.X -= 1.0; - v[12].Normal.X -= 1.0; - } - if (neighbours[1]) { - v[0].Normal.Z -= 1.0; - v[1].Normal.Z -= 1.0; - v[2].Normal.Z -= 1.0; - v[3].Normal.Z -= 1.0; - } - if (neighbours[2]) { - v[ 3].Normal.X += 1.0; - v[ 7].Normal.X += 1.0; - v[11].Normal.X += 1.0; - v[15].Normal.X += 1.0; - } - if (neighbours[3]) { - v[12].Normal.Z += 1.0; - v[13].Normal.Z += 1.0; - v[14].Normal.Z += 1.0; - v[15].Normal.Z += 1.0; - } - - for (int i = 0; i < 16; ++i) { - v[i + 32] = v[i]; - v[i + 32].Pos.Y = -ry; - - v[i].Normal = core::vector3df(0.0, 1.0, 0.0); - v[i + 32].Normal = core::vector3df(0.0, -1.0, 0.0); + for (u32 i = 0; i < num_faces_to_draw; i++) + { + switch (i) + { + case 0: // top + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(0, 1, 0); + } + v[0].Pos.set(-rx, ry, -rz); + v[1].Pos.set(-rx, ry, rz); + v[2].Pos.set(rx, ry, rz); + v[3].Pos.set(rx, ry, -rz); + break; + case 1: // back + if (INAREA(xi, zi - 1, m_cloud_radius_i)) { + u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(0, 0, -1); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_1; + vertex.Normal.set(0, 0, -1); + } + } + v[0].Pos.set(-rx, ry, -rz); + v[1].Pos.set(rx, ry, -rz); + v[2].Pos.set(rx, 0, -rz); + v[3].Pos.set(-rx, 0, -rz); + break; + case 2: //right + if (INAREA(xi + 1, zi, m_cloud_radius_i)) { + u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(1, 0, 0); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_2; + vertex.Normal.set(1, 0, 0); + } + } + v[0].Pos.set(rx, ry, -rz); + v[1].Pos.set(rx, ry, rz); + v[2].Pos.set(rx, 0, rz); + v[3].Pos.set(rx, 0, -rz); + break; + case 3: // front + if (INAREA(xi, zi + 1, m_cloud_radius_i)) { + u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(0, 0, -1); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_1; + vertex.Normal.set(0, 0, -1); + } + } + v[0].Pos.set(rx, ry, rz); + v[1].Pos.set(-rx, ry, rz); + v[2].Pos.set(-rx, 0, rz); + v[3].Pos.set(rx, 0, rz); + break; + case 4: // left + if (INAREA(xi - 1, zi, m_cloud_radius_i)) { + u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(-1, 0, 0); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_2; + vertex.Normal.set(-1, 0, 0); + } + } + v[0].Pos.set(-rx, ry, rz); + v[1].Pos.set(-rx, ry, -rz); + v[2].Pos.set(-rx, 0, -rz); + v[3].Pos.set(-rx, 0, rz); + break; + case 5: // bottom + for (video::S3DVertex& vertex : v) { + vertex.Color = c_bottom; + vertex.Normal.set(0, -1, 0); + } + v[0].Pos.set(rx, 0, rz); + v[1].Pos.set(-rx, 0, rz); + v[2].Pos.set(-rx, 0, -rz); + v[3].Pos.set(rx, 0, -rz); + break; } for (video::S3DVertex& vertex : v) { - vertex.Color = shadow.toSColor(); vertex.Pos += pos; - } - - //top - - } - else { - video::S3DVertex v[4] = { - video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 1), - video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 1), - video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 0), - video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0) - }; - - for (u32 i = 0; i < num_faces_to_draw; i++) - { - switch (i) - { - case 0: // top - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(0, 1, 0); - } - v[0].Pos.set(-rx, ry, -rz); - v[1].Pos.set(-rx, ry, rz); - v[2].Pos.set(rx, ry, rz); - v[3].Pos.set(rx, ry, -rz); - break; - case 1: // back - if (INAREA(xi, zi - 1, m_cloud_radius_i)) { - u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(0, 0, -1); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_1; - vertex.Normal.set(0, 0, -1); - } - } - v[0].Pos.set(-rx, ry, -rz); - v[1].Pos.set(rx, ry, -rz); - v[2].Pos.set(rx, 0, -rz); - v[3].Pos.set(-rx, 0, -rz); - break; - case 2: //right - if (INAREA(xi + 1, zi, m_cloud_radius_i)) { - u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(1, 0, 0); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_2; - vertex.Normal.set(1, 0, 0); - } - } - v[0].Pos.set(rx, ry, -rz); - v[1].Pos.set(rx, ry, rz); - v[2].Pos.set(rx, 0, rz); - v[3].Pos.set(rx, 0, -rz); - break; - case 3: // front - if (INAREA(xi, zi + 1, m_cloud_radius_i)) { - u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(0, 0, -1); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_1; - vertex.Normal.set(0, 0, -1); - } - } - v[0].Pos.set(rx, ry, rz); - v[1].Pos.set(-rx, ry, rz); - v[2].Pos.set(-rx, 0, rz); - v[3].Pos.set(rx, 0, rz); - break; - case 4: // left - if (INAREA(xi - 1, zi, m_cloud_radius_i)) { - u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(-1, 0, 0); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_2; - vertex.Normal.set(-1, 0, 0); - } - } - v[0].Pos.set(-rx, ry, rz); - v[1].Pos.set(-rx, ry, -rz); - v[2].Pos.set(-rx, 0, -rz); - v[3].Pos.set(-rx, 0, rz); - break; - case 5: // bottom - for (video::S3DVertex& vertex : v) { - vertex.Color = c_bottom; - vertex.Normal.set(0, -1, 0); - } - v[0].Pos.set(rx, 0, rz); - v[1].Pos.set(-rx, 0, rz); - v[2].Pos.set(-rx, 0, -rz); - v[3].Pos.set(rx, 0, -rz); - break; - } - - for (video::S3DVertex& vertex : v) { - vertex.Pos += pos; - vertices.push_back(vertex); - } + vertices.push_back(vertex); } } } diff --git a/src/client/game.cpp b/src/client/game.cpp index 695581f3f..678116e0a 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -395,8 +395,6 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_camera_projinv_pixel{"mCameraProjInv"}; CachedVertexShaderSetting m_camera_view_vertex{"mCameraView"}; CachedPixelShaderSetting m_camera_view_pixel{"mCameraView"}; - CachedPixelShaderSetting m_camera_near_pixel{"cameraNear"}; - CachedPixelShaderSetting m_camera_far_pixel{"cameraFar"}; CachedPixelShaderSetting m_texture0{"texture0"}; CachedPixelShaderSetting m_texture1{"texture1"}; CachedPixelShaderSetting m_texture2{"texture2"}; @@ -428,6 +426,18 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_moon_brightness_pixel{"moonBrightness"}; CachedPixelShaderSetting m_volumetric_light_strength_pixel{"volumetricLightStrength"}; + CachedPixelShaderSetting + m_volumetric_beta_r0_pixel{ "beta_r0_l" }; + CachedVertexShaderSetting + m_volumetric_beta_r0_vertex{ "beta_r0_l" }; + CachedPixelShaderSetting m_cdl_slope_pixel{"cdl_slope"}; + CachedPixelShaderSetting m_cdl_offset_pixel{"cdl_offset"}; + CachedPixelShaderSetting m_cdl_power_pixel{"cdl_power"}; + CachedPixelShaderSetting m_vignette_dark_pixel{"vignette_dark"}; + CachedPixelShaderSetting m_vignette_bright_pixel{"vignette_bright"}; + CachedPixelShaderSetting m_vignette_power_pixel{"vignette_power"}; + CachedPixelShaderSetting m_fov_pixel{"fov"}; + CachedPixelShaderSetting m_window_size_pixel{"windowSize"}; static constexpr std::array SETTING_CALLBACKS = { "exposure_compensation", @@ -457,6 +467,7 @@ public: m_user_exposure_compensation = g_settings->getFloat("exposure_compensation", -1.0f, 1.0f); m_bloom_enabled = g_settings->getBool("enable_bloom"); m_volumetric_light_enabled = g_settings->getBool("enable_volumetric_lighting") && m_bloom_enabled; + m_gamma = g_settings->getFloat("secondstage_gamma"); } ~GameGlobalShaderConstantSetter() @@ -506,10 +517,11 @@ public: m_camera_view_vertex.set(camera_view, services); m_camera_view_pixel.set(camera_view, services); - float camera_near = m_client->getCamera()->getCameraNode()->getNearValue(); - m_camera_near_pixel.set(&camera_near, services); - float camera_far = m_client->getCamera()->getCameraNode()->getFarValue(); - m_camera_far_pixel.set(&camera_far, services); + float fov = m_client->getCamera()->getFovMax(); + m_fov_pixel.set(&fov, services); + v2u32 window_size_int = RenderingEngine::getWindowSize(); + core::vector2df window_size = core::vector2df(window_size_int.X, window_size_int.Y); + m_window_size_pixel.set(window_size, services); SamplerLayer_t tex_id; tex_id = 0; @@ -552,6 +564,26 @@ public: video::SColorf artificial_light = lighting.artificial_light_color; m_artificial_light.set(artificial_light, services); + float gamma = m_gamma; + m_gamma_pixel.set(&gamma, services); + + if (g_settings->getBool("enable_vignette")) { + const Vignette &vignette_params = lighting.vignette; + m_vignette_dark_pixel.set(&vignette_params.dark, services); + m_vignette_bright_pixel.set(&vignette_params.bright, services); + m_vignette_power_pixel.set(&vignette_params.power, services); + } + + if (g_settings->getBool("enable_color_grading")) { + const ColorDecisionList& cdl_params = lighting.cdl; + core::vector3df slope = cdl_params.slope; + m_cdl_slope_pixel.set(slope, services); + core::vector3df offset = cdl_params.offset; + m_cdl_offset_pixel.set(offset, services); + core::vector3df power = cdl_params.power; + m_cdl_power_pixel.set(power, services); + } + if (m_volumetric_light_enabled) { // Map directional light to screen space auto camera_node = m_client->getCamera()->getCameraNode(); @@ -594,6 +626,10 @@ public: float volumetric_light_strength = lighting.volumetric_light_strength; m_volumetric_light_strength_pixel.set(&volumetric_light_strength, services); + + core::vector3df beta_r0 = lighting.volumetric_beta_r0; + m_volumetric_beta_r0_vertex.set(beta_r0, services); + m_volumetric_beta_r0_pixel.set(beta_r0, services); } } diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 2f87d40d5..acc786454 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -727,6 +727,9 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, if (shadow_soft_radius < 1.0f) shadow_soft_radius = 1.0f; shaders_header << "#define SOFTSHADOWRADIUS " << shadow_soft_radius << "\n"; + + if (g_settings->getBool("enable_sun_tint")) + shaders_header << "#define ENABLE_TINTED_SUNLIGHT 1\n"; } if (g_settings->getBool("enable_bloom")) { @@ -757,6 +760,10 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, shaders_header << "#define VOLUMETRIC_LIGHT 1\n"; } + if (g_settings->getBool("enable_volumetric_depth_attenuation")) { + shaders_header << "#define VOLUMETRIC_DEPTH_ATTENUATION 1\n"; + } + shaders_header << "#line 0\n"; // reset the line counter for meaningful diagnostics std::string common_header = shaders_header.str(); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index d8d035ee0..47a70d6ee 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -344,12 +344,13 @@ void set_default_settings() settings->setDefault("enable_auto_exposure", "false"); settings->setDefault("enable_color_grading", "false"); settings->setDefault("enable_vignette", "false"); - settings->setDefault("gamma", "1.6"); + settings->setDefault("secondstage_gamma", "1.6"); settings->setDefault("debanding", "true"); settings->setDefault("antialiasing", "none"); settings->setDefault("enable_bloom", "false"); settings->setDefault("enable_bloom_debug", "false"); settings->setDefault("enable_volumetric_lighting", "false"); + settings->setDefault("enable_volumetric_depth_attenuation", "false"); settings->setDefault("enable_bumpmaps", "false"); settings->setDefault("enable_water_reflections", "false"); settings->setDefault("enable_translucent_foliage", "false"); @@ -368,6 +369,7 @@ void set_default_settings() settings->setDefault("shadow_update_frames", "8"); settings->setDefault("shadow_soft_radius", "5.0"); settings->setDefault("shadow_sky_body_orbit_tilt", "0.0"); + settings->setDefault("enable_sun_tint", "false"); // Input settings->setDefault("invert_mouse", "false"); diff --git a/src/lighting.h b/src/lighting.h index ff9ba091d..85e62b9d0 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once #include "SColor.h" +#include "vector3d.h" using namespace irr; @@ -48,14 +49,46 @@ struct AutoExposure AutoExposure(); }; +/** + * Parameters for vignette in post + * + */ +struct Vignette { + /// @brief The darkest part of the vignette will be darkened/brightened by this factor. + float dark = 0.3f; + /// @brief The brightest part of the vignette will be darkened/brightened by this factor. + float bright = 1.1f; + /// @brief Describes the blending between dark and bright. Higher values mean darkening is more intense at the screen edges. + float power = 1.1f; +}; + +/** + * ASL CDL parameters + * + * Colors in ASL CDL follow the following equation: + * + * out = pow(in * slope + offset, power) + * + */ +struct ColorDecisionList { + core::vector3df slope{1.2, 1.0, 0.8}; + core::vector3df offset{0.0, 0.0, 0.0}; + core::vector3df power{1.25, 1.0, 0.9}; +}; + /** Describes ambient light settings for a player */ struct Lighting { AutoExposure exposure; + Vignette vignette; + ColorDecisionList cdl; float shadow_intensity {0.0f}; float saturation {1.0f}; float volumetric_light_strength {0.0f}; + // These factors are calculated based on expected value of scattering factor of 1e-5 + // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere + core::vector3df volumetric_beta_r0{ 3.3362176e-01, 8.75378289198826e-01, 1.95342379700656 }; video::SColor artificial_light_color{ 255, 133, 133, 133 }; video::SColor shadow_tint {255, 0, 0, 0}; float bloom_intensity {0.05f}; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 346effe08..2864e742d 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1830,5 +1830,13 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt) >> lighting.bloom_radius; if (pkt->getRemainingBytes() >= 4) *pkt >> lighting.artificial_light_color; + if (pkt->getRemainingBytes() >= 60) + *pkt >> lighting.volumetric_beta_r0; + *pkt >> lighting.vignette.dark + >> lighting.vignette.bright + >> lighting.vignette.power; + *pkt >> lighting.cdl.slope; + *pkt >> lighting.cdl.offset; + *pkt >> lighting.cdl.power; } } diff --git a/src/network/networkprotocol.cpp b/src/network/networkprotocol.cpp index 40f8acef1..5ad852d37 100644 --- a/src/network/networkprotocol.cpp +++ b/src/network/networkprotocol.cpp @@ -58,6 +58,7 @@ Rename TOCLIENT_DEATHSCREEN to TOCLIENT_DEATHSCREEN_LEGACY Rename TOSERVER_RESPAWN to TOSERVER_RESPAWN_LEGACY Support float animation frame numbers in TOCLIENT_LOCAL_PLAYER_ANIMATIONS + Add beta_r0, vignette and cdl parameters to Lighting packets [scheduled bump for 5.10.0] */ diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 2ca3a4177..41eae4b1d 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2654,6 +2654,12 @@ int ObjectRef::l_set_lighting(lua_State *L) if (lua_istable(L, -1)) { getfloatfield(L, -1, "strength", lighting.volumetric_light_strength); lighting.volumetric_light_strength = rangelim(lighting.volumetric_light_strength, 0.0f, 1.0f); + + lua_getfield(L, -1, "beta_r0"); + if (!lua_isnil(L, -1)) { + lighting.volumetric_beta_r0 = read_v3f(L, -1); + } + lua_pop(L, 1); // beta_r0 } lua_pop(L, 1); // volumetric_light @@ -2664,6 +2670,31 @@ int ObjectRef::l_set_lighting(lua_State *L) lighting.bloom_radius = getfloatfield_default(L, -1, "radius", lighting.bloom_radius); } lua_pop(L, 1); // bloom + + lua_getfield(L, 2, "vignette"); + if (lua_istable(L, -1)) { + lighting.vignette.dark = getfloatfield_default(L, -1, "dark", lighting.vignette.dark); + lighting.vignette.bright = getfloatfield_default(L, -1, "bright", lighting.vignette.bright); + lighting.vignette.power = getfloatfield_default(L, -1, "power", lighting.vignette.power); + } + lua_pop(L, 1); // vignette + + lua_getfield(L, 2, "cdl"); + if (lua_istable(L, -1)) { + lua_getfield(L, -1, "slope"); + if (!lua_isnil(L, -1)) + lighting.cdl.slope = read_v3f(L, -1); + lua_pop(L, 1); // slope + lua_getfield(L, -1, "offset"); + if (!lua_isnil(L, -1)) + lighting.cdl.offset = read_v3f(L, -1); + lua_pop(L, 1); // offset + lua_getfield(L, -1, "power"); + if (!lua_isnil(L, -1)) + lighting.cdl.power = read_v3f(L, -1); + lua_pop(L, 1); // power + } + lua_pop(L, 1); // cdl } getServer(L)->setLighting(player, lighting); @@ -2709,6 +2740,8 @@ int ObjectRef::l_get_lighting(lua_State *L) lua_newtable(L); // "volumetric_light" lua_pushnumber(L, lighting.volumetric_light_strength); lua_setfield(L, -2, "strength"); + push_v3f(L, lighting.volumetric_beta_r0); + lua_setfield(L, -2, "beta_r0"); lua_setfield(L, -2, "volumetric_light"); lua_newtable(L); // "bloom" lua_pushnumber(L, lighting.bloom_intensity); @@ -2718,6 +2751,22 @@ int ObjectRef::l_get_lighting(lua_State *L) lua_pushnumber(L, lighting.bloom_radius); lua_setfield(L, -2, "radius"); lua_setfield(L, -2, "bloom"); + lua_newtable(L); // "vignette" + lua_pushnumber(L, lighting.vignette.dark); + lua_setfield(L, -2, "dark"); + lua_pushnumber(L, lighting.vignette.bright); + lua_setfield(L, -2, "bright"); + lua_pushnumber(L, lighting.vignette.power); + lua_setfield(L, -2, "power"); + lua_setfield(L, -2, "vignette"); + lua_newtable(L); // "cdl" + push_v3f(L, lighting.cdl.slope); + lua_setfield(L, -2, "slope"); + push_v3f(L, lighting.cdl.offset); + lua_setfield(L, -2, "offset"); + push_v3f(L, lighting.cdl.power); + lua_setfield(L, -2, "power"); + lua_setfield(L, -2, "cdl"); return 1; } diff --git a/src/server.cpp b/src/server.cpp index f690be745..0252aef78 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1913,7 +1913,7 @@ void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override, Send(&pkt); } -void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) +void Server::SendSetLighting(session_t peer_id, const Lighting & lighting) { NetworkPacket pkt(TOCLIENT_SET_LIGHTING, 4, peer_id); @@ -1932,6 +1932,13 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) pkt << lighting.bloom_intensity << lighting.bloom_strength_factor << lighting.bloom_radius; pkt << lighting.artificial_light_color; + pkt << lighting.volumetric_beta_r0; + pkt << lighting.vignette.dark + << lighting.vignette.bright + << lighting.vignette.power; + pkt << lighting.cdl.slope; + pkt << lighting.cdl.offset; + pkt << lighting.cdl.power; Send(&pkt); } From 6ad43575ff5354e23113bc99edfaa737f12744ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 27 Oct 2024 21:37:51 +0100 Subject: [PATCH 12/40] Remove smooth clouds shaders --- .../shaders/soft_clouds/opengl_fragment.glsl | 22 ----------------- client/shaders/soft_clouds/opengl_vertex.glsl | 24 ------------------- 2 files changed, 46 deletions(-) delete mode 100644 client/shaders/soft_clouds/opengl_fragment.glsl delete mode 100644 client/shaders/soft_clouds/opengl_vertex.glsl diff --git a/client/shaders/soft_clouds/opengl_fragment.glsl b/client/shaders/soft_clouds/opengl_fragment.glsl deleted file mode 100644 index 1cf0ef0bb..000000000 --- a/client/shaders/soft_clouds/opengl_fragment.glsl +++ /dev/null @@ -1,22 +0,0 @@ -uniform lowp vec4 fogColor; -uniform float fogDistance; -uniform float fogShadingParameter; -varying highp vec3 eyeVec; - -varying lowp vec4 varColor; -varying lowp vec3 normal; -uniform vec3 v_LightDirection; - -void main(void) -{ - float brightness = max(dot(-v_LightDirection, normal), 0.0); - vec4 col = varColor; - - col.rgb *= brightness; - - float clarity = clamp(fogShadingParameter - - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - col.rgb = mix(fogColor.rgb, col.rgb, clarity); - - gl_FragColor = col; -} diff --git a/client/shaders/soft_clouds/opengl_vertex.glsl b/client/shaders/soft_clouds/opengl_vertex.glsl deleted file mode 100644 index 72f747b87..000000000 --- a/client/shaders/soft_clouds/opengl_vertex.glsl +++ /dev/null @@ -1,24 +0,0 @@ -uniform lowp vec4 materialColor; - -varying lowp vec4 varColor; - -varying highp vec3 eyeVec; - -varying lowp vec3 normal; - -void main(void) -{ - gl_Position = mWorldViewProj * inVertexPosition; - -#ifdef GL_ES - vec4 color = inVertexColor.bgra; -#else - vec4 color = inVertexColor; -#endif - - color *= materialColor; - varColor = color; - normal = inVertexNormal; - - eyeVec = -(mWorldView * inVertexPosition).xyz; -} From 2fd22c1850a4938523478598443e8b9db09d85a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:07:52 +0100 Subject: [PATCH 13/40] Fixes and proper tangent space --- .../shaders/nodes_shader/opengl_fragment.glsl | 50 +-- .../shaders/nodes_shader/opengl_vertex.glsl | 4 + .../shaders/second_stage/opengl_fragment.glsl | 5 - .../volumetric_light/opengl_fragment.glsl | 2 +- irr/include/IMeshManipulator.h | 20 ++ irr/src/CMeshManipulator.cpp | 329 ++++++++++++++++++ irr/src/CMeshManipulator.h | 6 + src/client/mapblock_mesh.cpp | 61 ++-- src/client/mapblock_mesh.h | 4 +- src/client/mesh_generator_thread.cpp | 3 +- src/client/mesh_generator_thread.h | 1 + src/lighting.h | 2 +- 12 files changed, 417 insertions(+), 70 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index e345a7e88..e682aca88 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -44,6 +44,8 @@ uniform vec2 windowSize; uniform float fov; varying vec3 vNormal; +varying vec3 vTangent; +varying vec3 vBinormal; 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. @@ -100,36 +102,6 @@ vec3 gnoise(vec3 p){ ); } -float snoise(vec3 p) -{ - vec3 a = floor(p); - vec3 d = p - a; - d = d * d * (3.0 - 2.0 * d); - - vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0); - vec4 k1 = perm(b.xyxy); - vec4 k2 = perm(k1.xyxy + b.zzww); - - vec4 c = k2 + a.zzzz; - vec4 k3 = perm(c); - vec4 k4 = perm(c + 1.0); - - vec4 o1 = fract(k3 * (1.0 / 41.0)); - vec4 o2 = fract(k4 * (1.0 / 41.0)); - - vec4 o3 = o2 * d.z + o1 * (1.0 - d.z); - vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x); - - return o4.y * d.y + o4.x * (1.0 - d.y); -} - -vec3 hnoise(vec3 p) { - vec3 g = gnoise(p); - float s = snoise(p); - g *= 3.0 / (1.0 + exp(-16.0 * (s - 0.5))) - 1.5; - return g; -} - vec2 wave_noise(vec3 p, float off) { return (gnoise(p + vec3(0.0, 0.0, off)) * 0.4 + gnoise(2.0 * p + vec3(0.0, off, off)) * 0.2 + gnoise(3.0 * p + vec3(0.0, off, off)) * 0.225 + gnoise(4.0 * p + vec3(-off, off, 0.0)) * 0.2).xz; } @@ -457,13 +429,11 @@ vec3 getBumpMap(vec2 uv) { float fx0y0 = texture2D(baseTexture, uv).r; float fx1y0 = texture2D(baseTexture, uv + vec2(dr.x, 0.0)).r; float fx0y1 = texture2D(baseTexture, uv + vec2(0.0, dr.y)).r; + // We get the gradient using partial derivatives vec2 gradient = 0.1 * vec2((fx1y0 - fx0y0) / dr.x, (fx0y1 - fx0y0) / dr.y) + 0.05 * gnoise(vec3(2.0 * uv / texelSize0, 0.0)).xy; - // Compute a set of orthonormal basis vectors representing the node's surface plane. - vec3 orth1 = normalize(cross(vNormal, mix(vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, -1.0), step(0.9, abs(vNormal.y))))); - vec3 orth2 = normalize(cross(vNormal, orth1)); - // The normal is computed using the partial derivatives along the texture space x and y axes. - // These axes in world space are assumed to be parallel to the basis vectors we defined before. - return orth1 * gradient.x + orth2 * gradient.y; + vec3 tangent_space = normalize(vec3(gradient, 1.0)); + // Convert tangent space information to real space + return -vTangent * tangent_space.x + vBinormal * tangent_space.y + vNormal * tangent_space.z; } #endif @@ -501,10 +471,10 @@ void main(void) // When applied to all blocks, these bump maps produce irritating Moiré effects. // So we hide the bump maps when close up. float moire_factor = abs(dot(vNormal, viewVec)); - bump_normal *= mtsmoothstep(0.4 * moire_factor, 0.2 * moire_factor, length(eyeVec) * fov / windowSize.x); - fNormal = normalize(vNormal + bump_normal); + moire_factor = mtsmoothstep(0.4 * moire_factor, 0.2 * moire_factor, length(eyeVec) * fov / windowSize.x); + fNormal = normalize(mix(fNormal, bump_normal, moire_factor)); float adj_cosLight = max(1e-5, dot(fNormal, -v_LightDirection)); -#else +#else float adj_cosLight = cosLight; #endif @@ -642,7 +612,7 @@ void main(void) // Note: clarity = (1 - fogginess) float clarity = clamp(fogShadingParameter - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - + #ifdef ENABLE_TINTED_FOG float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b); // Prevent zero division. diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 8f48cb30b..57c2d568a 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -7,6 +7,8 @@ uniform highp vec3 cameraOffset; uniform float animationTimer; varying vec3 vNormal; +varying vec3 vTangent; +varying vec3 vBinormal; 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. @@ -209,6 +211,8 @@ void main(void) normalPass = normalize((inVertexNormal+1)/2); #endif vNormal = inVertexNormal; + vTangent = inVertexTangent.xyz; + vBinormal = inVertexBinormal.xyz; // Calculate color. vec4 color = inVertexColor; diff --git a/client/shaders/second_stage/opengl_fragment.glsl b/client/shaders/second_stage/opengl_fragment.glsl index e15e26803..3492917d1 100644 --- a/client/shaders/second_stage/opengl_fragment.glsl +++ b/client/shaders/second_stage/opengl_fragment.glsl @@ -111,11 +111,6 @@ vec3 screen_space_dither(highp vec2 frag_coord) { } #endif -float sFunction(float x, float a) { - x = 2.0 * x - 1.0; - return 0.5 * sign(x) * pow(abs(x), a) + 0.5; -} - void main(void) { vec2 uv = varTexCoord.st; diff --git a/client/shaders/volumetric_light/opengl_fragment.glsl b/client/shaders/volumetric_light/opengl_fragment.glsl index 86f012551..0a2bba60e 100644 --- a/client/shaders/volumetric_light/opengl_fragment.glsl +++ b/client/shaders/volumetric_light/opengl_fragment.glsl @@ -53,7 +53,7 @@ float sampleVolumetricLight(vec2 uv, vec3 lightVec, float rawDepth) // We use the depth map to approximate the effect of depth on the light intensity. // The exponent was chosen based on aesthetic preference. // To make this phsyically accurate, the brightness here should scale linearly with depth, - // but this would make the godrays either too faint or too strong in many cases. + // but this would make the godrays either too faint or too strong in many cases. return result / samples * pow(texture2D(depthmap, uv).r, 128.0); #else return result / samples; diff --git a/irr/include/IMeshManipulator.h b/irr/include/IMeshManipulator.h index de3d84416..7dd0e46fd 100644 --- a/irr/include/IMeshManipulator.h +++ b/irr/include/IMeshManipulator.h @@ -42,6 +42,26 @@ public: virtual void recalculateNormals(IMeshBuffer *buffer, bool smooth = false, bool angleWeighted = false) const = 0; + //! Recalculates tangents, requires a tangent mesh + /** \param mesh Mesh on which the operation is performed. + \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the mesh are used unchanged. + \param smooth If the normals shall be smoothed. + \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. + */ + virtual void recalculateTangents(IMesh* mesh, + bool recalculateNormals = false, bool smooth = false, + bool angleWeighted = false) const = 0; + + //! Recalculates tangents, requires a tangent mesh buffer + /** \param buffer Meshbuffer on which the operation is performed. + \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the buffer are used unchanged. + \param smooth If the normals shall be smoothed. + \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. + */ + virtual void recalculateTangents(IMeshBuffer* buffer, + bool recalculateNormals = false, bool smooth = false, + bool angleWeighted = false) const = 0; + //! Scales the actual mesh, not a scene node. /** \param mesh Mesh on which the operation is performed. \param factor Scale factor for each axis. */ diff --git a/irr/src/CMeshManipulator.cpp b/irr/src/CMeshManipulator.cpp index 67b22a07e..556a17507 100644 --- a/irr/src/CMeshManipulator.cpp +++ b/irr/src/CMeshManipulator.cpp @@ -80,6 +80,335 @@ void recalculateNormalsT(IMeshBuffer *buffer, bool smooth, bool angleWeighted) } } +namespace +{ + void calculateTangents( + core::vector3df& normal, + core::vector3df& tangent, + core::vector3df& binormal, + const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices + const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords + { + // choose one of them: + //#define USE_NVIDIA_GLH_VERSION // use version used by nvidia in glh headers +#define USE_IRR_VERSION + +#ifdef USE_IRR_VERSION + + core::vector3df v1 = vt1 - vt2; + core::vector3df v2 = vt3 - vt1; + normal = v2.crossProduct(v1); + normal.normalize(); + + // binormal + + f32 deltaX1 = tc1.X - tc2.X; + f32 deltaX2 = tc3.X - tc1.X; + binormal = (v1 * deltaX2) - (v2 * deltaX1); + binormal.normalize(); + + // tangent + + f32 deltaY1 = tc1.Y - tc2.Y; + f32 deltaY2 = tc3.Y - tc1.Y; + tangent = (v1 * deltaY2) - (v2 * deltaY1); + tangent.normalize(); + + // adjust + + core::vector3df txb = tangent.crossProduct(binormal); + if (txb.dotProduct(normal) < 0.0f) + { + tangent *= -1.0f; + binormal *= -1.0f; + } + +#endif // USE_IRR_VERSION + +#ifdef USE_NVIDIA_GLH_VERSION + + tangent.set(0, 0, 0); + binormal.set(0, 0, 0); + + core::vector3df v1(vt2.X - vt1.X, tc2.X - tc1.X, tc2.Y - tc1.Y); + core::vector3df v2(vt3.X - vt1.X, tc3.X - tc1.X, tc3.Y - tc1.Y); + + core::vector3df txb = v1.crossProduct(v2); + if (!core::iszero(txb.X)) + { + tangent.X = -txb.Y / txb.X; + binormal.X = -txb.Z / txb.X; + } + + v1.X = vt2.Y - vt1.Y; + v2.X = vt3.Y - vt1.Y; + txb = v1.crossProduct(v2); + + if (!core::iszero(txb.X)) + { + tangent.Y = -txb.Y / txb.X; + binormal.Y = -txb.Z / txb.X; + } + + v1.X = vt2.Z - vt1.Z; + v2.X = vt3.Z - vt1.Z; + txb = v1.crossProduct(v2); + + if (!core::iszero(txb.X)) + { + tangent.Z = -txb.Y / txb.X; + binormal.Z = -txb.Z / txb.X; + } + + tangent.normalize(); + binormal.normalize(); + + normal = tangent.crossProduct(binormal); + normal.normalize(); + + binormal = tangent.crossProduct(normal); + binormal.normalize(); + + core::plane3d pl(vt1, vt2, vt3); + + if (normal.dotProduct(pl.Normal) < 0.0f) + normal *= -1.0f; + +#endif // USE_NVIDIA_GLH_VERSION + } + + + //! Recalculates tangents for a tangent mesh buffer + template + void recalculateTangentsT(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) + { + if (!buffer || (buffer->getVertexType() != video::EVT_TANGENTS)) + return; + + const u32 vtxCnt = buffer->getVertexCount(); + const u32 idxCnt = buffer->getIndexCount(); + + T* idx = reinterpret_cast(buffer->getIndices()); + video::S3DVertexTangents* v = + (video::S3DVertexTangents*)buffer->getVertices(); + + if (smooth) + { + u32 i; + + for (i = 0; i != vtxCnt; ++i) + { + if (recalculateNormals) + v[i].Normal.set(0.f, 0.f, 0.f); + v[i].Tangent.set(0.f, 0.f, 0.f); + v[i].Binormal.set(0.f, 0.f, 0.f); + } + + //Each vertex gets the sum of the tangents and binormals from the faces around it + for (i = 0; i < idxCnt; i += 3) + { + // if this triangle is degenerate, skip it! + if (v[idx[i + 0]].Pos == v[idx[i + 1]].Pos || + v[idx[i + 0]].Pos == v[idx[i + 2]].Pos || + v[idx[i + 1]].Pos == v[idx[i + 2]].Pos + /*|| + v[idx[i+0]].TCoords == v[idx[i+1]].TCoords || + v[idx[i+0]].TCoords == v[idx[i+2]].TCoords || + v[idx[i+1]].TCoords == v[idx[i+2]].TCoords */ + ) + continue; + + //Angle-weighted normals look better, but are slightly more CPU intensive to calculate + core::vector3df weight(1.f, 1.f, 1.f); + if (angleWeighted) + weight = irr::scene::getAngleWeight(v[i + 0].Pos, v[i + 1].Pos, v[i + 2].Pos); // writing irr::scene:: necessary for borland + core::vector3df localNormal; + core::vector3df localTangent; + core::vector3df localBinormal; + + calculateTangents( + localNormal, + localTangent, + localBinormal, + v[idx[i + 0]].Pos, + v[idx[i + 1]].Pos, + v[idx[i + 2]].Pos, + v[idx[i + 0]].TCoords, + v[idx[i + 1]].TCoords, + v[idx[i + 2]].TCoords); + + if (recalculateNormals) + v[idx[i + 0]].Normal += localNormal * weight.X; + v[idx[i + 0]].Tangent += localTangent * weight.X; + v[idx[i + 0]].Binormal += localBinormal * weight.X; + + calculateTangents( + localNormal, + localTangent, + localBinormal, + v[idx[i + 1]].Pos, + v[idx[i + 2]].Pos, + v[idx[i + 0]].Pos, + v[idx[i + 1]].TCoords, + v[idx[i + 2]].TCoords, + v[idx[i + 0]].TCoords); + + if (recalculateNormals) + v[idx[i + 1]].Normal += localNormal * weight.Y; + v[idx[i + 1]].Tangent += localTangent * weight.Y; + v[idx[i + 1]].Binormal += localBinormal * weight.Y; + + calculateTangents( + localNormal, + localTangent, + localBinormal, + v[idx[i + 2]].Pos, + v[idx[i + 0]].Pos, + v[idx[i + 1]].Pos, + v[idx[i + 2]].TCoords, + v[idx[i + 0]].TCoords, + v[idx[i + 1]].TCoords); + + if (recalculateNormals) + v[idx[i + 2]].Normal += localNormal * weight.Z; + v[idx[i + 2]].Tangent += localTangent * weight.Z; + v[idx[i + 2]].Binormal += localBinormal * weight.Z; + } + + // Normalize the tangents and binormals + if (recalculateNormals) + { + for (i = 0; i != vtxCnt; ++i) + v[i].Normal.normalize(); + } + for (i = 0; i != vtxCnt; ++i) + { + v[i].Tangent.normalize(); + v[i].Binormal.normalize(); + } + } + else + { + core::vector3df localNormal; + for (u32 i = 0; i < idxCnt; i += 3) + { + calculateTangents( + localNormal, + v[idx[i + 0]].Tangent, + v[idx[i + 0]].Binormal, + v[idx[i + 0]].Pos, + v[idx[i + 1]].Pos, + v[idx[i + 2]].Pos, + v[idx[i + 0]].TCoords, + v[idx[i + 1]].TCoords, + v[idx[i + 2]].TCoords); + if (recalculateNormals) + v[idx[i + 0]].Normal = localNormal; + + calculateTangents( + localNormal, + v[idx[i + 1]].Tangent, + v[idx[i + 1]].Binormal, + v[idx[i + 1]].Pos, + v[idx[i + 2]].Pos, + v[idx[i + 0]].Pos, + v[idx[i + 1]].TCoords, + v[idx[i + 2]].TCoords, + v[idx[i + 0]].TCoords); + if (recalculateNormals) + v[idx[i + 1]].Normal = localNormal; + + calculateTangents( + localNormal, + v[idx[i + 2]].Tangent, + v[idx[i + 2]].Binormal, + v[idx[i + 2]].Pos, + v[idx[i + 0]].Pos, + v[idx[i + 1]].Pos, + v[idx[i + 2]].TCoords, + v[idx[i + 0]].TCoords, + v[idx[i + 1]].TCoords); + if (recalculateNormals) + v[idx[i + 2]].Normal = localNormal; + } + } + } +} + + +//! Recalculates tangents for a tangent mesh buffer +void CMeshManipulator::recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) const +{ + if (buffer && (buffer->getVertexType() == video::EVT_TANGENTS)) + { + if (buffer->getIndexType() == video::EIT_16BIT) + recalculateTangentsT(buffer, recalculateNormals, smooth, angleWeighted); + else + recalculateTangentsT(buffer, recalculateNormals, smooth, angleWeighted); + } +} + + +//! Recalculates tangents for all tangent mesh buffers +void CMeshManipulator::recalculateTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted) const +{ + if (!mesh) + return; + + const u32 meshBufferCount = mesh->getMeshBufferCount(); + for (u32 b = 0; b < meshBufferCount; ++b) + { + recalculateTangents(mesh->getMeshBuffer(b), recalculateNormals, smooth, angleWeighted); + } +} + + +namespace +{ + //! Creates a planar texture mapping on the meshbuffer + template + void makePlanarTextureMappingT(scene::IMeshBuffer* buffer, f32 resolution) + { + u32 idxcnt = buffer->getIndexCount(); + T* idx = reinterpret_cast(buffer->getIndices()); + + for (u32 i = 0; i < idxcnt; i += 3) + { + core::plane3df p(buffer->getPosition(idx[i + 0]), buffer->getPosition(idx[i + 1]), buffer->getPosition(idx[i + 2])); + p.Normal.X = fabsf(p.Normal.X); + p.Normal.Y = fabsf(p.Normal.Y); + p.Normal.Z = fabsf(p.Normal.Z); + // calculate planar mapping worldspace coordinates + + if (p.Normal.X > p.Normal.Y && p.Normal.X > p.Normal.Z) + { + for (u32 o = 0; o != 3; ++o) + { + buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).Y * resolution; + buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Z * resolution; + } + } + else + if (p.Normal.Y > p.Normal.X && p.Normal.Y > p.Normal.Z) + { + for (u32 o = 0; o != 3; ++o) + { + buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).X * resolution; + buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Z * resolution; + } + } + else + { + for (u32 o = 0; o != 3; ++o) + { + buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).X * resolution; + buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Y * resolution; + } + } + } + } +} + //! Recalculates all normals of the mesh buffer. /** \param buffer: Mesh buffer on which the operation is performed. */ void CMeshManipulator::recalculateNormals(IMeshBuffer *buffer, bool smooth, bool angleWeighted) const diff --git a/irr/src/CMeshManipulator.h b/irr/src/CMeshManipulator.h index 0377d6a3a..58b8e9ffc 100644 --- a/irr/src/CMeshManipulator.h +++ b/irr/src/CMeshManipulator.h @@ -29,6 +29,12 @@ public: \param smooth: Whether to use smoothed normals. */ void recalculateNormals(IMeshBuffer *buffer, bool smooth = false, bool angleWeighted = false) const override; + //! Recalculates tangents, requires a tangent mesh buffer + virtual void recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false) const _IRR_OVERRIDE_; + + //! Recalculates tangents, requires a tangent mesh + virtual void recalculateTangents(IMesh* mesh, bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false) const _IRR_OVERRIDE_; + //! Clones a static IMesh into a modifiable SMesh. SMesh *createMeshCopy(scene::IMesh *mesh) const override; diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 071b03132..5bbd54c8a 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -40,10 +40,11 @@ with this program; if not, write to the Free Software Foundation, Inc., MeshMakeData */ -MeshMakeData::MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders): +MeshMakeData::MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders, bool use_tangent_vertices): side_length(side_length), nodedef(ndef), - m_use_shaders(use_shaders) + m_use_shaders(use_shaders), + m_use_tangent_vertices(use_tangent_vertices) {} void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos) @@ -617,6 +618,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs for (auto &m : m_mesh) m = make_irr(); m_enable_shaders = data->m_use_shaders; + m_use_tangent_vertices = data->m_use_tangent_vertices; auto mesh_grid = client->getMeshGrid(); v3s16 bp = data->m_blockpos; @@ -752,27 +754,44 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs p.layer.applyMaterialOptions(material); } - scene::SMeshBuffer *buf = new scene::SMeshBuffer(); - buf->Material = material; - if (p.layer.isTransparent()) { - buf->append(&p.vertices[0], p.vertices.size(), nullptr, 0); - - MeshTriangle t; - t.buffer = buf; - m_transparent_triangles.reserve(p.indices.size() / 3); - for (u32 i = 0; i < p.indices.size(); i += 3) { - t.p1 = p.indices[i]; - t.p2 = p.indices[i + 1]; - t.p3 = p.indices[i + 2]; - t.updateAttributes(); - m_transparent_triangles.push_back(t); - } - } else { - buf->append(&p.vertices[0], p.vertices.size(), + if (m_use_tangent_vertices && !p.layer.isTransparent()) { + scene::SMeshBufferTangents* buf = new scene::SMeshBufferTangents(); + buf->Material = material; + std::vector vertices; + vertices.reserve(p.vertices.size()); + for (video::S3DVertex &v : p.vertices) + vertices.push_back(video::S3DVertexTangents(v.Pos, v.Normal, v.Color, v.TCoords)); + buf->append(&vertices[0], vertices.size(), &p.indices[0], p.indices.size()); + buf->recalculateBoundingBox(); + scene::IMeshManipulator* meshmanip = + client->getSceneManager()->getMeshManipulator(); + meshmanip->recalculateTangents(buf); + mesh->addMeshBuffer(buf); + buf->drop(); + } else { + scene::SMeshBuffer *buf = new scene::SMeshBuffer(); + buf->Material = material; + if (p.layer.isTransparent()) { + buf->append(&p.vertices[0], p.vertices.size(), nullptr, 0); + + MeshTriangle t; + t.buffer = buf; + m_transparent_triangles.reserve(p.indices.size() / 3); + for (u32 i = 0; i < p.indices.size(); i += 3) { + t.p1 = p.indices[i]; + t.p2 = p.indices[i + 1]; + t.p3 = p.indices[i + 2]; + t.updateAttributes(); + m_transparent_triangles.push_back(t); + } + } else { + buf->append(&p.vertices[0], p.vertices.size(), + &p.indices[0], p.indices.size()); + } + mesh->addMeshBuffer(buf); + buf->drop(); } - mesh->addMeshBuffer(buf); - buf->drop(); } if (mesh) { diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index c52df5ed3..56b23a4a3 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -51,8 +51,9 @@ struct MeshMakeData const NodeDefManager *nodedef; bool m_use_shaders; + bool m_use_tangent_vertices; - MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders); + MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders, bool use_tangent_vertices = false); /* Copy block data manually (to allow optimizations by the caller) @@ -251,6 +252,7 @@ private: v3f m_bounding_sphere_center; bool m_enable_shaders; + bool m_use_tangent_vertices; // Must animate() be called before rendering? bool m_has_animation; diff --git a/src/client/mesh_generator_thread.cpp b/src/client/mesh_generator_thread.cpp index 21656aa6e..a48b7fdf0 100644 --- a/src/client/mesh_generator_thread.cpp +++ b/src/client/mesh_generator_thread.cpp @@ -55,6 +55,7 @@ MeshUpdateQueue::MeshUpdateQueue(Client *client): m_client(client) { m_cache_enable_shaders = g_settings->getBool("enable_shaders"); + m_cache_use_tangent_vertices = m_cache_enable_shaders && g_settings->getBool("enable_bumpmaps"); m_cache_smooth_lighting = g_settings->getBool("smooth_lighting"); } @@ -192,7 +193,7 @@ void MeshUpdateQueue::done(v3s16 pos) void MeshUpdateQueue::fillDataFromMapBlocks(QueuedMeshUpdate *q) { auto mesh_grid = m_client->getMeshGrid(); - MeshMakeData *data = new MeshMakeData(m_client->ndef(), MAP_BLOCKSIZE * mesh_grid.cell_size, m_cache_enable_shaders); + MeshMakeData *data = new MeshMakeData(m_client->ndef(), MAP_BLOCKSIZE * mesh_grid.cell_size, m_cache_enable_shaders, m_cache_use_tangent_vertices); q->data = data; data->fillBlockDataBegin(q->p); diff --git a/src/client/mesh_generator_thread.h b/src/client/mesh_generator_thread.h index 607bc66df..5b6729364 100644 --- a/src/client/mesh_generator_thread.h +++ b/src/client/mesh_generator_thread.h @@ -86,6 +86,7 @@ private: // TODO: Add callback to update these when g_settings changes bool m_cache_enable_shaders; + bool m_cache_use_tangent_vertices; bool m_cache_smooth_lighting; void fillDataFromMapBlocks(QueuedMeshUpdate *q); diff --git a/src/lighting.h b/src/lighting.h index 85e62b9d0..38c3e70de 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -68,7 +68,7 @@ struct Vignette { * Colors in ASL CDL follow the following equation: * * out = pow(in * slope + offset, power) - * + * */ struct ColorDecisionList { core::vector3df slope{1.2, 1.0, 0.8}; From d8a6155029f2bcef658de286e2d4323f5b88cb2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:10:17 +0100 Subject: [PATCH 14/40] Fix trailing whitespace i hate this --- builtin/settingtypes.txt | 4 ++-- client/shaders/nodes_shader/opengl_fragment.glsl | 2 +- client/shaders/nodes_shader/opengl_vertex.glsl | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 9b62ee152..28654dad0 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -620,7 +620,7 @@ enable_auto_exposure (Enable Automatic Exposure) bool false exposure_compensation (Exposure compensation) float 0.0 -1.0 1.0 # Set the post processing gamma value. -# Higher values give lower contrast and vice versa. +# Higher values give lower contrast and vice versa. # Range: from 1.0 to 5.0 # Default: 1.6 # @@ -677,7 +677,7 @@ enable_tinted_fog (Tinted fog) bool false enable_bumpmaps (Bump maps) bool false # Simulate translucency when looking at foliage in the sunlight. -# It is recommended to use this with the leaves style set to fancy. +# It is recommended to use this with the leaves style set to fancy. # # Requires: shaders, enable_dynamic_shadows enable_translucent_foliage (Translucent foliage) bool false diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index e682aca88..227e89163 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -45,7 +45,7 @@ uniform float fov; varying vec3 vNormal; varying vec3 vTangent; -varying vec3 vBinormal; +varying vec3 vBinormal; 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. diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 57c2d568a..1d59fb99e 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -8,7 +8,7 @@ uniform float animationTimer; varying vec3 vNormal; varying vec3 vTangent; -varying vec3 vBinormal; +varying vec3 vBinormal; 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. From c236c1f1f1f9f550315895b28e8d3575435c05ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Mon, 11 Nov 2024 18:00:25 +0100 Subject: [PATCH 15/40] Update mapblock_mesh.cpp fix failed checks (hopefully for crying out loud) --- src/client/mapblock_mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 5bbd54c8a..0f096dc98 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -760,7 +760,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs std::vector vertices; vertices.reserve(p.vertices.size()); for (video::S3DVertex &v : p.vertices) - vertices.push_back(video::S3DVertexTangents(v.Pos, v.Normal, v.Color, v.TCoords)); + vertices.emplace_back(video::S3DVertexTangents(v.Pos, v.Normal, v.Color, v.TCoords)); buf->append(&vertices[0], vertices.size(), &p.indices[0], p.indices.size()); buf->recalculateBoundingBox(); From 812506c0b423ec87b01f7ad86618b16183a58882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Mon, 11 Nov 2024 19:16:35 +0100 Subject: [PATCH 16/40] Update mapblock_mesh.cpp Let's try this again... --- src/client/mapblock_mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 0f096dc98..156c60dac 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -760,7 +760,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs std::vector vertices; vertices.reserve(p.vertices.size()); for (video::S3DVertex &v : p.vertices) - vertices.emplace_back(video::S3DVertexTangents(v.Pos, v.Normal, v.Color, v.TCoords)); + vertices.emplace_back(v.Pos, v.Normal, v.Color, v.TCoords); buf->append(&vertices[0], vertices.size(), &p.indices[0], p.indices.size()); buf->recalculateBoundingBox(); From 795f669c97661f1729d0215030b50c25277c9bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sat, 30 Nov 2024 17:12:06 +0100 Subject: [PATCH 17/40] Revert Irrlicht changes --- irr/include/IMeshManipulator.h | 20 -- irr/src/CMeshManipulator.cpp | 329 --------------------------------- irr/src/CMeshManipulator.h | 6 - 3 files changed, 355 deletions(-) diff --git a/irr/include/IMeshManipulator.h b/irr/include/IMeshManipulator.h index 9dc67e085..54770c6f7 100644 --- a/irr/include/IMeshManipulator.h +++ b/irr/include/IMeshManipulator.h @@ -41,26 +41,6 @@ public: virtual void recalculateNormals(IMeshBuffer *buffer, bool smooth = false, bool angleWeighted = false) const = 0; - //! Recalculates tangents, requires a tangent mesh - /** \param mesh Mesh on which the operation is performed. - \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the mesh are used unchanged. - \param smooth If the normals shall be smoothed. - \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. - */ - virtual void recalculateTangents(IMesh* mesh, - bool recalculateNormals = false, bool smooth = false, - bool angleWeighted = false) const = 0; - - //! Recalculates tangents, requires a tangent mesh buffer - /** \param buffer Meshbuffer on which the operation is performed. - \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the buffer are used unchanged. - \param smooth If the normals shall be smoothed. - \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. - */ - virtual void recalculateTangents(IMeshBuffer* buffer, - bool recalculateNormals = false, bool smooth = false, - bool angleWeighted = false) const = 0; - //! Scales the actual mesh, not a scene node. /** \param mesh Mesh on which the operation is performed. \param factor Scale factor for each axis. */ diff --git a/irr/src/CMeshManipulator.cpp b/irr/src/CMeshManipulator.cpp index 556a17507..67b22a07e 100644 --- a/irr/src/CMeshManipulator.cpp +++ b/irr/src/CMeshManipulator.cpp @@ -80,335 +80,6 @@ void recalculateNormalsT(IMeshBuffer *buffer, bool smooth, bool angleWeighted) } } -namespace -{ - void calculateTangents( - core::vector3df& normal, - core::vector3df& tangent, - core::vector3df& binormal, - const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices - const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords - { - // choose one of them: - //#define USE_NVIDIA_GLH_VERSION // use version used by nvidia in glh headers -#define USE_IRR_VERSION - -#ifdef USE_IRR_VERSION - - core::vector3df v1 = vt1 - vt2; - core::vector3df v2 = vt3 - vt1; - normal = v2.crossProduct(v1); - normal.normalize(); - - // binormal - - f32 deltaX1 = tc1.X - tc2.X; - f32 deltaX2 = tc3.X - tc1.X; - binormal = (v1 * deltaX2) - (v2 * deltaX1); - binormal.normalize(); - - // tangent - - f32 deltaY1 = tc1.Y - tc2.Y; - f32 deltaY2 = tc3.Y - tc1.Y; - tangent = (v1 * deltaY2) - (v2 * deltaY1); - tangent.normalize(); - - // adjust - - core::vector3df txb = tangent.crossProduct(binormal); - if (txb.dotProduct(normal) < 0.0f) - { - tangent *= -1.0f; - binormal *= -1.0f; - } - -#endif // USE_IRR_VERSION - -#ifdef USE_NVIDIA_GLH_VERSION - - tangent.set(0, 0, 0); - binormal.set(0, 0, 0); - - core::vector3df v1(vt2.X - vt1.X, tc2.X - tc1.X, tc2.Y - tc1.Y); - core::vector3df v2(vt3.X - vt1.X, tc3.X - tc1.X, tc3.Y - tc1.Y); - - core::vector3df txb = v1.crossProduct(v2); - if (!core::iszero(txb.X)) - { - tangent.X = -txb.Y / txb.X; - binormal.X = -txb.Z / txb.X; - } - - v1.X = vt2.Y - vt1.Y; - v2.X = vt3.Y - vt1.Y; - txb = v1.crossProduct(v2); - - if (!core::iszero(txb.X)) - { - tangent.Y = -txb.Y / txb.X; - binormal.Y = -txb.Z / txb.X; - } - - v1.X = vt2.Z - vt1.Z; - v2.X = vt3.Z - vt1.Z; - txb = v1.crossProduct(v2); - - if (!core::iszero(txb.X)) - { - tangent.Z = -txb.Y / txb.X; - binormal.Z = -txb.Z / txb.X; - } - - tangent.normalize(); - binormal.normalize(); - - normal = tangent.crossProduct(binormal); - normal.normalize(); - - binormal = tangent.crossProduct(normal); - binormal.normalize(); - - core::plane3d pl(vt1, vt2, vt3); - - if (normal.dotProduct(pl.Normal) < 0.0f) - normal *= -1.0f; - -#endif // USE_NVIDIA_GLH_VERSION - } - - - //! Recalculates tangents for a tangent mesh buffer - template - void recalculateTangentsT(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) - { - if (!buffer || (buffer->getVertexType() != video::EVT_TANGENTS)) - return; - - const u32 vtxCnt = buffer->getVertexCount(); - const u32 idxCnt = buffer->getIndexCount(); - - T* idx = reinterpret_cast(buffer->getIndices()); - video::S3DVertexTangents* v = - (video::S3DVertexTangents*)buffer->getVertices(); - - if (smooth) - { - u32 i; - - for (i = 0; i != vtxCnt; ++i) - { - if (recalculateNormals) - v[i].Normal.set(0.f, 0.f, 0.f); - v[i].Tangent.set(0.f, 0.f, 0.f); - v[i].Binormal.set(0.f, 0.f, 0.f); - } - - //Each vertex gets the sum of the tangents and binormals from the faces around it - for (i = 0; i < idxCnt; i += 3) - { - // if this triangle is degenerate, skip it! - if (v[idx[i + 0]].Pos == v[idx[i + 1]].Pos || - v[idx[i + 0]].Pos == v[idx[i + 2]].Pos || - v[idx[i + 1]].Pos == v[idx[i + 2]].Pos - /*|| - v[idx[i+0]].TCoords == v[idx[i+1]].TCoords || - v[idx[i+0]].TCoords == v[idx[i+2]].TCoords || - v[idx[i+1]].TCoords == v[idx[i+2]].TCoords */ - ) - continue; - - //Angle-weighted normals look better, but are slightly more CPU intensive to calculate - core::vector3df weight(1.f, 1.f, 1.f); - if (angleWeighted) - weight = irr::scene::getAngleWeight(v[i + 0].Pos, v[i + 1].Pos, v[i + 2].Pos); // writing irr::scene:: necessary for borland - core::vector3df localNormal; - core::vector3df localTangent; - core::vector3df localBinormal; - - calculateTangents( - localNormal, - localTangent, - localBinormal, - v[idx[i + 0]].Pos, - v[idx[i + 1]].Pos, - v[idx[i + 2]].Pos, - v[idx[i + 0]].TCoords, - v[idx[i + 1]].TCoords, - v[idx[i + 2]].TCoords); - - if (recalculateNormals) - v[idx[i + 0]].Normal += localNormal * weight.X; - v[idx[i + 0]].Tangent += localTangent * weight.X; - v[idx[i + 0]].Binormal += localBinormal * weight.X; - - calculateTangents( - localNormal, - localTangent, - localBinormal, - v[idx[i + 1]].Pos, - v[idx[i + 2]].Pos, - v[idx[i + 0]].Pos, - v[idx[i + 1]].TCoords, - v[idx[i + 2]].TCoords, - v[idx[i + 0]].TCoords); - - if (recalculateNormals) - v[idx[i + 1]].Normal += localNormal * weight.Y; - v[idx[i + 1]].Tangent += localTangent * weight.Y; - v[idx[i + 1]].Binormal += localBinormal * weight.Y; - - calculateTangents( - localNormal, - localTangent, - localBinormal, - v[idx[i + 2]].Pos, - v[idx[i + 0]].Pos, - v[idx[i + 1]].Pos, - v[idx[i + 2]].TCoords, - v[idx[i + 0]].TCoords, - v[idx[i + 1]].TCoords); - - if (recalculateNormals) - v[idx[i + 2]].Normal += localNormal * weight.Z; - v[idx[i + 2]].Tangent += localTangent * weight.Z; - v[idx[i + 2]].Binormal += localBinormal * weight.Z; - } - - // Normalize the tangents and binormals - if (recalculateNormals) - { - for (i = 0; i != vtxCnt; ++i) - v[i].Normal.normalize(); - } - for (i = 0; i != vtxCnt; ++i) - { - v[i].Tangent.normalize(); - v[i].Binormal.normalize(); - } - } - else - { - core::vector3df localNormal; - for (u32 i = 0; i < idxCnt; i += 3) - { - calculateTangents( - localNormal, - v[idx[i + 0]].Tangent, - v[idx[i + 0]].Binormal, - v[idx[i + 0]].Pos, - v[idx[i + 1]].Pos, - v[idx[i + 2]].Pos, - v[idx[i + 0]].TCoords, - v[idx[i + 1]].TCoords, - v[idx[i + 2]].TCoords); - if (recalculateNormals) - v[idx[i + 0]].Normal = localNormal; - - calculateTangents( - localNormal, - v[idx[i + 1]].Tangent, - v[idx[i + 1]].Binormal, - v[idx[i + 1]].Pos, - v[idx[i + 2]].Pos, - v[idx[i + 0]].Pos, - v[idx[i + 1]].TCoords, - v[idx[i + 2]].TCoords, - v[idx[i + 0]].TCoords); - if (recalculateNormals) - v[idx[i + 1]].Normal = localNormal; - - calculateTangents( - localNormal, - v[idx[i + 2]].Tangent, - v[idx[i + 2]].Binormal, - v[idx[i + 2]].Pos, - v[idx[i + 0]].Pos, - v[idx[i + 1]].Pos, - v[idx[i + 2]].TCoords, - v[idx[i + 0]].TCoords, - v[idx[i + 1]].TCoords); - if (recalculateNormals) - v[idx[i + 2]].Normal = localNormal; - } - } - } -} - - -//! Recalculates tangents for a tangent mesh buffer -void CMeshManipulator::recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) const -{ - if (buffer && (buffer->getVertexType() == video::EVT_TANGENTS)) - { - if (buffer->getIndexType() == video::EIT_16BIT) - recalculateTangentsT(buffer, recalculateNormals, smooth, angleWeighted); - else - recalculateTangentsT(buffer, recalculateNormals, smooth, angleWeighted); - } -} - - -//! Recalculates tangents for all tangent mesh buffers -void CMeshManipulator::recalculateTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted) const -{ - if (!mesh) - return; - - const u32 meshBufferCount = mesh->getMeshBufferCount(); - for (u32 b = 0; b < meshBufferCount; ++b) - { - recalculateTangents(mesh->getMeshBuffer(b), recalculateNormals, smooth, angleWeighted); - } -} - - -namespace -{ - //! Creates a planar texture mapping on the meshbuffer - template - void makePlanarTextureMappingT(scene::IMeshBuffer* buffer, f32 resolution) - { - u32 idxcnt = buffer->getIndexCount(); - T* idx = reinterpret_cast(buffer->getIndices()); - - for (u32 i = 0; i < idxcnt; i += 3) - { - core::plane3df p(buffer->getPosition(idx[i + 0]), buffer->getPosition(idx[i + 1]), buffer->getPosition(idx[i + 2])); - p.Normal.X = fabsf(p.Normal.X); - p.Normal.Y = fabsf(p.Normal.Y); - p.Normal.Z = fabsf(p.Normal.Z); - // calculate planar mapping worldspace coordinates - - if (p.Normal.X > p.Normal.Y && p.Normal.X > p.Normal.Z) - { - for (u32 o = 0; o != 3; ++o) - { - buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).Y * resolution; - buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Z * resolution; - } - } - else - if (p.Normal.Y > p.Normal.X && p.Normal.Y > p.Normal.Z) - { - for (u32 o = 0; o != 3; ++o) - { - buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).X * resolution; - buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Z * resolution; - } - } - else - { - for (u32 o = 0; o != 3; ++o) - { - buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).X * resolution; - buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Y * resolution; - } - } - } - } -} - //! Recalculates all normals of the mesh buffer. /** \param buffer: Mesh buffer on which the operation is performed. */ void CMeshManipulator::recalculateNormals(IMeshBuffer *buffer, bool smooth, bool angleWeighted) const diff --git a/irr/src/CMeshManipulator.h b/irr/src/CMeshManipulator.h index 58b8e9ffc..0377d6a3a 100644 --- a/irr/src/CMeshManipulator.h +++ b/irr/src/CMeshManipulator.h @@ -29,12 +29,6 @@ public: \param smooth: Whether to use smoothed normals. */ void recalculateNormals(IMeshBuffer *buffer, bool smooth = false, bool angleWeighted = false) const override; - //! Recalculates tangents, requires a tangent mesh buffer - virtual void recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false) const _IRR_OVERRIDE_; - - //! Recalculates tangents, requires a tangent mesh - virtual void recalculateTangents(IMesh* mesh, bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false) const _IRR_OVERRIDE_; - //! Clones a static IMesh into a modifiable SMesh. SMesh *createMeshCopy(scene::IMesh *mesh) const override; From 364ca57819ebfd066e7c1f836887a4e3940e7d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sat, 30 Nov 2024 18:18:06 +0100 Subject: [PATCH 18/40] Remove bumpmapping and make requested changes --- builtin/settingtypes.txt | 10 ---- .../shaders/nodes_shader/opengl_fragment.glsl | 40 +++---------- .../shaders/second_stage/opengl_fragment.glsl | 2 - doc/lua_api.md | 6 +- src/client/clouds.cpp | 40 ++++++------- src/client/mapblock_mesh.cpp | 60 +++++++------------ src/client/mapblock_mesh.h | 6 +- src/client/mesh_generator_thread.cpp | 5 +- src/client/mesh_generator_thread.h | 1 - src/client/shader.cpp | 6 -- src/defaultsettings.cpp | 2 - src/lighting.h | 6 +- src/log.h | 2 +- 13 files changed, 57 insertions(+), 129 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index d7f5cac52..294e64424 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -662,11 +662,6 @@ enable_volumetric_depth_attenuation (Volumetric Depth Attenuation) bool false # Makes the color of light fog more saturated. enable_tinted_fog (Tinted fog) bool false -# Apply bump maps to nodes based on their textures. It is recommended to use a tilted sun orbit to go with this (Sky Body Orbit Tilt). -# -# Requires: enable_dynamic_shadows -enable_bumpmaps (Bump maps) bool false - # Simulate translucency when looking at foliage in the sunlight. # It is recommended to use this with the leaves style set to fancy. # @@ -678,11 +673,6 @@ enable_translucent_foliage (Translucent foliage) bool false # Requires: enable_dynamic_shadows enable_node_specular (Node specular) bool false -# When enabled, liquid reflections are simulated. -# -# Requires: enable_waving_water, enable_dynamic_shadows -enable_water_reflections (Liquid reflections) bool false - [*Audio] # Volume of all sounds. diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 227e89163..f8f5f4d57 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -63,7 +63,7 @@ varying highp vec3 eyeVec; varying float nightRatio; #ifdef ENABLE_DYNAMIC_SHADOWS -#if ((defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS)) || defined(ENABLE_BUMPMAPS)) +#if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS)) vec4 perm(vec4 x) { return mod(((x * 34.0) + 1.0) * x, 289.0); @@ -420,23 +420,6 @@ float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance) #endif #endif - -#if (defined(ENABLE_BUMPMAPS) && !defined(MATERIAL_LIQUID)) -//This is mostly a placeholder and probably should use proper textures eventually... -vec3 getBumpMap(vec2 uv) { - vec2 dr = vec2(0.25) * texelSize0; - // Sample the texture to then compute the gradient - float fx0y0 = texture2D(baseTexture, uv).r; - float fx1y0 = texture2D(baseTexture, uv + vec2(dr.x, 0.0)).r; - float fx0y1 = texture2D(baseTexture, uv + vec2(0.0, dr.y)).r; - // We get the gradient using partial derivatives - vec2 gradient = 0.1 * vec2((fx1y0 - fx0y0) / dr.x, (fx0y1 - fx0y0) / dr.y) + 0.05 * gnoise(vec3(2.0 * uv / texelSize0, 0.0)).xy; - vec3 tangent_space = normalize(vec3(gradient, 1.0)); - // Convert tangent space information to real space - return -vTangent * tangent_space.x + vBinormal * tangent_space.y + vNormal * tangent_space.z; -} -#endif - #endif void main(void) @@ -466,17 +449,7 @@ void main(void) vec3 viewVec = normalize(worldPosition + cameraOffset - cameraPosition); -#if ((defined(ENABLE_DYNAMIC_SHADOWS) && defined(ENABLE_BUMPMAPS)) && !defined(MATERIAL_LIQUID)) - vec3 bump_normal = getBumpMap(uv); - // When applied to all blocks, these bump maps produce irritating Moiré effects. - // So we hide the bump maps when close up. - float moire_factor = abs(dot(vNormal, viewVec)); - moire_factor = mtsmoothstep(0.4 * moire_factor, 0.2 * moire_factor, length(eyeVec) * fov / windowSize.x); - fNormal = normalize(mix(fNormal, bump_normal, moire_factor)); - float adj_cosLight = max(1e-5, dot(fNormal, -v_LightDirection)); -#else float adj_cosLight = cosLight; -#endif if (f_shadow_strength > 0.0) { float shadow_int = 0.0; @@ -556,7 +529,7 @@ void main(void) wavePos.x /= WATER_WAVE_LENGTH * 3.0; wavePos.z /= WATER_WAVE_LENGTH * 2.0; - // This is an analogous method to the bumpmap, except we get the gradient information directly from gnoise. + // We get the gradient information of the waves using gnoise. vec2 gradient = wave_noise(wavePos, off); fNormal = normalize(normalize(fNormal) + vec3(gradient.x, 0., gradient.y) * WATER_WAVE_HEIGHT * abs(fNormal.y) * 0.25); reflect_ray = -normalize(v_LightDirection - fNormal * dot(v_LightDirection, fNormal) * 2.0); @@ -572,12 +545,15 @@ void main(void) // Sky reflection col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.5 * brightness_factor; + vec3 water_reflect_color = + 6.0 * sunTint * dayLight * fresnel_factor * f_adj_shadow_strength * max(1.0 - shadow_uncorrected, 0.0) * + mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)); + // We clip the reflection color if it gets too bright - vec3 water_reflect_color = 6.0 * sunTint * dayLight * fresnel_factor * mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)) * max(1.0 - shadow_uncorrected, 0.0); - water_reflect_color /= max(0.4 * length(water_reflect_color), 1.0); + water_reflect_color *= min(2.0 / max(water_reflect_color.r, max(water_reflect_color.g, water_reflect_color.b)), 1.0); // Sun reflection - col.rgb += water_reflect_color * f_adj_shadow_strength * brightness_factor; + col.rgb += water_reflect_color * brightness_factor; #endif #if (defined(ENABLE_NODE_SPECULAR) && !defined(MATERIAL_WAVING_LIQUID)) diff --git a/client/shaders/second_stage/opengl_fragment.glsl b/client/shaders/second_stage/opengl_fragment.glsl index 3492917d1..ecfe94cf6 100644 --- a/client/shaders/second_stage/opengl_fragment.glsl +++ b/client/shaders/second_stage/opengl_fragment.glsl @@ -150,9 +150,7 @@ void main(void) #endif { -#ifdef ENABLE_VIGNETTE color.rgb *= (vignette_bright - vignette_dark) * (1.0 - pow(length(uv - vec2(0.5)) * 1.4, vignette_power)) + vignette_dark; -#endif #if ENABLE_TONE_MAPPING color = applyToneMapping(color); diff --git a/doc/lua_api.md b/doc/lua_api.md index 7bcf2ab31..96eb38fa2 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8828,9 +8828,9 @@ child will follow movement and rotation of that bone. * Setting all components to zero effectively disables tinted sunlight. * `vignette`: is a table that controls the vignette post-processing effect. * This has no effect on clients who have the "Vignette" effects disabled. - * `dark`: brightness of the vignette's darkest part (default: `0.3`) - * `bright`: brightness of the vignette's brightest part (default: `1.1`) - * `power`: the higher this is set, the more the vignette "retreats" to the edges of the screen (default: `1.1`) + * `dark`: brightness of the vignette's darkest part (default: `1.0`) + * `bright`: brightness of the vignette's brightest part (default: `1.0`) + * `power`: the higher this is set, the more the vignette "retreats" to the edges of the screen (default: `1.0`) * `cdl`: is a table that controls the ASL CDL color grading effect. * This has no effect on clients who have the "Color grading" effect disabled. * The output color follows the equation: `out = pow(in*slope+offset, power)` diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 04d787c68..420a51674 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -215,10 +215,10 @@ void Clouds::updateMesh() for (video::S3DVertex& vertex : v) { vertex.Normal.set(0, 1, 0); } - v[0].Pos.set(-rx, ry, -rz); + v[0].Pos.set(-rx, ry,-rz); v[1].Pos.set(-rx, ry, rz); - v[2].Pos.set(rx, ry, rz); - v[3].Pos.set(rx, ry, -rz); + v[2].Pos.set( rx, ry, rz); + v[3].Pos.set( rx, ry,-rz); break; case 1: // back if (INAREA(xi, zi - 1, m_cloud_radius_i)) { @@ -239,10 +239,10 @@ void Clouds::updateMesh() vertex.Normal.set(0, 0, -1); } } - v[0].Pos.set(-rx, ry, -rz); - v[1].Pos.set(rx, ry, -rz); - v[2].Pos.set(rx, 0, -rz); - v[3].Pos.set(-rx, 0, -rz); + v[0].Pos.set(-rx, ry,-rz); + v[1].Pos.set( rx, ry,-rz); + v[2].Pos.set( rx, 0,-rz); + v[3].Pos.set(-rx, 0,-rz); break; case 2: //right if (INAREA(xi + 1, zi, m_cloud_radius_i)) { @@ -263,10 +263,10 @@ void Clouds::updateMesh() vertex.Normal.set(1, 0, 0); } } - v[0].Pos.set(rx, ry, -rz); + v[0].Pos.set(rx, ry,-rz); v[1].Pos.set(rx, ry, rz); - v[2].Pos.set(rx, 0, rz); - v[3].Pos.set(rx, 0, -rz); + v[2].Pos.set(rx, 0, rz); + v[3].Pos.set(rx, 0,-rz); break; case 3: // front if (INAREA(xi, zi + 1, m_cloud_radius_i)) { @@ -287,10 +287,10 @@ void Clouds::updateMesh() vertex.Normal.set(0, 0, -1); } } - v[0].Pos.set(rx, ry, rz); + v[0].Pos.set( rx, ry, rz); v[1].Pos.set(-rx, ry, rz); - v[2].Pos.set(-rx, 0, rz); - v[3].Pos.set(rx, 0, rz); + v[2].Pos.set(-rx, 0, rz); + v[3].Pos.set( rx, 0, rz); break; case 4: // left if (INAREA(xi - 1, zi, m_cloud_radius_i)) { @@ -312,19 +312,19 @@ void Clouds::updateMesh() } } v[0].Pos.set(-rx, ry, rz); - v[1].Pos.set(-rx, ry, -rz); - v[2].Pos.set(-rx, 0, -rz); - v[3].Pos.set(-rx, 0, rz); + v[1].Pos.set(-rx, ry,-rz); + v[2].Pos.set(-rx, 0,-rz); + v[3].Pos.set(-rx, 0, rz); break; case 5: // bottom for (video::S3DVertex& vertex : v) { vertex.Color = c_bottom; vertex.Normal.set(0, -1, 0); } - v[0].Pos.set(rx, 0, rz); - v[1].Pos.set(-rx, 0, rz); - v[2].Pos.set(-rx, 0, -rz); - v[3].Pos.set(rx, 0, -rz); + v[0].Pos.set( rx, 0, rz); + v[1].Pos.set(-rx, 0, rz); + v[2].Pos.set(-rx, 0,-rz); + v[3].Pos.set( rx, 0,-rz); break; } diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 409a64204..c212bd148 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -25,10 +25,9 @@ MeshMakeData */ -MeshMakeData::MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_tangent_vertices): +MeshMakeData::MeshMakeData(const NodeDefManager *ndef, u16 side_length): side_length(side_length), - nodedef(ndef), - m_use_tangent_vertices(use_tangent_vertices) + nodedef(ndef) {} void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos) @@ -602,8 +601,6 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs for (auto &m : m_mesh) m = make_irr(); - m_use_tangent_vertices = data->m_use_tangent_vertices; - auto mesh_grid = client->getMeshGrid(); v3s16 bp = data->m_blockpos; // Only generate minimap mapblocks at even coordinates. @@ -712,44 +709,27 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs p.layer.applyMaterialOptionsWithShaders(material); } - if (m_use_tangent_vertices && !p.layer.isTransparent()) { - scene::SMeshBufferTangents* buf = new scene::SMeshBufferTangents(); - buf->Material = material; - std::vector vertices; - vertices.reserve(p.vertices.size()); - for (video::S3DVertex &v : p.vertices) - vertices.emplace_back(v.Pos, v.Normal, v.Color, v.TCoords); - buf->append(&vertices[0], vertices.size(), - &p.indices[0], p.indices.size()); - buf->recalculateBoundingBox(); - scene::IMeshManipulator* meshmanip = - client->getSceneManager()->getMeshManipulator(); - meshmanip->recalculateTangents(buf); - mesh->addMeshBuffer(buf); - buf->drop(); - } else { - scene::SMeshBuffer *buf = new scene::SMeshBuffer(); - buf->Material = material; - if (p.layer.isTransparent()) { - buf->append(&p.vertices[0], p.vertices.size(), nullptr, 0); + scene::SMeshBuffer *buf = new scene::SMeshBuffer(); + buf->Material = material; + if (p.layer.isTransparent()) { + buf->append(&p.vertices[0], p.vertices.size(), nullptr, 0); - MeshTriangle t; - t.buffer = buf; - m_transparent_triangles.reserve(p.indices.size() / 3); - for (u32 i = 0; i < p.indices.size(); i += 3) { - t.p1 = p.indices[i]; - t.p2 = p.indices[i + 1]; - t.p3 = p.indices[i + 2]; - t.updateAttributes(); - m_transparent_triangles.push_back(t); - } - } else { - buf->append(&p.vertices[0], p.vertices.size(), - &p.indices[0], p.indices.size()); + MeshTriangle t; + t.buffer = buf; + m_transparent_triangles.reserve(p.indices.size() / 3); + for (u32 i = 0; i < p.indices.size(); i += 3) { + t.p1 = p.indices[i]; + t.p2 = p.indices[i + 1]; + t.p3 = p.indices[i + 2]; + t.updateAttributes(); + m_transparent_triangles.push_back(t); } - mesh->addMeshBuffer(buf); - buf->drop(); + } else { + buf->append(&p.vertices[0], p.vertices.size(), + &p.indices[0], p.indices.size()); } + mesh->addMeshBuffer(buf); + buf->drop(); } if (mesh) { diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index e9928ac37..5a8daf50c 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -36,9 +36,7 @@ struct MeshMakeData const NodeDefManager *nodedef; - bool m_use_tangent_vertices; - - MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_tangent_vertices = false); + MeshMakeData(const NodeDefManager *ndef, u16 side_length); /* Copy block data manually (to allow optimizations by the caller) @@ -236,8 +234,6 @@ private: f32 m_bounding_radius; v3f m_bounding_sphere_center; - bool m_use_tangent_vertices; - // Must animate() be called before rendering? bool m_has_animation; int m_animation_force_timer; diff --git a/src/client/mesh_generator_thread.cpp b/src/client/mesh_generator_thread.cpp index 45264dae7..790477bf3 100644 --- a/src/client/mesh_generator_thread.cpp +++ b/src/client/mesh_generator_thread.cpp @@ -39,8 +39,6 @@ QueuedMeshUpdate::~QueuedMeshUpdate() MeshUpdateQueue::MeshUpdateQueue(Client *client): m_client(client) { - m_cache_use_tangent_vertices = g_settings->getBool("enable_bumpmaps"); - m_cache_smooth_lighting = g_settings->getBool("smooth_lighting"); } @@ -179,8 +177,7 @@ void MeshUpdateQueue::fillDataFromMapBlocks(QueuedMeshUpdate *q) { auto mesh_grid = m_client->getMeshGrid(); - MeshMakeData *data = new MeshMakeData(m_client->ndef(), MAP_BLOCKSIZE * mesh_grid.cell_size, m_cache_use_tangent_vertices); - + MeshMakeData *data = new MeshMakeData(m_client->ndef(), MAP_BLOCKSIZE * mesh_grid.cell_size); q->data = data; data->fillBlockDataBegin(q->p); diff --git a/src/client/mesh_generator_thread.h b/src/client/mesh_generator_thread.h index 564e46198..fb9b5ae9e 100644 --- a/src/client/mesh_generator_thread.h +++ b/src/client/mesh_generator_thread.h @@ -70,7 +70,6 @@ private: std::mutex m_mutex; // TODO: Add callback to update these when g_settings changes - bool m_cache_use_tangent_vertices; bool m_cache_smooth_lighting; void fillDataFromMapBlocks(QueuedMeshUpdate *q); diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 534ab864f..139d82a2f 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -680,9 +680,6 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, if (g_settings->getBool("shadow_poisson_filter")) shaders_header << "#define POISSON_FILTER 1\n"; - if (g_settings->getBool("enable_bumpmaps")) - shaders_header << "#define ENABLE_BUMPMAPS 1\n"; - if (g_settings->getBool("enable_water_reflections")) shaders_header << "#define ENABLE_WATER_REFLECTIONS 1\n"; @@ -716,9 +713,6 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, if (g_settings->getBool("enable_color_grading")) shaders_header << "#define ENABLE_COLOR_GRADING 1\n"; - if (g_settings->getBool("enable_vignette")) - shaders_header << "#define ENABLE_VIGNETTE 1\n"; - if (g_settings->get("antialiasing") == "ssaa") { shaders_header << "#define ENABLE_SSAA 1\n"; u16 ssaa_scale = MYMAX(2, g_settings->getU16("fsaa")); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 2c9ef4fad..ff16b9b69 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -326,7 +326,6 @@ void set_default_settings() settings->setDefault("exposure_compensation", "0.0"); settings->setDefault("enable_auto_exposure", "false"); settings->setDefault("enable_color_grading", "false"); - settings->setDefault("enable_vignette", "false"); settings->setDefault("secondstage_gamma", "1.6"); settings->setDefault("debanding", "true"); settings->setDefault("antialiasing", "none"); @@ -334,7 +333,6 @@ void set_default_settings() settings->setDefault("enable_bloom_debug", "false"); settings->setDefault("enable_volumetric_lighting", "false"); settings->setDefault("enable_volumetric_depth_attenuation", "false"); - settings->setDefault("enable_bumpmaps", "false"); settings->setDefault("enable_water_reflections", "false"); settings->setDefault("enable_translucent_foliage", "false"); settings->setDefault("enable_node_specular", "false"); diff --git a/src/lighting.h b/src/lighting.h index 1452bc78b..f04c2fde3 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -40,11 +40,11 @@ struct AutoExposure */ struct Vignette { /// @brief The darkest part of the vignette will be darkened/brightened by this factor. - float dark = 0.3f; + float dark = 1.0f; /// @brief The brightest part of the vignette will be darkened/brightened by this factor. - float bright = 1.1f; + float bright = 1.0f; /// @brief Describes the blending between dark and bright. Higher values mean darkening is more intense at the screen edges. - float power = 1.1f; + float power = 1.0f; }; /** diff --git a/src/log.h b/src/log.h index 0e34b2c83..1073d7935 100644 --- a/src/log.h +++ b/src/log.h @@ -62,7 +62,7 @@ private: // These calls explicitly use the templated version of operator<<, // so that they won't use the overloads created by ADD_NULL_CHECK. if (arg == nullptr) - return this->operator<< ("(null)"); + return this->operator<< ((const char*)"(null)"); else return this->operator<< (std::forward(arg)); } From f0407080ac245f79d645a6c0050fb7f135232e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 1 Dec 2024 12:11:29 +0100 Subject: [PATCH 19/40] Fix vignette and whitespace --- builtin/settingtypes.txt | 5 ----- client/shaders/nodes_shader/opengl_fragment.glsl | 2 +- client/shaders/second_stage/opengl_fragment.glsl | 2 +- src/client/game.cpp | 10 ++++------ 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 294e64424..64e1cb197 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -625,11 +625,6 @@ secondstage_gamma (Gamma) float 1.6 1.0 5.0 # Requires: enable_post_processing enable_color_grading (Color grading) bool false -# Apply vignette effect to darken the edges of the screen. -# -# Requires: enable_post_processing -enable_vignette (Vignette) bool false - # Apply dithering to reduce color banding artifacts. # Dithering significantly increases the size of losslessly-compressed # screenshots and it works incorrectly if the display or operating system diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index f8f5f4d57..a8e5e1768 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -546,7 +546,7 @@ void main(void) col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.5 * brightness_factor; vec3 water_reflect_color = - 6.0 * sunTint * dayLight * fresnel_factor * f_adj_shadow_strength * max(1.0 - shadow_uncorrected, 0.0) * + 6.0 * sunTint * dayLight * fresnel_factor * f_adj_shadow_strength * max(1.0 - shadow_uncorrected, 0.0) * mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)); // We clip the reflection color if it gets too bright diff --git a/client/shaders/second_stage/opengl_fragment.glsl b/client/shaders/second_stage/opengl_fragment.glsl index ecfe94cf6..89cea2a2e 100644 --- a/client/shaders/second_stage/opengl_fragment.glsl +++ b/client/shaders/second_stage/opengl_fragment.glsl @@ -150,7 +150,7 @@ void main(void) #endif { - color.rgb *= (vignette_bright - vignette_dark) * (1.0 - pow(length(uv - vec2(0.5)) * 1.4, vignette_power)) + vignette_dark; + color.rgb *= (vignette_bright - vignette_dark) * (1.0 - pow(length(uv - vec2(0.5)) * 1.4, vignette_power)) + vignette_dark; #if ENABLE_TONE_MAPPING color = applyToneMapping(color); diff --git a/src/client/game.cpp b/src/client/game.cpp index 8d5460f7c..b27db749b 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -548,12 +548,10 @@ public: float gamma = m_gamma; m_gamma_pixel.set(&gamma, services); - if (g_settings->getBool("enable_vignette")) { - const Vignette &vignette_params = lighting.vignette; - m_vignette_dark_pixel.set(&vignette_params.dark, services); - m_vignette_bright_pixel.set(&vignette_params.bright, services); - m_vignette_power_pixel.set(&vignette_params.power, services); - } + const Vignette &vignette_params = lighting.vignette; + m_vignette_dark_pixel.set(&vignette_params.dark, services); + m_vignette_bright_pixel.set(&vignette_params.bright, services); + m_vignette_power_pixel.set(&vignette_params.power, services); if (g_settings->getBool("enable_color_grading")) { const ColorDecisionList& cdl_params = lighting.cdl; From 1fa9731172634df83cedfeead767b4a2b880c761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 1 Dec 2024 12:15:05 +0100 Subject: [PATCH 20/40] Fix whitespace pls :( --- client/shaders/nodes_shader/opengl_fragment.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index a8e5e1768..75585d9c4 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -545,7 +545,7 @@ void main(void) // Sky reflection col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.5 * brightness_factor; - vec3 water_reflect_color = + vec3 water_reflect_color = 6.0 * sunTint * dayLight * fresnel_factor * f_adj_shadow_strength * max(1.0 - shadow_uncorrected, 0.0) * mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)); From 45289b6919f37215a323c95ea57f057e5d2fec72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:00:59 +0100 Subject: [PATCH 21/40] Remove redundant stuff and other small fixes --- builtin/settingtypes.txt | 5 +--- .../shaders/nodes_shader/opengl_fragment.glsl | 23 ++++--------------- .../object_shader/opengl_fragment.glsl | 10 ++++++++ doc/lua_api.md | 2 +- src/client/game.cpp | 22 ------------------ src/client/shader.cpp | 9 ++++---- 6 files changed, 21 insertions(+), 50 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 64e1cb197..41cb2cf8c 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -485,22 +485,19 @@ enable_waving_water (Waving liquids) bool false # 0.0 = Wave doesn't move at all. # Default is 1.0 (1/2 node). # -# Requires: enable_waving_water water_wave_height (Waving liquids wave height) float 1.0 0.0 4.0 # Length of liquid waves. # -# Requires: enable_waving_water water_wave_length (Waving liquids wavelength) float 20.0 0.1 # How fast liquid waves will move. Higher = faster. # If negative, liquid waves will move backwards. # -# Requires: enable_waving_water water_wave_speed (Waving liquids wave speed) float 5.0 # When enabled, crude liquid reflections are simulated. -# When waving liquids are enabled, the wave parameters will affect these reflections. +# Wave height, length and speed will affect these reflections. # # Requires: enable_dynamic_shadows enable_water_reflections (Liquid reflections) bool false diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 75585d9c4..b0cc7c266 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -40,12 +40,7 @@ uniform float animationTimer; varying float perspective_factor; #endif -uniform vec2 windowSize; -uniform float fov; - varying vec3 vNormal; -varying vec3 vTangent; -varying vec3 vBinormal; 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. @@ -449,8 +444,6 @@ void main(void) vec3 viewVec = normalize(worldPosition + cameraOffset - cameraPosition); - float adj_cosLight = cosLight; - if (f_shadow_strength > 0.0) { float shadow_int = 0.0; vec3 shadow_color = vec3(0.0, 0.0, 0.0); @@ -465,14 +458,14 @@ void main(void) #ifdef COLORED_SHADOWS vec4 visibility; - if (adj_cosLight > 0.0 || f_normal_length < 1e-3) + 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 (adj_cosLight > 0.0 || f_normal_length < 1e-3) + if (cosLight > 0.0 || f_normal_length < 1e-3) shadow_int = getShadow(ShadowMapSampler, posLightSpace.xy, posLightSpace.z); else shadow_int = 1.0; @@ -493,9 +486,9 @@ void main(void) // Cosine of the cut-off angle. const float self_shadow_cutoff_cosine = 0.035; - if (f_normal_length != 0 && adj_cosLight < self_shadow_cutoff_cosine) { - shadow_int = max(shadow_int, 1 - clamp(adj_cosLight, 0.0, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); - shadow_color = mix(vec3(0.0), shadow_color, min(adj_cosLight, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); + 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); #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES || MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS) // Prevents foliage from becoming insanely bright outside the shadow map. @@ -518,12 +511,6 @@ void main(void) // Water reflections #if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS)) -#if !ENABLE_WAVING_WATER -#define WATER_WAVE_HEIGHT 0.5 -#define WATER_WAVE_SPEED 5.0 -#define WATER_WAVE_LENGTH 10.0 -#endif - vec3 wavePos = worldPosition * vec3(2.0, 0.0, 2.0); float off = animationTimer * WATER_WAVE_SPEED * 10.0; wavePos.x /= WATER_WAVE_LENGTH * 3.0; diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index b41e234e1..504a10964 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -450,7 +450,17 @@ void main(void) float clarity = clamp(fogShadingParameter - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); +#ifdef ENABLE_TINTED_FOG + float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b); + // Prevent zero division. + if (fogColorMax < 0.0000001) fogColorMax = 1.0; + // For high clarity (light fog) we tint the fog color. + // For this to not make the fog color artificially dark we need to normalize using the + // fog color's brightest value. We then blend our base color with this to make the fog. + col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity); +#else col = mix(fogColor, col, clarity); +#endif col = vec4(col.rgb, base.a); diff --git a/doc/lua_api.md b/doc/lua_api.md index 96eb38fa2..f99e2eea8 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8827,7 +8827,7 @@ child will follow movement and rotation of that bone. * This may be used to create effects like differently colored sunsets on alien planets. * Setting all components to zero effectively disables tinted sunlight. * `vignette`: is a table that controls the vignette post-processing effect. - * This has no effect on clients who have the "Vignette" effects disabled. + * This has no effect on clients who have post processing disabled. * `dark`: brightness of the vignette's darkest part (default: `1.0`) * `bright`: brightness of the vignette's brightest part (default: `1.0`) * `power`: the higher this is set, the more the vignette "retreats" to the edges of the screen (default: `1.0`) diff --git a/src/client/game.cpp b/src/client/game.cpp index b27db749b..a7555b55d 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -373,10 +373,6 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_camera_offset_pixel{ "cameraOffset" }; CachedVertexShaderSetting m_camera_position_vertex{"cameraPosition"}; CachedPixelShaderSetting m_camera_position_pixel{"cameraPosition"}; - CachedVertexShaderSetting m_camera_projinv_vertex{"mCameraProjInv"}; - CachedPixelShaderSetting m_camera_projinv_pixel{"mCameraProjInv"}; - CachedVertexShaderSetting m_camera_view_vertex{"mCameraView"}; - CachedPixelShaderSetting m_camera_view_pixel{"mCameraView"}; CachedPixelShaderSetting m_texture0{"texture0"}; CachedPixelShaderSetting m_texture1{"texture1"}; CachedPixelShaderSetting m_texture2{"texture2"}; @@ -418,8 +414,6 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_vignette_dark_pixel{"vignette_dark"}; CachedPixelShaderSetting m_vignette_bright_pixel{"vignette_bright"}; CachedPixelShaderSetting m_vignette_power_pixel{"vignette_power"}; - CachedPixelShaderSetting m_fov_pixel{"fov"}; - CachedPixelShaderSetting m_window_size_pixel{"windowSize"}; static constexpr std::array SETTING_CALLBACKS = { "exposure_compensation", @@ -488,22 +482,6 @@ public: m_camera_position_vertex.set(camera_position, services); m_camera_position_pixel.set(camera_position, services); - core::matrix4 camera_proj = m_client->getCamera()->getCameraNode()->getProjectionMatrix(); - core::matrix4 camera_projinv; - camera_proj.getInverse(camera_projinv); - m_camera_projinv_vertex.set(camera_projinv, services); - m_camera_projinv_pixel.set(camera_projinv, services); - - core::matrix4 camera_view = m_client->getCamera()->getCameraNode()->getViewMatrix(); - m_camera_view_vertex.set(camera_view, services); - m_camera_view_pixel.set(camera_view, services); - - float fov = m_client->getCamera()->getFovMax(); - m_fov_pixel.set(&fov, services); - v2u32 window_size_int = RenderingEngine::getWindowSize(); - core::vector2df window_size = core::vector2df(window_size_int.X, window_size_int.Y); - m_window_size_pixel.set(window_size, services); - SamplerLayer_t tex_id; tex_id = 0; m_texture0.set(&tex_id, services); diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 139d82a2f..ddb0f8f85 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -659,11 +659,10 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, bool enable_waving_water = g_settings->getBool("enable_waving_water"); shaders_header << "#define ENABLE_WAVING_WATER " << enable_waving_water << "\n"; - if (enable_waving_water) { - shaders_header << "#define WATER_WAVE_HEIGHT " << g_settings->getFloat("water_wave_height") << "\n"; - shaders_header << "#define WATER_WAVE_LENGTH " << g_settings->getFloat("water_wave_length") << "\n"; - shaders_header << "#define WATER_WAVE_SPEED " << g_settings->getFloat("water_wave_speed") << "\n"; - } + + shaders_header << "#define WATER_WAVE_HEIGHT " << g_settings->getFloat("water_wave_height") << "\n"; + shaders_header << "#define WATER_WAVE_LENGTH " << g_settings->getFloat("water_wave_length") << "\n"; + shaders_header << "#define WATER_WAVE_SPEED " << g_settings->getFloat("water_wave_speed") << "\n"; shaders_header << "#define ENABLE_WAVING_LEAVES " << g_settings->getBool("enable_waving_leaves") << "\n"; shaders_header << "#define ENABLE_WAVING_PLANTS " << g_settings->getBool("enable_waving_plants") << "\n"; From b3710a982ec167f8c868ad53e50c1400ad7d515a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Fri, 20 Dec 2024 15:00:01 +0100 Subject: [PATCH 22/40] Fixes and Lua control --- client/shaders/nodes_shader/opengl_fragment.glsl | 16 +++++++++------- doc/lua_api.md | 4 ++++ src/client/clouds.cpp | 1 - src/client/game.cpp | 5 +++++ src/client/mesh_generator_thread.cpp | 1 - src/lighting.h | 6 ++++-- src/network/clientpackethandler.cpp | 4 +++- src/network/networkprotocol.cpp | 2 +- src/script/lua_api/l_object.cpp | 6 ++++++ src/server.cpp | 2 ++ 10 files changed, 34 insertions(+), 13 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index b0cc7c266..edf5d5af7 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -32,6 +32,8 @@ uniform float animationTimer; uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias1; uniform vec3 shadow_tint; + uniform float foliage_translucency; + uniform float specular_intensity; varying float adj_shadow_strength; varying float cosLight; @@ -533,12 +535,9 @@ void main(void) col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.5 * brightness_factor; vec3 water_reflect_color = - 6.0 * sunTint * dayLight * fresnel_factor * f_adj_shadow_strength * max(1.0 - shadow_uncorrected, 0.0) * + 2.0 * specular_intensity * sunTint * dayLight * fresnel_factor * max(1.0 - shadow_uncorrected, 0.0) * mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)); - // We clip the reflection color if it gets too bright - water_reflect_color *= min(2.0 / max(water_reflect_color.r, max(water_reflect_color.g, water_reflect_color.b)), 1.0); - // Sun reflection col.rgb += water_reflect_color * brightness_factor; #endif @@ -547,23 +546,26 @@ void main(void) // Apply specular to blocks. if (dot(v_LightDirection, vNormal) < 0.0) { // This intensity is a placeholder and should be replaced by proper specular maps. - float intensity = 4.0 * min(1.0, length(varColor.rgb * base.rgb)); + float intensity = specular_intensity * min(1.0, length(varColor.rgb * base.rgb)); const float specular_exponent = 5.0; const float fresnel_exponent = 4.0; col.rgb += - sunTint * intensity * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) * f_adj_shadow_strength * + sunTint * intensity * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) * pow(max(dot(reflect_ray, viewVec), 0.0), fresnel_exponent) * pow(1.0 - abs(dot(viewVec, fNormal)), specular_exponent); } #endif #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES) && defined(ENABLE_TRANSLUCENT_FOLIAGE) // Simulate translucent foliage. - col.rgb += 4.0 * sunTint * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) * f_adj_shadow_strength * pow(max(-dot(v_LightDirection, viewVec), 0.0), 4.0) * max(1.0 - shadow_uncorrected, 0.0); + col.rgb += foliage_translucency * sunTint * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) * pow(max(-dot(v_LightDirection, viewVec), 0.0), 4.0) * max(1.0 - shadow_uncorrected, 0.0); #endif } #endif + // We clip the color if it gets too bright + col *= min(2.0 / base.a / max(col.r, max(col.g, col.b)), 1.0); + // Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?), // the fog will only be rendered correctly if the last operation before the // clamp() is an addition. Else, the clamp() seems to be ignored. diff --git a/doc/lua_api.md b/doc/lua_api.md index f99e2eea8..ec22aed99 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8786,6 +8786,10 @@ child will follow movement and rotation of that bone. but keeping original luma and being symmetrical in terms of saturation (eg. -1 and 1 is the same saturation and luma, but different hues) * This value has no effect on clients who have shaders or post-processing disabled. + * `foliage_translucency` controls the intensity of the foliage translucency effect (default: `2.0`). + * This has no effect when dynamic shadows are disabled and on clients who have the "Translucent foliage" effect disabled. + * `specular_intensity` controls the intensity of specular highlights on nodes and liquids (default: `2.0`). + * This has no effect when dynamic shadows are disabled and on clients who have the "Translucent foliage" effect disabled. * `shadows` is a table that controls ambient shadows * This has no effect on clients who have the "Dynamic Shadows" effect disabled. * `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness) diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 420a51674..319a6e9ec 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -196,7 +196,6 @@ void Clouds::updateMesh() const f32 rz = cloud_size / 2; bool soft_clouds_enabled = g_settings->getBool("soft_clouds"); - bool shaded_clouds_enabled = soft_clouds_enabled && g_settings->getBool("enable_dynamic_shadows") && g_settings->getBool("enable_3d_clouds"); v3f pos(p0.X, m_params.height * BS, p0.Y); diff --git a/src/client/game.cpp b/src/client/game.cpp index a7555b55d..de9846bdf 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -414,6 +414,8 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_vignette_dark_pixel{"vignette_dark"}; CachedPixelShaderSetting m_vignette_bright_pixel{"vignette_bright"}; CachedPixelShaderSetting m_vignette_power_pixel{"vignette_power"}; + CachedPixelShaderSetting m_foliage_translucency_pixel{ "foliage_translucency" }; + CachedPixelShaderSetting m_specular_intensity_pixel{ "specular_intensity" }; static constexpr std::array SETTING_CALLBACKS = { "exposure_compensation", @@ -531,6 +533,9 @@ public: m_vignette_bright_pixel.set(&vignette_params.bright, services); m_vignette_power_pixel.set(&vignette_params.power, services); + m_foliage_translucency_pixel.set(&lighting.foliage_translucency, services); + m_specular_intensity_pixel.set(&lighting.specular_intensity, services); + if (g_settings->getBool("enable_color_grading")) { const ColorDecisionList& cdl_params = lighting.cdl; core::vector3df slope = cdl_params.slope; diff --git a/src/client/mesh_generator_thread.cpp b/src/client/mesh_generator_thread.cpp index 790477bf3..3d80f8e67 100644 --- a/src/client/mesh_generator_thread.cpp +++ b/src/client/mesh_generator_thread.cpp @@ -176,7 +176,6 @@ void MeshUpdateQueue::done(v3s16 pos) void MeshUpdateQueue::fillDataFromMapBlocks(QueuedMeshUpdate *q) { auto mesh_grid = m_client->getMeshGrid(); - MeshMakeData *data = new MeshMakeData(m_client->ndef(), MAP_BLOCKSIZE * mesh_grid.cell_size); q->data = data; diff --git a/src/lighting.h b/src/lighting.h index f04c2fde3..5f2436f70 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -56,9 +56,9 @@ struct Vignette { * */ struct ColorDecisionList { - core::vector3df slope{1.2, 1.0, 0.8}; + core::vector3df slope{1.0, 1.0, 1.0}; core::vector3df offset{0.0, 0.0, 0.0}; - core::vector3df power{1.25, 1.0, 0.9}; + core::vector3df power{1.0, 1.0, 1.0}; }; /** Describes ambient light settings for a player @@ -71,6 +71,8 @@ struct Lighting float shadow_intensity {0.0f}; float saturation {1.0f}; float volumetric_light_strength {0.0f}; + float foliage_translucency{1.5f}; + float specular_intensity{1.5f}; // These factors are calculated based on expected value of scattering factor of 1e-5 // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere core::vector3df volumetric_beta_r0{ 3.3362176e-01, 8.75378289198826e-01, 1.95342379700656 }; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 4315c6b9b..7a5d34dde 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1817,7 +1817,7 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt) >> lighting.bloom_radius; if (pkt->getRemainingBytes() >= 4) *pkt >> lighting.artificial_light_color; - if (pkt->getRemainingBytes() >= 60) + if (pkt->getRemainingBytes() >= 68) *pkt >> lighting.volumetric_beta_r0; *pkt >> lighting.vignette.dark >> lighting.vignette.bright @@ -1825,5 +1825,7 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt) *pkt >> lighting.cdl.slope; *pkt >> lighting.cdl.offset; *pkt >> lighting.cdl.power; + *pkt >> lighting.foliage_translucency; + *pkt >> lighting.specular_intensity; } } diff --git a/src/network/networkprotocol.cpp b/src/network/networkprotocol.cpp index 5ad852d37..a8b4953c7 100644 --- a/src/network/networkprotocol.cpp +++ b/src/network/networkprotocol.cpp @@ -58,7 +58,7 @@ Rename TOCLIENT_DEATHSCREEN to TOCLIENT_DEATHSCREEN_LEGACY Rename TOSERVER_RESPAWN to TOSERVER_RESPAWN_LEGACY Support float animation frame numbers in TOCLIENT_LOCAL_PLAYER_ANIMATIONS - Add beta_r0, vignette and cdl parameters to Lighting packets + Add beta_r0, vignette, specular intensity, foliage translucency and cdl parameters to Lighting packets [scheduled bump for 5.10.0] */ diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index ac89b7e1b..8c70cf473 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2623,6 +2623,8 @@ int ObjectRef::l_set_lighting(lua_State *L) lua_pop(L, 1); // shadows getfloatfield(L, -1, "saturation", lighting.saturation); + getfloatfield(L, -1, "foliage_translucency", lighting.foliage_translucency); + getfloatfield(L, -1, "specular_intensity", lighting.specular_intensity); lua_getfield(L, 2, "exposure"); if (lua_istable(L, -1)) { @@ -2700,6 +2702,10 @@ int ObjectRef::l_get_lighting(lua_State *L) lua_newtable(L); // result push_ARGB8(L, lighting.artificial_light_color); lua_setfield(L, -2, "artificial_light"); + lua_pushnumber(L, lighting.foliage_translucency); + lua_setfield(L, -2, "foliage_translucency"); + lua_pushnumber(L, lighting.specular_intensity); + lua_setfield(L, -2, "specular_intensity"); lua_newtable(L); // "shadows" lua_pushnumber(L, lighting.shadow_intensity); lua_setfield(L, -2, "intensity"); diff --git a/src/server.cpp b/src/server.cpp index 4b863b923..82aa8cf13 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1926,6 +1926,8 @@ void Server::SendSetLighting(session_t peer_id, const Lighting & lighting) pkt << lighting.cdl.slope; pkt << lighting.cdl.offset; pkt << lighting.cdl.power; + pkt << lighting.foliage_translucency; + pkt << lighting.specular_intensity; Send(&pkt); } From 91f614cbeed0795a7bf26df8731a56c8932192bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 22 Dec 2024 20:26:41 +0100 Subject: [PATCH 23/40] Various fixes Fix binormal and tangent Fix inconsistent sunrise/sunset timings and bright foliage at night --- client/shaders/nodes_shader/opengl_fragment.glsl | 10 +++++++--- client/shaders/nodes_shader/opengl_vertex.glsl | 13 ++++++------- client/shaders/object_shader/opengl_vertex.glsl | 6 +++--- src/client/shader.cpp | 9 ++++----- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 871fbc2e4..36603f8de 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -51,6 +51,7 @@ centroid varying vec2 varTexCoord; #endif varying highp vec3 eyeVec; varying float nightRatio; +varying float nightFactor; #ifdef ENABLE_DYNAMIC_SHADOWS #if (MATERIAL_WAVING_LIQUID && defined(ENABLE_WATER_REFLECTIONS)) @@ -448,6 +449,7 @@ void main(void) 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); + float f_shadow_factor = adj_shadow_strength / f_shadow_strength; if (distance_rate > 1e-7) { @@ -531,7 +533,7 @@ void main(void) mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)); // Sun reflection - col.rgb += water_reflect_color * brightness_factor; + col.rgb += water_reflect_color * f_shadow_factor * brightness_factor; #endif #if (defined(ENABLE_NODE_SPECULAR) && !MATERIAL_WAVING_LIQUID) @@ -543,14 +545,16 @@ void main(void) const float fresnel_exponent = 4.0; col.rgb += - sunTint * intensity * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) * + sunTint * intensity * f_shadow_factor * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) * pow(max(dot(reflect_ray, viewVec), 0.0), fresnel_exponent) * pow(1.0 - abs(dot(viewVec, fNormal)), specular_exponent); } #endif #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES) && defined(ENABLE_TRANSLUCENT_FOLIAGE) // Simulate translucent foliage. - col.rgb += foliage_translucency * sunTint * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) * pow(max(-dot(v_LightDirection, viewVec), 0.0), 4.0) * max(1.0 - shadow_uncorrected, 0.0); + col.rgb += + foliage_translucency * nightFactor * sunTint * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) * + pow(max(-dot(v_LightDirection, viewVec), 0.0), 4.0) * max(1.0 - shadow_uncorrected, 0.0); #endif } #endif diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 7b8f1a106..02a3741db 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -7,8 +7,6 @@ uniform highp vec3 cameraOffset; uniform float animationTimer; varying vec3 vNormal; -varying vec3 vTangent; -varying vec3 vBinormal; 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. @@ -48,6 +46,7 @@ varying float area_enable_parallax; varying highp vec3 eyeVec; varying float nightRatio; varying vec3 sunTint; +varying float nightFactor; // Color of the light emitted by the light sources. uniform vec3 artificialLight; const float e = 2.718281828459; @@ -209,8 +208,6 @@ void main(void) normalPass = normalize((inVertexNormal+1)/2); #endif vNormal = inVertexNormal; - vTangent = inVertexTangent.xyz; - vBinormal = inVertexBinormal.xyz; // Calculate color. vec4 color = inVertexColor; @@ -272,6 +269,7 @@ void main(void) perspective_factor = pFactor; sunTint = vec3(1.0); + nightFactor = 0.; if (f_timeofday < 0.21) { adj_shadow_strength = f_shadow_strength * 0.5 * (1.0 - mtsmoothstep(0.18, 0.21, f_timeofday)); @@ -280,10 +278,11 @@ void main(void) mtsmoothstep(0.793, 0.823, f_timeofday); } else { adj_shadow_strength = f_shadow_strength * - mtsmoothstep(0.21, 0.26, f_timeofday) * - (1.0 - mtsmoothstep(0.743, 0.793, f_timeofday)); + mtsmoothstep(0.21, 0.24, f_timeofday) * + (1.0 - mtsmoothstep(0.763, 0.793, f_timeofday)); + nightFactor = adj_shadow_strength / f_shadow_strength; #ifdef ENABLE_TINTED_SUNLIGHT - sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), min(1.0, 4.0 * adj_shadow_strength)); + sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), adj_shadow_strength / f_shadow_strength); #endif } } diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index 375918904..5be797dbc 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -182,9 +182,9 @@ void main(void) mtsmoothstep(0.793, 0.823, f_timeofday); } else { adj_shadow_strength = f_shadow_strength * - mtsmoothstep(0.21, 0.26, f_timeofday) * - (1.0 - mtsmoothstep(0.743, 0.793, f_timeofday)); - sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), min(1.0, 4.0 * adj_shadow_strength)); + mtsmoothstep(0.21, 0.24, f_timeofday) * + (1.0 - mtsmoothstep(0.763, 0.793, f_timeofday)); + sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), adj_shadow_strength / f_shadow_strength); } } #endif diff --git a/src/client/shader.cpp b/src/client/shader.cpp index de9d1980a..f81e86f76 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -674,11 +674,10 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, bool enable_waving_water = g_settings->getBool("enable_waving_water"); shaders_header << "#define ENABLE_WAVING_WATER " << enable_waving_water << "\n"; - if (enable_waving_water) { - shaders_header << "#define WATER_WAVE_HEIGHT " << g_settings->getFloat("water_wave_height") << "\n"; - shaders_header << "#define WATER_WAVE_LENGTH " << g_settings->getFloat("water_wave_length") << "\n"; - shaders_header << "#define WATER_WAVE_SPEED " << g_settings->getFloat("water_wave_speed") << "\n"; - } + shaders_header << "#define WATER_WAVE_HEIGHT " << g_settings->getFloat("water_wave_height") << "\n"; + shaders_header << "#define WATER_WAVE_LENGTH " << g_settings->getFloat("water_wave_length") << "\n"; + shaders_header << "#define WATER_WAVE_SPEED " << g_settings->getFloat("water_wave_speed") << "\n"; + switch (material_type) { case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT: case TILE_MATERIAL_WAVING_LIQUID_OPAQUE: From e8f486f3cc09239877e4199037944c17545ee8d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 22 Dec 2024 20:28:13 +0100 Subject: [PATCH 24/40] Fix trailing whitespace --- client/shaders/nodes_shader/opengl_fragment.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 36603f8de..20dfe111c 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -552,8 +552,8 @@ void main(void) #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES) && defined(ENABLE_TRANSLUCENT_FOLIAGE) // Simulate translucent foliage. - col.rgb += - foliage_translucency * nightFactor * sunTint * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) * + col.rgb += + foliage_translucency * nightFactor * sunTint * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) * pow(max(-dot(v_LightDirection, viewVec), 0.0), 4.0) * max(1.0 - shadow_uncorrected, 0.0); #endif } From 442245599bc00f2e0d58535a8e3898e16163d414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 22 Dec 2024 22:19:43 +0100 Subject: [PATCH 25/40] Fix tinted sunlight --- src/client/game.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client/game.cpp b/src/client/game.cpp index 830df0376..058619879 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -420,11 +420,11 @@ public: float volumetric_light_strength = lighting.volumetric_light_strength; m_volumetric_light_strength_pixel.set(&volumetric_light_strength, services); - - core::vector3df beta_r0 = lighting.volumetric_beta_r0; - m_volumetric_beta_r0_vertex.set(beta_r0, services); - m_volumetric_beta_r0_pixel.set(beta_r0, services); } + + core::vector3df beta_r0 = lighting.volumetric_beta_r0; + m_volumetric_beta_r0_vertex.set(beta_r0, services); + m_volumetric_beta_r0_pixel.set(beta_r0, services); } void onSetMaterial(const video::SMaterial &material) override From cb5d97e751dc7dd8791f404771efe32b915a6597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sat, 28 Dec 2024 10:47:57 +0100 Subject: [PATCH 26/40] Apply suggestions --- .../shaders/nodes_shader/opengl_vertex.glsl | 13 ++++++----- .../shaders/object_shader/opengl_vertex.glsl | 13 ++++++----- src/client/clouds.cpp | 22 +++++++++---------- src/network/clientpackethandler.cpp | 8 +++---- src/network/networkprotocol.cpp | 2 +- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 02a3741db..8eeee8796 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -270,16 +270,17 @@ void main(void) sunTint = vec3(1.0); nightFactor = 0.; - if (f_timeofday < 0.21) { + // The sun rises at 5:00 and sets at 19:00, which corresponds to 5/24=0.208 and 19/24 = 0.792. + if (f_timeofday < 0.208) { adj_shadow_strength = f_shadow_strength * 0.5 * - (1.0 - mtsmoothstep(0.18, 0.21, f_timeofday)); - } else if (f_timeofday >= 0.793) { + (1.0 - mtsmoothstep(0.178, 0.208, f_timeofday)); + } else if (f_timeofday >= 0.792) { adj_shadow_strength = f_shadow_strength * 0.5 * - mtsmoothstep(0.793, 0.823, f_timeofday); + mtsmoothstep(0.792, 0.822, f_timeofday); } else { adj_shadow_strength = f_shadow_strength * - mtsmoothstep(0.21, 0.24, f_timeofday) * - (1.0 - mtsmoothstep(0.763, 0.793, f_timeofday)); + mtsmoothstep(0.208, 0.238, f_timeofday) * + (1.0 - mtsmoothstep(0.762, 0.792, f_timeofday)); nightFactor = adj_shadow_strength / f_shadow_strength; #ifdef ENABLE_TINTED_SUNLIGHT sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), adj_shadow_strength / f_shadow_strength); diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index 5be797dbc..6dc1b8bda 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -173,17 +173,18 @@ void main(void) shadow_position.z -= z_bias; perspective_factor = pFactor; + // The sun rises at 5:00 and sets at 19:00, which corresponds to 5/24=0.208 and 19/24 = 0.792. sunTint = vec3(1.0); - if (f_timeofday < 0.21) { + if (f_timeofday < 0.208) { adj_shadow_strength = f_shadow_strength * 0.5 * - (1.0 - mtsmoothstep(0.18, 0.21, f_timeofday)); - } else if (f_timeofday >= 0.793) { + (1.0 - mtsmoothstep(0.178, 0.208, f_timeofday)); + } else if (f_timeofday >= 0.792) { adj_shadow_strength = f_shadow_strength * 0.5 * - mtsmoothstep(0.793, 0.823, f_timeofday); + mtsmoothstep(0.792, 0.822, f_timeofday); } else { adj_shadow_strength = f_shadow_strength * - mtsmoothstep(0.21, 0.24, f_timeofday) * - (1.0 - mtsmoothstep(0.763, 0.793, f_timeofday)); + mtsmoothstep(0.208, 0.238, f_timeofday) * + (1.0 - mtsmoothstep(0.762, 0.792, f_timeofday)); sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), adj_shadow_strength / f_shadow_strength); } } diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 62fc2c270..44caf93fd 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -211,7 +211,7 @@ void Clouds::updateMesh() switch (i) { case 0: // top - for (video::S3DVertex& vertex : v) { + for (video::S3DVertex &vertex : v) { vertex.Normal.set(0, 1, 0); } v[0].Pos.set(-rx, ry,-rz); @@ -226,14 +226,14 @@ void Clouds::updateMesh() continue; } if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { + for (video::S3DVertex &vertex : v) { vertex.Normal.set(0, 0, -1); } v[2].Color = c_bottom; v[3].Color = c_bottom; } else { - for (video::S3DVertex& vertex : v) { + for (video::S3DVertex &vertex : v) { vertex.Color = c_side_1; vertex.Normal.set(0, 0, -1); } @@ -250,14 +250,14 @@ void Clouds::updateMesh() continue; } if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { + for (video::S3DVertex &vertex : v) { vertex.Normal.set(1, 0, 0); } v[2].Color = c_bottom; v[3].Color = c_bottom; } else { - for (video::S3DVertex& vertex : v) { + for (video::S3DVertex &vertex : v) { vertex.Color = c_side_2; vertex.Normal.set(1, 0, 0); } @@ -274,14 +274,14 @@ void Clouds::updateMesh() continue; } if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { + for (video::S3DVertex &vertex : v) { vertex.Normal.set(0, 0, -1); } v[2].Color = c_bottom; v[3].Color = c_bottom; } else { - for (video::S3DVertex& vertex : v) { + for (video::S3DVertex &vertex : v) { vertex.Color = c_side_1; vertex.Normal.set(0, 0, -1); } @@ -298,14 +298,14 @@ void Clouds::updateMesh() continue; } if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { + for (video::S3DVertex &vertex : v) { vertex.Normal.set(-1, 0, 0); } v[2].Color = c_bottom; v[3].Color = c_bottom; } else { - for (video::S3DVertex& vertex : v) { + for (video::S3DVertex &vertex : v) { vertex.Color = c_side_2; vertex.Normal.set(-1, 0, 0); } @@ -316,7 +316,7 @@ void Clouds::updateMesh() v[3].Pos.set(-rx, 0, rz); break; case 5: // bottom - for (video::S3DVertex& vertex : v) { + for (video::S3DVertex &vertex : v) { vertex.Color = c_bottom; vertex.Normal.set(0, -1, 0); } @@ -327,7 +327,7 @@ void Clouds::updateMesh() break; } - for (video::S3DVertex& vertex : v) { + for (video::S3DVertex &vertex : v) { vertex.Pos += pos; vertices.push_back(vertex); } diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index e69718533..6423640f3 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1813,13 +1813,13 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt) *pkt >> lighting.bloom_intensity >> lighting.bloom_strength_factor >> lighting.bloom_radius; - if (pkt->getRemainingBytes() >= 4) + } + if (pkt->getRemainingBytes() >= 72) { *pkt >> lighting.artificial_light_color; - if (pkt->getRemainingBytes() >= 68) *pkt >> lighting.volumetric_beta_r0; *pkt >> lighting.vignette.dark - >> lighting.vignette.bright - >> lighting.vignette.power; + >> lighting.vignette.bright + >> lighting.vignette.power; *pkt >> lighting.cdl.slope; *pkt >> lighting.cdl.offset; *pkt >> lighting.cdl.power; diff --git a/src/network/networkprotocol.cpp b/src/network/networkprotocol.cpp index 6b4cf791d..6884be504 100644 --- a/src/network/networkprotocol.cpp +++ b/src/network/networkprotocol.cpp @@ -58,10 +58,10 @@ Rename TOCLIENT_DEATHSCREEN to TOCLIENT_DEATHSCREEN_LEGACY Rename TOSERVER_RESPAWN to TOSERVER_RESPAWN_LEGACY Support float animation frame numbers in TOCLIENT_LOCAL_PLAYER_ANIMATIONS - Add beta_r0, vignette, specular intensity, foliage translucency and cdl parameters to Lighting packets [scheduled bump for 5.10.0] PROTOCOL VERSION 47 Add particle blend mode "clip" + Add artificial light color, beta_r0, vignette, specular intensity, foliage translucency and cdl parameters to Lighting packets [scheduled bump for 5.11.0] */ From 03fd933c483ba89645e7e43b90a0d44c75dc733d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sat, 28 Dec 2024 10:49:16 +0100 Subject: [PATCH 27/40] Update log.h --- src/log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/log.h b/src/log.h index 1073d7935..0e34b2c83 100644 --- a/src/log.h +++ b/src/log.h @@ -62,7 +62,7 @@ private: // These calls explicitly use the templated version of operator<<, // so that they won't use the overloads created by ADD_NULL_CHECK. if (arg == nullptr) - return this->operator<< ((const char*)"(null)"); + return this->operator<< ("(null)"); else return this->operator<< (std::forward(arg)); } From ba31db3eef6684168381f95ee5649a2ffac01b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sat, 28 Dec 2024 16:06:34 +0100 Subject: [PATCH 28/40] Update l_object.cpp --- src/script/lua_api/l_object.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 8c70cf473..6ca82a3d8 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2660,9 +2660,9 @@ int ObjectRef::l_set_lighting(lua_State *L) lua_getfield(L, 2, "vignette"); if (lua_istable(L, -1)) { - lighting.vignette.dark = getfloatfield_default(L, -1, "dark", lighting.vignette.dark); - lighting.vignette.bright = getfloatfield_default(L, -1, "bright", lighting.vignette.bright); - lighting.vignette.power = getfloatfield_default(L, -1, "power", lighting.vignette.power); + getfloatfield(L, -1, "dark", lighting.vignette.dark); + getfloatfield(L, -1, "bright", lighting.vignette.bright); + getfloatfield(L, -1, "power", lighting.vignette.power); } lua_pop(L, 1); // vignette From 6b6baf3fd71760f60662065fc4cf9ae2778a080e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sat, 28 Dec 2024 21:41:33 +0100 Subject: [PATCH 29/40] Undo changes to the clouds --- src/client/clouds.cpp | 370 +++++++++++++++++++++--------------------- 1 file changed, 187 insertions(+), 183 deletions(-) diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 44caf93fd..3d56c5bf8 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -13,21 +13,22 @@ #include "settings.h" #include -scene::ISceneManager *g_menucloudsmgr = nullptr; -Clouds *g_menuclouds = nullptr; +class Clouds; +scene::ISceneManager* g_menucloudsmgr = nullptr; +Clouds* g_menuclouds = nullptr; // Constant for now static constexpr const float cloud_size = BS * 64.0f; -static void cloud_3d_setting_changed(const std::string &settingname, void *data) +static void cloud_3d_setting_changed(const std::string& settingname, void* data) { - ((Clouds *)data)->readSettings(); + ((Clouds*)data)->readSettings(); } -Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc, - s32 id, - u32 seed -): +Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource* ssrc, + s32 id, + u32 seed +) : scene::ISceneNode(mgr->getRootSceneNode(), mgr, id), m_seed(seed) { @@ -62,7 +63,7 @@ Clouds::~Clouds() void Clouds::OnRegisterSceneNode() { - if(IsVisible) + if (IsVisible) { SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); } @@ -90,13 +91,16 @@ void Clouds::updateMesh() if (!m_mesh_valid) { // mesh was never created or invalidated - } else if (m_mesh_origin.getDistanceFrom(m_origin) >= max_d) { + } + else if (m_mesh_origin.getDistanceFrom(m_origin) >= max_d) { // clouds moved - } else if (center_of_drawing_in_noise_i != m_last_noise_center) { + } + else if (center_of_drawing_in_noise_i != m_last_noise_center) { // noise offset changed // I think in practice this never happens due to the camera offset // being smaller than the cloud size.(?) - } else { + } + else { return; } @@ -140,7 +144,7 @@ void Clouds::updateMesh() std::vector grid(m_cloud_radius_i * 2 * m_cloud_radius_i * 2); - for(s16 zi = -m_cloud_radius_i; zi < m_cloud_radius_i; zi++) { + for (s16 zi = -m_cloud_radius_i; zi < m_cloud_radius_i; zi++) { u32 si = (zi + m_cloud_radius_i) * m_cloud_radius_i * 2 + m_cloud_radius_i; for (s16 xi = -m_cloud_radius_i; xi < m_cloud_radius_i; xi++) { @@ -154,9 +158,9 @@ void Clouds::updateMesh() } - auto *mb = m_meshbuffer.get(); - auto &vertices = mb->Vertices->Data; - auto &indices = mb->Indices->Data; + auto* mb = m_meshbuffer.get(); + auto& vertices = mb->Vertices->Data; + auto& indices = mb->Indices->Data; { const u32 vertex_count = num_faces_to_draw * 16 * m_cloud_radius_i * m_cloud_radius_i; const u32 quad_count = vertex_count / 4; @@ -172,167 +176,166 @@ void Clouds::updateMesh() ((x) >= -(radius) && (x) < (radius) && (z) >= -(radius) && (z) < (radius)) vertices.clear(); - for (s16 zi0= -m_cloud_radius_i; zi0 < m_cloud_radius_i; zi0++) - for (s16 xi0= -m_cloud_radius_i; xi0 < m_cloud_radius_i; xi0++) - { - s16 zi = zi0; - s16 xi = xi0; - // Draw from back to front for proper transparency - if(zi >= 0) - zi = m_cloud_radius_i - zi - 1; - if(xi >= 0) - xi = m_cloud_radius_i - xi - 1; - - u32 i = GETINDEX(xi, zi, m_cloud_radius_i); - - if (!grid[i]) - continue; - - v2f p0 = v2f(xi,zi)*cloud_size + world_center_of_drawing_in_noise_f; - - const f32 rx = cloud_size / 2.0f; - // if clouds are flat, the top layer should be at the given height - const f32 ry = is3D() ? m_params.thickness * BS : 0.0f; - const f32 rz = cloud_size / 2; - - bool soft_clouds_enabled = g_settings->getBool("soft_clouds"); - - v3f pos(p0.X, m_params.height * BS, p0.Y); - - video::S3DVertex v[4] = { - video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 1), - video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 1), - video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 0), - video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0) - }; - - for (u32 i = 0; i < num_faces_to_draw; i++) + for (s16 zi0 = -m_cloud_radius_i; zi0 < m_cloud_radius_i; zi0++) + for (s16 xi0 = -m_cloud_radius_i; xi0 < m_cloud_radius_i; xi0++) { - switch (i) - { - case 0: // top - for (video::S3DVertex &vertex : v) { - vertex.Normal.set(0, 1, 0); - } - v[0].Pos.set(-rx, ry,-rz); - v[1].Pos.set(-rx, ry, rz); - v[2].Pos.set( rx, ry, rz); - v[3].Pos.set( rx, ry,-rz); - break; - case 1: // back - if (INAREA(xi, zi - 1, m_cloud_radius_i)) { - u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex &vertex : v) { - vertex.Normal.set(0, 0, -1); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex &vertex : v) { - vertex.Color = c_side_1; - vertex.Normal.set(0, 0, -1); - } - } - v[0].Pos.set(-rx, ry,-rz); - v[1].Pos.set( rx, ry,-rz); - v[2].Pos.set( rx, 0,-rz); - v[3].Pos.set(-rx, 0,-rz); - break; - case 2: //right - if (INAREA(xi + 1, zi, m_cloud_radius_i)) { - u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex &vertex : v) { - vertex.Normal.set(1, 0, 0); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex &vertex : v) { - vertex.Color = c_side_2; - vertex.Normal.set(1, 0, 0); - } - } - v[0].Pos.set(rx, ry,-rz); - v[1].Pos.set(rx, ry, rz); - v[2].Pos.set(rx, 0, rz); - v[3].Pos.set(rx, 0,-rz); - break; - case 3: // front - if (INAREA(xi, zi + 1, m_cloud_radius_i)) { - u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex &vertex : v) { - vertex.Normal.set(0, 0, -1); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex &vertex : v) { - vertex.Color = c_side_1; - vertex.Normal.set(0, 0, -1); - } - } - v[0].Pos.set( rx, ry, rz); - v[1].Pos.set(-rx, ry, rz); - v[2].Pos.set(-rx, 0, rz); - v[3].Pos.set( rx, 0, rz); - break; - case 4: // left - if (INAREA(xi - 1, zi, m_cloud_radius_i)) { - u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex &vertex : v) { - vertex.Normal.set(-1, 0, 0); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex &vertex : v) { - vertex.Color = c_side_2; - vertex.Normal.set(-1, 0, 0); - } - } - v[0].Pos.set(-rx, ry, rz); - v[1].Pos.set(-rx, ry,-rz); - v[2].Pos.set(-rx, 0,-rz); - v[3].Pos.set(-rx, 0, rz); - break; - case 5: // bottom - for (video::S3DVertex &vertex : v) { - vertex.Color = c_bottom; - vertex.Normal.set(0, -1, 0); - } - v[0].Pos.set( rx, 0, rz); - v[1].Pos.set(-rx, 0, rz); - v[2].Pos.set(-rx, 0,-rz); - v[3].Pos.set( rx, 0,-rz); - break; - } + s16 zi = zi0; + s16 xi = xi0; + // Draw from back to front for proper transparency + if (zi >= 0) + zi = m_cloud_radius_i - zi - 1; + if (xi >= 0) + xi = m_cloud_radius_i - xi - 1; - for (video::S3DVertex &vertex : v) { - vertex.Pos += pos; - vertices.push_back(vertex); + u32 i = GETINDEX(xi, zi, m_cloud_radius_i); + + if (!grid[i]) + continue; + + v2f p0 = v2f(xi, zi) * cloud_size + world_center_of_drawing_in_noise_f; + + video::S3DVertex v[4] = { + video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 1), + video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 1), + video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 0), + video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0) + }; + + const f32 rx = cloud_size / 2.0f; + // if clouds are flat, the top layer should be at the given height + const f32 ry = is3D() ? m_params.thickness * BS : 0.0f; + const f32 rz = cloud_size / 2; + + bool soft_clouds_enabled = g_settings->getBool("soft_clouds"); + for (u32 i = 0; i < num_faces_to_draw; i++) + { + switch (i) + { + case 0: // top + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(0, 1, 0); + } + v[0].Pos.set(-rx, ry, -rz); + v[1].Pos.set(-rx, ry, rz); + v[2].Pos.set(rx, ry, rz); + v[3].Pos.set(rx, ry, -rz); + break; + case 1: // back + if (INAREA(xi, zi - 1, m_cloud_radius_i)) { + u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(0, 0, -1); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_1; + vertex.Normal.set(0, 0, -1); + } + } + v[0].Pos.set(-rx, ry, -rz); + v[1].Pos.set(rx, ry, -rz); + v[2].Pos.set(rx, 0, -rz); + v[3].Pos.set(-rx, 0, -rz); + break; + case 2: //right + if (INAREA(xi + 1, zi, m_cloud_radius_i)) { + u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(1, 0, 0); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_2; + vertex.Normal.set(1, 0, 0); + } + } + v[0].Pos.set(rx, ry, -rz); + v[1].Pos.set(rx, ry, rz); + v[2].Pos.set(rx, 0, rz); + v[3].Pos.set(rx, 0, -rz); + break; + case 3: // front + if (INAREA(xi, zi + 1, m_cloud_radius_i)) { + u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(0, 0, -1); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_1; + vertex.Normal.set(0, 0, -1); + } + } + v[0].Pos.set(rx, ry, rz); + v[1].Pos.set(-rx, ry, rz); + v[2].Pos.set(-rx, 0, rz); + v[3].Pos.set(rx, 0, rz); + break; + case 4: // left + if (INAREA(xi - 1, zi, m_cloud_radius_i)) { + u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(-1, 0, 0); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_2; + vertex.Normal.set(-1, 0, 0); + } + } + v[0].Pos.set(-rx, ry, rz); + v[1].Pos.set(-rx, ry, -rz); + v[2].Pos.set(-rx, 0, -rz); + v[3].Pos.set(-rx, 0, rz); + break; + case 5: // bottom + for (video::S3DVertex& vertex : v) { + vertex.Color = c_bottom; + vertex.Normal.set(0, -1, 0); + } + v[0].Pos.set(rx, 0, rz); + v[1].Pos.set(-rx, 0, rz); + v[2].Pos.set(-rx, 0, -rz); + v[3].Pos.set(rx, 0, -rz); + break; + } + + v3f pos(p0.X, m_params.height * BS, p0.Y); + + for (video::S3DVertex& vertex : v) { + vertex.Pos += pos; + vertices.push_back(vertex); + } } } - } mb->setDirty(scene::EBT_VERTEX); const u32 quad_count = mb->getVertexCount() / 4; @@ -341,7 +344,8 @@ void Clouds::updateMesh() if (mb->getIndexCount() > index_count) { indices.resize(index_count); mb->setDirty(scene::EBT_INDEX); - } else if (mb->getIndexCount() < index_count) { + } + else if (mb->getIndexCount() < index_count) { const u32 start = mb->getIndexCount() / 6; assert(start * 6 == mb->getIndexCount()); for (u32 k = start; k < quad_count; k++) { @@ -389,7 +393,7 @@ void Clouds::render() const float cloud_full_radius = cloud_size * m_cloud_radius_i; // Get fog parameters for setting them back later - video::SColor fog_color(0,0,0,0); + video::SColor fog_color(0, 0, 0, 0); video::E_FOG_TYPE fog_type = video::EFT_FOG_LINEAR; f32 fog_start = 0; f32 fog_end = 0; @@ -397,19 +401,19 @@ void Clouds::render() bool fog_pixelfog = false; bool fog_rangefog = false; driver->getFog(fog_color, fog_type, fog_start, fog_end, fog_density, - fog_pixelfog, fog_rangefog); + fog_pixelfog, fog_rangefog); // Set our own fog, unless it was already disabled if (fog_start < FOG_RANGE_ALL) { driver->setFog(fog_color, fog_type, cloud_full_radius * 0.5, - cloud_full_radius*1.2, fog_density, fog_pixelfog, fog_rangefog); + cloud_full_radius * 1.2, fog_density, fog_pixelfog, fog_rangefog); } driver->drawMeshBuffer(m_meshbuffer.get()); // Restore fog settings driver->setFog(fog_color, fog_type, fog_start, fog_end, fog_density, - fog_pixelfog, fog_rangefog); + fog_pixelfog, fog_rangefog); } void Clouds::step(float dtime) @@ -417,7 +421,7 @@ void Clouds::step(float dtime) m_origin = m_origin + dtime * BS * m_params.speed; } -void Clouds::update(const v3f &camera_p, const video::SColorf &color_diffuse) +void Clouds::update(const v3f& camera_p, const video::SColorf& color_diffuse) { video::SColorf ambient(m_params.color_ambient); video::SColorf bright(m_params.color_bright); @@ -432,7 +436,7 @@ void Clouds::update(const v3f &camera_p, const video::SColorf &color_diffuse) if (is3D()) { float camera_height = camera_p.Y - BS * m_camera_offset.Y; if (camera_height >= m_box.MinEdge.Y && - camera_height <= m_box.MaxEdge.Y) { + camera_height <= m_box.MaxEdge.Y) { v2f camera_in_noise; camera_in_noise.X = floor((camera_p.X - m_origin.X) / cloud_size + 0.5); camera_in_noise.Y = floor((camera_p.Z - m_origin.Y) / cloud_size + 0.5); @@ -458,9 +462,9 @@ bool Clouds::gridFilled(int x, int y) const { float cloud_size_noise = cloud_size / (BS * 200.f); float noise = noise2d_perlin( - (float)x * cloud_size_noise, - (float)y * cloud_size_noise, - m_seed, 3, 0.5); + (float)x * cloud_size_noise, + (float)y * cloud_size_noise, + m_seed, 3, 0.5); // normalize to 0..1 (given 3 octaves) static constexpr const float noise_bound = 1.0f + 0.5f + 0.25f; float density = noise / noise_bound * 0.5f + 0.5f; From 83aeec4935329ac1b0891b4b10d2e777027aae13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sat, 28 Dec 2024 21:45:51 +0100 Subject: [PATCH 30/40] Undo silly Visual Studio autocorrect stuff My rage is untethered and knows no bounds --- src/client/clouds.cpp | 361 +++++++++++++++++++++--------------------- 1 file changed, 177 insertions(+), 184 deletions(-) diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 3d56c5bf8..55e89410d 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -14,21 +14,21 @@ #include class Clouds; -scene::ISceneManager* g_menucloudsmgr = nullptr; -Clouds* g_menuclouds = nullptr; +scene::ISceneManager *g_menucloudsmgr = nullptr; +Clouds *g_menuclouds = nullptr; // Constant for now static constexpr const float cloud_size = BS * 64.0f; -static void cloud_3d_setting_changed(const std::string& settingname, void* data) +static void cloud_3d_setting_changed(const std::string &settingname, void *data) { - ((Clouds*)data)->readSettings(); + ((Clouds *)data)->readSettings(); } -Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource* ssrc, - s32 id, - u32 seed -) : +Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc, + s32 id, + u32 seed +): scene::ISceneNode(mgr->getRootSceneNode(), mgr, id), m_seed(seed) { @@ -63,7 +63,7 @@ Clouds::~Clouds() void Clouds::OnRegisterSceneNode() { - if (IsVisible) + if(IsVisible) { SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); } @@ -91,16 +91,13 @@ void Clouds::updateMesh() if (!m_mesh_valid) { // mesh was never created or invalidated - } - else if (m_mesh_origin.getDistanceFrom(m_origin) >= max_d) { + } else if (m_mesh_origin.getDistanceFrom(m_origin) >= max_d) { // clouds moved - } - else if (center_of_drawing_in_noise_i != m_last_noise_center) { + } else if (center_of_drawing_in_noise_i != m_last_noise_center) { // noise offset changed // I think in practice this never happens due to the camera offset // being smaller than the cloud size.(?) - } - else { + } else { return; } @@ -144,7 +141,7 @@ void Clouds::updateMesh() std::vector grid(m_cloud_radius_i * 2 * m_cloud_radius_i * 2); - for (s16 zi = -m_cloud_radius_i; zi < m_cloud_radius_i; zi++) { + for(s16 zi = -m_cloud_radius_i; zi < m_cloud_radius_i; zi++) { u32 si = (zi + m_cloud_radius_i) * m_cloud_radius_i * 2 + m_cloud_radius_i; for (s16 xi = -m_cloud_radius_i; xi < m_cloud_radius_i; xi++) { @@ -158,9 +155,9 @@ void Clouds::updateMesh() } - auto* mb = m_meshbuffer.get(); - auto& vertices = mb->Vertices->Data; - auto& indices = mb->Indices->Data; + auto *mb = m_meshbuffer.get(); + auto &vertices = mb->Vertices->Data; + auto &indices = mb->Indices->Data; { const u32 vertex_count = num_faces_to_draw * 16 * m_cloud_radius_i * m_cloud_radius_i; const u32 quad_count = vertex_count / 4; @@ -176,166 +173,163 @@ void Clouds::updateMesh() ((x) >= -(radius) && (x) < (radius) && (z) >= -(radius) && (z) < (radius)) vertices.clear(); - for (s16 zi0 = -m_cloud_radius_i; zi0 < m_cloud_radius_i; zi0++) - for (s16 xi0 = -m_cloud_radius_i; xi0 < m_cloud_radius_i; xi0++) + for (s16 zi0= -m_cloud_radius_i; zi0 < m_cloud_radius_i; zi0++) + for (s16 xi0= -m_cloud_radius_i; xi0 < m_cloud_radius_i; xi0++) + { + s16 zi = zi0; + s16 xi = xi0; + // Draw from back to front for proper transparency + if(zi >= 0) + zi = m_cloud_radius_i - zi - 1; + if(xi >= 0) + xi = m_cloud_radius_i - xi - 1; + + u32 i = GETINDEX(xi, zi, m_cloud_radius_i); + + if (!grid[i]) + continue; + + v2f p0 = v2f(xi,zi)*cloud_size + world_center_of_drawing_in_noise_f; + + video::S3DVertex v[4] = { + video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 1), + video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 1), + video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 0), + video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0) + }; + + const f32 rx = cloud_size / 2.0f; + // if clouds are flat, the top layer should be at the given height + const f32 ry = is3D() ? m_params.thickness * BS : 0.0f; + const f32 rz = cloud_size / 2; + + bool soft_clouds_enabled = g_settings->getBool("soft_clouds"); + for (u32 i = 0; i < num_faces_to_draw; i++) { - s16 zi = zi0; - s16 xi = xi0; - // Draw from back to front for proper transparency - if (zi >= 0) - zi = m_cloud_radius_i - zi - 1; - if (xi >= 0) - xi = m_cloud_radius_i - xi - 1; - - u32 i = GETINDEX(xi, zi, m_cloud_radius_i); - - if (!grid[i]) - continue; - - v2f p0 = v2f(xi, zi) * cloud_size + world_center_of_drawing_in_noise_f; - - video::S3DVertex v[4] = { - video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 1), - video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 1), - video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 0), - video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0) - }; - - const f32 rx = cloud_size / 2.0f; - // if clouds are flat, the top layer should be at the given height - const f32 ry = is3D() ? m_params.thickness * BS : 0.0f; - const f32 rz = cloud_size / 2; - - bool soft_clouds_enabled = g_settings->getBool("soft_clouds"); - for (u32 i = 0; i < num_faces_to_draw; i++) + switch (i) { - switch (i) - { - case 0: // top - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(0, 1, 0); - } - v[0].Pos.set(-rx, ry, -rz); - v[1].Pos.set(-rx, ry, rz); - v[2].Pos.set(rx, ry, rz); - v[3].Pos.set(rx, ry, -rz); - break; - case 1: // back - if (INAREA(xi, zi - 1, m_cloud_radius_i)) { - u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(0, 0, -1); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_1; - vertex.Normal.set(0, 0, -1); - } - } - v[0].Pos.set(-rx, ry, -rz); - v[1].Pos.set(rx, ry, -rz); - v[2].Pos.set(rx, 0, -rz); - v[3].Pos.set(-rx, 0, -rz); - break; - case 2: //right - if (INAREA(xi + 1, zi, m_cloud_radius_i)) { - u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(1, 0, 0); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_2; - vertex.Normal.set(1, 0, 0); - } - } - v[0].Pos.set(rx, ry, -rz); - v[1].Pos.set(rx, ry, rz); - v[2].Pos.set(rx, 0, rz); - v[3].Pos.set(rx, 0, -rz); - break; - case 3: // front - if (INAREA(xi, zi + 1, m_cloud_radius_i)) { - u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(0, 0, -1); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_1; - vertex.Normal.set(0, 0, -1); - } - } - v[0].Pos.set(rx, ry, rz); - v[1].Pos.set(-rx, ry, rz); - v[2].Pos.set(-rx, 0, rz); - v[3].Pos.set(rx, 0, rz); - break; - case 4: // left - if (INAREA(xi - 1, zi, m_cloud_radius_i)) { - u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i); - if (grid[j]) - continue; - } - if (soft_clouds_enabled) { - for (video::S3DVertex& vertex : v) { - vertex.Normal.set(-1, 0, 0); - } - v[2].Color = c_bottom; - v[3].Color = c_bottom; - } - else { - for (video::S3DVertex& vertex : v) { - vertex.Color = c_side_2; - vertex.Normal.set(-1, 0, 0); - } - } - v[0].Pos.set(-rx, ry, rz); - v[1].Pos.set(-rx, ry, -rz); - v[2].Pos.set(-rx, 0, -rz); - v[3].Pos.set(-rx, 0, rz); - break; - case 5: // bottom - for (video::S3DVertex& vertex : v) { - vertex.Color = c_bottom; - vertex.Normal.set(0, -1, 0); - } - v[0].Pos.set(rx, 0, rz); - v[1].Pos.set(-rx, 0, rz); - v[2].Pos.set(-rx, 0, -rz); - v[3].Pos.set(rx, 0, -rz); - break; - } - - v3f pos(p0.X, m_params.height * BS, p0.Y); - + case 0: // top for (video::S3DVertex& vertex : v) { - vertex.Pos += pos; - vertices.push_back(vertex); + vertex.Normal.set(0, 1, 0); } + v[0].Pos.set(-rx, ry,-rz); + v[1].Pos.set(-rx, ry, rz); + v[2].Pos.set( rx, ry, rz); + v[3].Pos.set( rx, ry,-rz); + break; + case 1: // back + if (INAREA(xi, zi - 1, m_cloud_radius_i)) { + u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(0, 0, -1); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_1; + vertex.Normal.set(0, 0, -1); + } + } + v[0].Pos.set(-rx, ry,-rz); + v[1].Pos.set( rx, ry,-rz); + v[2].Pos.set( rx, 0,-rz); + v[3].Pos.set(-rx, 0,-rz); + break; + case 2: //right + if (INAREA(xi + 1, zi, m_cloud_radius_i)) { + u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(1, 0, 0); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } + else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_2; + vertex.Normal.set(1, 0, 0); + } + } + v[0].Pos.set(rx, ry,-rz); + v[1].Pos.set(rx, ry, rz); + v[2].Pos.set(rx, 0, rz); + v[3].Pos.set(rx, 0,-rz); + break; + case 3: // front + if (INAREA(xi, zi + 1, m_cloud_radius_i)) { + u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(0, 0, -1); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_1; + vertex.Normal.set(0, 0, -1); + } + } + v[0].Pos.set( rx, ry, rz); + v[1].Pos.set(-rx, ry, rz); + v[2].Pos.set(-rx, 0, rz); + v[3].Pos.set( rx, 0, rz); + break; + case 4: // left + if (INAREA(xi - 1, zi, m_cloud_radius_i)) { + u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i); + if (grid[j]) + continue; + } + if (soft_clouds_enabled) { + for (video::S3DVertex& vertex : v) { + vertex.Normal.set(-1, 0, 0); + } + v[2].Color = c_bottom; + v[3].Color = c_bottom; + } else { + for (video::S3DVertex& vertex : v) { + vertex.Color = c_side_2; + vertex.Normal.set(-1, 0, 0); + } + } + v[0].Pos.set(-rx, ry, rz); + v[1].Pos.set(-rx, ry,-rz); + v[2].Pos.set(-rx, 0,-rz); + v[3].Pos.set(-rx, 0, rz); + break; + case 5: // bottom + for (video::S3DVertex& vertex : v) { + vertex.Color = c_bottom; + vertex.Normal.set(0, -1, 0); + } + v[0].Pos.set( rx, 0, rz); + v[1].Pos.set(-rx, 0, rz); + v[2].Pos.set(-rx, 0,-rz); + v[3].Pos.set( rx, 0,-rz); + break; + } + + v3f pos(p0.X, m_params.height * BS, p0.Y); + + for (video::S3DVertex &vertex : v) { + vertex.Pos += pos; + vertices.push_back(vertex); } } + } mb->setDirty(scene::EBT_VERTEX); const u32 quad_count = mb->getVertexCount() / 4; @@ -344,8 +338,7 @@ void Clouds::updateMesh() if (mb->getIndexCount() > index_count) { indices.resize(index_count); mb->setDirty(scene::EBT_INDEX); - } - else if (mb->getIndexCount() < index_count) { + } else if (mb->getIndexCount() < index_count) { const u32 start = mb->getIndexCount() / 6; assert(start * 6 == mb->getIndexCount()); for (u32 k = start; k < quad_count; k++) { @@ -393,7 +386,7 @@ void Clouds::render() const float cloud_full_radius = cloud_size * m_cloud_radius_i; // Get fog parameters for setting them back later - video::SColor fog_color(0, 0, 0, 0); + video::SColor fog_color(0,0,0,0); video::E_FOG_TYPE fog_type = video::EFT_FOG_LINEAR; f32 fog_start = 0; f32 fog_end = 0; @@ -401,19 +394,19 @@ void Clouds::render() bool fog_pixelfog = false; bool fog_rangefog = false; driver->getFog(fog_color, fog_type, fog_start, fog_end, fog_density, - fog_pixelfog, fog_rangefog); + fog_pixelfog, fog_rangefog); // Set our own fog, unless it was already disabled if (fog_start < FOG_RANGE_ALL) { driver->setFog(fog_color, fog_type, cloud_full_radius * 0.5, - cloud_full_radius * 1.2, fog_density, fog_pixelfog, fog_rangefog); + cloud_full_radius*1.2, fog_density, fog_pixelfog, fog_rangefog); } driver->drawMeshBuffer(m_meshbuffer.get()); // Restore fog settings driver->setFog(fog_color, fog_type, fog_start, fog_end, fog_density, - fog_pixelfog, fog_rangefog); + fog_pixelfog, fog_rangefog); } void Clouds::step(float dtime) @@ -421,7 +414,7 @@ void Clouds::step(float dtime) m_origin = m_origin + dtime * BS * m_params.speed; } -void Clouds::update(const v3f& camera_p, const video::SColorf& color_diffuse) +void Clouds::update(const v3f &camera_p, const video::SColorf &color_diffuse) { video::SColorf ambient(m_params.color_ambient); video::SColorf bright(m_params.color_bright); @@ -436,7 +429,7 @@ void Clouds::update(const v3f& camera_p, const video::SColorf& color_diffuse) if (is3D()) { float camera_height = camera_p.Y - BS * m_camera_offset.Y; if (camera_height >= m_box.MinEdge.Y && - camera_height <= m_box.MaxEdge.Y) { + camera_height <= m_box.MaxEdge.Y) { v2f camera_in_noise; camera_in_noise.X = floor((camera_p.X - m_origin.X) / cloud_size + 0.5); camera_in_noise.Y = floor((camera_p.Z - m_origin.Y) / cloud_size + 0.5); @@ -462,9 +455,9 @@ bool Clouds::gridFilled(int x, int y) const { float cloud_size_noise = cloud_size / (BS * 200.f); float noise = noise2d_perlin( - (float)x * cloud_size_noise, - (float)y * cloud_size_noise, - m_seed, 3, 0.5); + (float)x * cloud_size_noise, + (float)y * cloud_size_noise, + m_seed, 3, 0.5); // normalize to 0..1 (given 3 octaves) static constexpr const float noise_bound = 1.0f + 0.5f + 0.25f; float density = noise / noise_bound * 0.5f + 0.5f; From 15e6f0a2e20038f78d0ec651662ee8b9f48556cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sat, 28 Dec 2024 23:41:07 +0100 Subject: [PATCH 31/40] Undo more non-changes --- src/client/render/pipeline.cpp | 1 + src/client/render/pipeline.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/render/pipeline.cpp b/src/client/render/pipeline.cpp index 740117111..33b3e78e2 100644 --- a/src/client/render/pipeline.cpp +++ b/src/client/render/pipeline.cpp @@ -101,6 +101,7 @@ void TextureBuffer::swapTextures(u8 texture_a, u8 texture_b) m_textures[texture_b] = temp; } + bool TextureBuffer::ensureTexture(video::ITexture **texture, const TextureDefinition& definition, PipelineContext &context) { bool modify; diff --git a/src/client/render/pipeline.h b/src/client/render/pipeline.h index 1e2f3d87f..17bed8b7b 100644 --- a/src/client/render/pipeline.h +++ b/src/client/render/pipeline.h @@ -133,7 +133,6 @@ public: virtual video::ITexture *getTexture(u8 index) override; virtual void reset(PipelineContext &context) override; void swapTextures(u8 texture_a, u8 texture_b); - void setTextureImage(u8 id, video::IImage* image); private: static const u8 NO_DEPTH_TEXTURE = 255; From 33b68a4d050d829042a3a5a8b2a890be7d27421b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 29 Dec 2024 18:08:03 +0100 Subject: [PATCH 32/40] Update server.cpp --- src/server.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index 6df86f890..198e06677 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1901,7 +1901,7 @@ void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override, Send(&pkt); } -void Server::SendSetLighting(session_t peer_id, const Lighting & lighting) +void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) { NetworkPacket pkt(TOCLIENT_SET_LIGHTING, 4, peer_id); @@ -1910,11 +1910,11 @@ void Server::SendSetLighting(session_t peer_id, const Lighting & lighting) pkt << lighting.saturation; pkt << lighting.exposure.luminance_min - << lighting.exposure.luminance_max - << lighting.exposure.exposure_correction - << lighting.exposure.speed_dark_bright - << lighting.exposure.speed_bright_dark - << lighting.exposure.center_weight_power; + << lighting.exposure.luminance_max + << lighting.exposure.exposure_correction + << lighting.exposure.speed_dark_bright + << lighting.exposure.speed_bright_dark + << lighting.exposure.center_weight_power; pkt << lighting.volumetric_light_strength << lighting.shadow_tint; pkt << lighting.bloom_intensity << lighting.bloom_strength_factor << From 0dab606f2ad8caf3ca49118cb55da912d16d1ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 29 Dec 2024 18:09:39 +0100 Subject: [PATCH 33/40] Update server.cpp --- src/server.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index 198e06677..24ad4d9c0 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1910,11 +1910,11 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) pkt << lighting.saturation; pkt << lighting.exposure.luminance_min - << lighting.exposure.luminance_max - << lighting.exposure.exposure_correction - << lighting.exposure.speed_dark_bright - << lighting.exposure.speed_bright_dark - << lighting.exposure.center_weight_power; + << lighting.exposure.luminance_max + << lighting.exposure.exposure_correction + << lighting.exposure.speed_dark_bright + << lighting.exposure.speed_bright_dark + << lighting.exposure.center_weight_power; pkt << lighting.volumetric_light_strength << lighting.shadow_tint; pkt << lighting.bloom_intensity << lighting.bloom_strength_factor << From dac9ff70960bc601dde54ccadea37622432c0f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sat, 4 Jan 2025 11:59:36 +0100 Subject: [PATCH 34/40] Remove clipping --- client/shaders/nodes_shader/opengl_fragment.glsl | 5 ----- client/shaders/nodes_shader/opengl_vertex.glsl | 1 - 2 files changed, 6 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index ee75c335d..1730b41ac 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -53,7 +53,6 @@ centroid varying vec2 varTexCoord; centroid varying float nightRatio; #endif varying highp vec3 eyeVec; -varying float nightRatio; varying float nightFactor; #ifdef ENABLE_DYNAMIC_SHADOWS @@ -561,10 +560,6 @@ void main(void) #endif } #endif - - // We clip the color if it gets too bright - col *= min(2.0 / base.a / max(col.r, max(col.g, col.b)), 1.0); - // Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?), // the fog will only be rendered correctly if the last operation before the // clamp() is an addition. Else, the clamp() seems to be ignored. diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index a0a00c646..757d6a4f4 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -47,7 +47,6 @@ centroid varying float nightRatio; varying float area_enable_parallax; varying highp vec3 eyeVec; -varying float nightRatio; varying vec3 sunTint; varying float nightFactor; From ed36ca9c91f95cc9ecd6b1ecfd2ce835947616d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:33:13 +0100 Subject: [PATCH 35/40] Update lua_api.md --- doc/lua_api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index 4c2711baa..a4e6c7c69 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8800,9 +8800,9 @@ child will follow movement and rotation of that bone. but keeping original luma and being symmetrical in terms of saturation (eg. -1 and 1 is the same saturation and luma, but different hues) * This value has no effect on clients who have shaders or post-processing disabled. - * `foliage_translucency` controls the intensity of the foliage translucency effect (default: `2.0`). + * `foliage_translucency` controls the intensity of the foliage translucency effect (default: `1.5`). * This has no effect when dynamic shadows are disabled and on clients who have the "Translucent foliage" effect disabled. - * `specular_intensity` controls the intensity of specular highlights on nodes and liquids (default: `2.0`). + * `specular_intensity` controls the intensity of specular highlights on nodes and liquids (default: `1.5`). * This has no effect when dynamic shadows are disabled and on clients who have the "Translucent foliage" effect disabled. * `shadows` is a table that controls ambient shadows * This has no effect on clients who have the "Dynamic Shadows" effect disabled. From 7fdad3600e3b097a28e73d7ffc246c8707f04d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Fri, 10 Jan 2025 22:23:14 +0100 Subject: [PATCH 36/40] Update opengl_fragment.glsl --- client/shaders/nodes_shader/opengl_fragment.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 1730b41ac..1eea019d5 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -531,7 +531,7 @@ void main(void) col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.5 * brightness_factor; vec3 water_reflect_color = - 2.0 * specular_intensity * sunTint * dayLight * fresnel_factor * max(1.0 - shadow_uncorrected, 0.0) * + 1.5 * specular_intensity * sunTint * dayLight * fresnel_factor * max(1.0 - shadow_uncorrected, 0.0) * mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)); // Sun reflection From 632bd7a5f79935d588fa8cc5282b7e46fe7e4d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Tue, 14 Jan 2025 20:28:54 +0100 Subject: [PATCH 37/40] Apply suggested changes --- .../shaders/minimap_shader/opengl_fragment.glsl | 2 +- client/shaders/nodes_shader/opengl_fragment.glsl | 4 +--- client/shaders/nodes_shader/opengl_vertex.glsl | 4 +++- src/client/game.cpp | 15 +++++++-------- src/lighting.h | 14 ++++++-------- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/client/shaders/minimap_shader/opengl_fragment.glsl b/client/shaders/minimap_shader/opengl_fragment.glsl index d1b7291af..70deceee9 100644 --- a/client/shaders/minimap_shader/opengl_fragment.glsl +++ b/client/shaders/minimap_shader/opengl_fragment.glsl @@ -33,4 +33,4 @@ void main (void) vec4 col = vec4(color.rgb, base.a); col *= varColor; gl_FragColor = vec4(col.rgb, base.a); -} \ No newline at end of file +} diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 1eea019d5..9027c5fa1 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -1,7 +1,4 @@ uniform sampler2D baseTexture; -uniform vec2 texelSize0; - -varying vec3 sunTint; uniform vec3 dayLight; uniform lowp vec4 fogColor; @@ -33,6 +30,7 @@ uniform float animationTimer; varying float f_normal_length; varying vec3 shadow_position; varying float perspective_factor; + varying vec3 sunTint; #endif varying vec3 vNormal; diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index 757d6a4f4..24f669829 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -58,7 +58,9 @@ uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias1; uniform float zPerspectiveBias; -uniform vec3 beta_r0_l; +#ifdef ENABLE_TINTED_SUNLIGHT + uniform vec3 beta_r0_l; +#endif #ifdef ENABLE_DYNAMIC_SHADOWS diff --git a/src/client/game.cpp b/src/client/game.cpp index bd9e525fe..f907744c7 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -221,6 +221,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter }}; float m_user_exposure_compensation; bool m_bloom_enabled; + bool m_color_grading_enabled; CachedPixelShaderSetting m_bloom_intensity_pixel{"bloomIntensity"}; CachedPixelShaderSetting m_bloom_strength_pixel{"bloomStrength"}; CachedPixelShaderSetting m_bloom_radius_pixel{"bloomRadius"}; @@ -278,6 +279,7 @@ public: m_bloom_enabled = g_settings->getBool("enable_bloom"); m_volumetric_light_enabled = g_settings->getBool("enable_volumetric_lighting") && m_bloom_enabled; m_gamma = g_settings->getFloat("secondstage_gamma"); + m_color_grading_enabled = g_settings->getBool("enable_color_grading"); } ~GameGlobalShaderConstantSetter() @@ -368,14 +370,11 @@ public: m_foliage_translucency_pixel.set(&lighting.foliage_translucency, services); m_specular_intensity_pixel.set(&lighting.specular_intensity, services); - if (g_settings->getBool("enable_color_grading")) { + if (m_color_grading_enabled) { const ColorDecisionList& cdl_params = lighting.cdl; - core::vector3df slope = cdl_params.slope; - m_cdl_slope_pixel.set(slope, services); - core::vector3df offset = cdl_params.offset; - m_cdl_offset_pixel.set(offset, services); - core::vector3df power = cdl_params.power; - m_cdl_power_pixel.set(power, services); + m_cdl_slope_pixel.set(cdl_params.slope, services); + m_cdl_offset_pixel.set(cdl_params.offset, services); + m_cdl_power_pixel.set(cdl_params.power, services); } if (m_volumetric_light_enabled) { @@ -422,7 +421,7 @@ public: m_volumetric_light_strength_pixel.set(&volumetric_light_strength, services); } - core::vector3df beta_r0 = lighting.volumetric_beta_r0; + v3f beta_r0 = lighting.volumetric_beta_r0; m_volumetric_beta_r0_vertex.set(beta_r0, services); m_volumetric_beta_r0_pixel.set(beta_r0, services); } diff --git a/src/lighting.h b/src/lighting.h index 5f2436f70..aaf49983f 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -4,9 +4,7 @@ #pragma once #include "SColor.h" -#include "vector3d.h" - -using namespace irr; +#include "irr_v3d.h" /** * Parameters for automatic exposure compensation @@ -35,7 +33,7 @@ struct AutoExposure }; /** - * Parameters for vignette in post + * Parameters for vignette in post-processing * */ struct Vignette { @@ -56,9 +54,9 @@ struct Vignette { * */ struct ColorDecisionList { - core::vector3df slope{1.0, 1.0, 1.0}; - core::vector3df offset{0.0, 0.0, 0.0}; - core::vector3df power{1.0, 1.0, 1.0}; + v3f slope{1.0, 1.0, 1.0}; + v3f offset{0.0, 0.0, 0.0}; + v3f power{1.0, 1.0, 1.0}; }; /** Describes ambient light settings for a player @@ -75,7 +73,7 @@ struct Lighting float specular_intensity{1.5f}; // These factors are calculated based on expected value of scattering factor of 1e-5 // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere - core::vector3df volumetric_beta_r0{ 3.3362176e-01, 8.75378289198826e-01, 1.95342379700656 }; + v3f volumetric_beta_r0{ 3.3362176e-01f, 8.753783e-01f, 1.9534237f }; video::SColor artificial_light_color{ 255, 133, 133, 133 }; video::SColor shadow_tint {255, 0, 0, 0}; float bloom_intensity {0.05f}; From 68a202a5f5718d7678509d4756e63f06ad27cb89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:32:35 +0100 Subject: [PATCH 38/40] Update opengl_fragment.glsl --- client/shaders/nodes_shader/opengl_fragment.glsl | 1 + 1 file changed, 1 insertion(+) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 8a10f34c4..681e7dcf7 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -53,6 +53,7 @@ centroid varying float nightRatio; varying highp vec3 eyeVec; varying float nightFactor; +#ifdef ENABLE_DYNAMIC_SHADOWS #if (MATERIAL_WAVING_LIQUID && defined(ENABLE_WATER_REFLECTIONS)) vec4 perm(vec4 x) { From 282b9ad7c5b37f89c830bfd55f75663e83fd0798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Sun, 13 Apr 2025 14:56:08 +0200 Subject: [PATCH 39/40] Fix stuff --- .../shaders/nodes_shader/opengl_fragment.glsl | 30 ++++++++++++++----- .../shaders/nodes_shader/opengl_vertex.glsl | 3 +- .../shaders/object_shader/opengl_vertex.glsl | 5 +++- doc/lua_api.md | 6 ++-- src/lighting.h | 2 +- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 681e7dcf7..f0159c67c 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -53,6 +53,8 @@ centroid varying float nightRatio; varying highp vec3 eyeVec; varying float nightFactor; +#define PI 3.141592653589 + #ifdef ENABLE_DYNAMIC_SHADOWS #if (MATERIAL_WAVING_LIQUID && defined(ENABLE_WATER_REFLECTIONS)) vec4 perm(vec4 x) @@ -526,7 +528,7 @@ void main(void) vec3 reflection_color = mix(vec3(max(fogColor.r, max(fogColor.g, fogColor.b))), fogColor.rgb, f_shadow_strength); // Sky reflection - col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.5 * brightness_factor; + col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.3 * brightness_factor; vec3 water_reflect_color = 1.5 * specular_intensity * sunTint * dayLight * fresnel_factor * max(1.0 - shadow_uncorrected, 0.0) * @@ -539,14 +541,28 @@ void main(void) #if (defined(ENABLE_NODE_SPECULAR) && !MATERIAL_WATER_REFLECTIONS) // Apply specular to blocks. if (dot(v_LightDirection, vNormal) < 0.0) { - // This intensity is a placeholder and should be replaced by proper specular maps. - float intensity = specular_intensity * min(1.0, length(varColor.rgb * base.rgb)); - const float specular_exponent = 5.0; - const float fresnel_exponent = 4.0; + // This intensity/roughness is a placeholder and should be replaced by proper specular maps. + float intensity = 0.35 * min(1.0, length(varColor.rgb * base.rgb)); + float roughness = 0.5; + + float rms = 1.0 / (1.0 - roughness) - 1.0; + vec3 half_vector = normalize(viewVec + v_LightDirection); + const float F0 = 0.04; + + float HV = dot(viewVec, half_vector); + float HN = dot(fNormal, half_vector); + float VN = dot(viewVec, normalize(fNormal)); + float LN = dot(v_LightDirection, fNormal); + + float HN2 = HN*HN; + + float beckmann = exp((HN2 - 1.0) / (rms * rms * HN2)) / (PI * rms * rms * HN2*HN2); + float geometry = min(min(1.0, 2.0 * HN * VN / HV), 2.0 * HN * LN / HV); + float fresnel_schlick = F0 + (1.0 - F0) * pow(1.0 - HV, 5.0); col.rgb += - sunTint * intensity * f_shadow_factor * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) * - pow(max(dot(reflect_ray, viewVec), 0.0), fresnel_exponent) * pow(1.0 - abs(dot(viewVec, fNormal)), specular_exponent); + sunTint * specular_intensity * f_shadow_factor * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) * + intensity * beckmann * geometry * fresnel_schlick / (VN * LN * PI); } #endif diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index cdadf92b9..e5d480f6c 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -286,7 +286,8 @@ void main(void) (1.0 - mtsmoothstep(0.762, 0.792, f_timeofday)); nightFactor = adj_shadow_strength / f_shadow_strength; #ifdef ENABLE_TINTED_SUNLIGHT - sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), adj_shadow_strength / f_shadow_strength); + float tint_strength = 1.0 - mtsmoothstep(0.792, 0.5, f_timeofday) * mtsmoothstep(0.208, 0.5, f_timeofday); + sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), nightFactor * tint_strength); #endif } } diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index 6dc1b8bda..8ed1c6f67 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -185,7 +185,10 @@ void main(void) adj_shadow_strength = f_shadow_strength * mtsmoothstep(0.208, 0.238, f_timeofday) * (1.0 - mtsmoothstep(0.762, 0.792, f_timeofday)); - sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), adj_shadow_strength / f_shadow_strength); +#ifdef ENABLE_TINTED_SUNLIGHT + float tint_strength = 1.0 - mtsmoothstep(0.792, 0.5, f_timeofday) * mtsmoothstep(0.208, 0.5, f_timeofday); + sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), nightFactor * tint_strength); +#endif } } #endif diff --git a/doc/lua_api.md b/doc/lua_api.md index 60e9705f3..8dc573c0c 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8941,9 +8941,11 @@ child will follow movement and rotation of that bone. (eg. -1 and 1 is the same saturation and luma, but different hues) * This value has no effect on clients who have shaders or post-processing disabled. * `foliage_translucency` controls the intensity of the foliage translucency effect (default: `1.5`). + * Subject to change and can be removed at any time. * This has no effect when dynamic shadows are disabled and on clients who have the "Translucent foliage" effect disabled. - * `specular_intensity` controls the intensity of specular highlights on nodes and liquids (default: `1.5`). - * This has no effect when dynamic shadows are disabled and on clients who have the "Translucent foliage" effect disabled. + * `specular_intensity` controls the intensity of specular highlights on nodes and liquids (default: `0.0`). + * Subject to change and can be removed at any time. + * This has no effect when dynamic shadows are disabled. * `shadows` is a table that controls ambient shadows * This has no effect on clients who have the "Dynamic Shadows" effect disabled. * `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness) diff --git a/src/lighting.h b/src/lighting.h index 216bbfb59..864262aa3 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -77,7 +77,7 @@ struct Lighting float saturation {1.0f}; float volumetric_light_strength {0.0f}; float foliage_translucency{1.5f}; - float specular_intensity{1.5f}; + float specular_intensity{0.0f}; // These factors are calculated based on expected value of scattering factor of 1e-5 // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere v3f volumetric_beta_r0{ 3.3362176e-01f, 8.753783e-01f, 1.9534237f }; From 51cb37570a68cf36becda4a2bc074e3d7d64890a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gef=C3=BCllte=20Taubenbrust?= <72752000+GefullteTaubenbrust2@users.noreply.github.com> Date: Tue, 20 May 2025 21:40:19 +0200 Subject: [PATCH 40/40] Various changes and fixes Hopefully this works, I haven't yet checked in detail for any problems. --- .../shaders/nodes_shader/opengl_fragment.glsl | 2 +- .../shaders/nodes_shader/opengl_vertex.glsl | 8 ++--- .../shaders/object_shader/opengl_vertex.glsl | 30 +++++++++++-------- .../volumetric_light/opengl_fragment.glsl | 7 ++--- doc/lua_api.md | 5 +++- src/client/game.cpp | 25 +++++++--------- src/client/shader.cpp | 3 ++ src/defaultsettings.cpp | 2 -- src/lighting.h | 4 +-- src/log.h | 2 +- src/network/clientpackethandler.cpp | 6 ++-- src/network/networkprotocol.cpp | 4 +-- src/script/lua_api/l_object.cpp | 24 ++++++++++----- src/server.cpp | 6 ++-- 14 files changed, 72 insertions(+), 56 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index f0159c67c..1b9cf6df2 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -539,7 +539,7 @@ void main(void) #endif #if (defined(ENABLE_NODE_SPECULAR) && !MATERIAL_WATER_REFLECTIONS) - // Apply specular to blocks. + // Apply specular to nodes. if (dot(v_LightDirection, vNormal) < 0.0) { // This intensity/roughness is a placeholder and should be replaced by proper specular maps. float intensity = 0.35 * min(1.0, length(varColor.rgb * base.rgb)); diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index e5d480f6c..34fe2c5c7 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -57,7 +57,7 @@ uniform float xyPerspectiveBias1; uniform float zPerspectiveBias; #ifdef ENABLE_TINTED_SUNLIGHT - uniform vec3 beta_r0_l; + uniform vec3 scattering_coefficients; #endif #ifdef ENABLE_DYNAMIC_SHADOWS @@ -155,11 +155,11 @@ float snoise(vec3 p) vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) { // Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham - const float beta_r0 = 1e-5; // Rayleigh scattering beta + const float unit_conversion = 1e-5; // Rayleigh scattering beta const float atmosphere_height = 15000.; // height of the atmosphere in meters // sun/moon light at the ground level, after going through the atmosphere - return exp(-beta_r0_l * beta_r0 * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); + return exp(-scattering_coefficients * unit_conversion * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); } #endif @@ -221,7 +221,7 @@ void main(void) // The alpha gives the ratio of sunlight in the incoming light. nightRatio = 1.0 - color.a; color.rgb = color.rgb * (color.a * dayLight.rgb + - nightRatio * 2.0 * artificialLight.rgb) * 2.0; + nightRatio * max(artificialLight.rgb, vec3(0.0))) * 2.0; color.a = 1.0; // Emphase blue a bit in darker places diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index 8ed1c6f67..f6fe0e4e6 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -42,6 +42,10 @@ uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias1; uniform float zPerspectiveBias; +#ifdef ENABLE_TINTED_SUNLIGHT + uniform vec3 scattering_coefficients; +#endif + #ifdef ENABLE_DYNAMIC_SHADOWS vec4 getRelativePosition(in vec4 position) @@ -90,19 +94,17 @@ float directional_ambient(vec3 normal) return dot(v, vec3(0.670820, 1.000000, 0.836660)); } -vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) -{ - // Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham - const float beta_r0 = 1e-5; // Rayleigh scattering beta +#ifdef ENABLE_TINTED_SUNLIGHT + vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) + { + // Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham + const float unit_conversion = 1e-5; // Rayleigh scattering beta - // These factors are calculated based on expected value of scattering factor of 1e-5 - // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere - const vec3 beta_r0_l = vec3(3.3362176e-01, 8.75378289198826e-01, 1.95342379700656) * beta_r0; // wavelength-dependent scattering - - const float atmosphere_height = 15000.; // height of the atmosphere in meters - // sun/moon light at the ground level, after going through the atmosphere - return exp(-beta_r0_l * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); -} + const float atmosphere_height = 15000.; // height of the atmosphere in meters + // sun/moon light at the ground level, after going through the atmosphere + return exp(-scattering_coefficients * unit_conversion * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); + } +#endif void main(void) { @@ -131,7 +133,7 @@ void main(void) // The alpha gives the ratio of sunlight in the incoming light. nightRatio = 1.0 - color.a; color.rgb = color.rgb * (color.a * dayLight.rgb + - nightRatio * 2.0 * artificialLight.rgb) * 2.0; + nightRatio * max(artificialLight.rgb, vec3(0.0))) * 2.0; color.a = 1.0; // Emphase blue a bit in darker places @@ -174,6 +176,7 @@ void main(void) perspective_factor = pFactor; // The sun rises at 5:00 and sets at 19:00, which corresponds to 5/24=0.208 and 19/24 = 0.792. + float nightFactor = 0.; sunTint = vec3(1.0); if (f_timeofday < 0.208) { adj_shadow_strength = f_shadow_strength * 0.5 * @@ -185,6 +188,7 @@ void main(void) adj_shadow_strength = f_shadow_strength * mtsmoothstep(0.208, 0.238, f_timeofday) * (1.0 - mtsmoothstep(0.762, 0.792, f_timeofday)); + nightFactor = adj_shadow_strength / f_shadow_strength; #ifdef ENABLE_TINTED_SUNLIGHT float tint_strength = 1.0 - mtsmoothstep(0.792, 0.5, f_timeofday) * mtsmoothstep(0.208, 0.5, f_timeofday); sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), nightFactor * tint_strength); diff --git a/client/shaders/volumetric_light/opengl_fragment.glsl b/client/shaders/volumetric_light/opengl_fragment.glsl index 0a2bba60e..cc7045d22 100644 --- a/client/shaders/volumetric_light/opengl_fragment.glsl +++ b/client/shaders/volumetric_light/opengl_fragment.glsl @@ -24,7 +24,7 @@ varying mediump vec2 varTexCoord; centroid varying vec2 varTexCoord; #endif -uniform vec3 beta_r0_l; +uniform vec3 scattering_coefficients; const float far = 1000.; float mapDepth(float depth) @@ -63,12 +63,11 @@ float sampleVolumetricLight(vec2 uv, vec3 lightVec, float rawDepth) vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) { // Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham - const float beta_r0 = 1e-5; // Rayleigh scattering beta + const float unit_conversion = 1e-5; // Rayleigh scattering beta const float atmosphere_height = 15000.; // height of the atmosphere in meters // sun/moon light at the ground level, after going through the atmosphere - - return exp(-beta_r0_l * beta_r0 * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); + return exp(-scattering_coefficients * unit_conversion * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); } vec3 applyVolumetricLight(vec3 color, vec2 uv, float rawDepth) diff --git a/doc/lua_api.md b/doc/lua_api.md index cd138c2d9..a814dd996 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -9029,7 +9029,7 @@ child will follow movement and rotation of that bone. * Currently, bloom `intensity` and `strength_factor` affect volumetric lighting `strength` and vice versa. This behavior is to be changed in the future, do not rely on it. - * `beta_r0`: the scattering coefficient that controls the tint of sunlight during sunrise and sunset. + * `scattering_coefficients`: the scattering coefficients that control the tint of sunlight during sunrise and sunset. * Defaults to { x = 3.3362176e-01, y = 8.75378289198826e-01, z = 1.95342379700656} which is physically accurate. * This may be used to create effects like differently colored sunsets on alien planets. * Setting all components to zero effectively disables tinted sunlight. @@ -9044,6 +9044,9 @@ child will follow movement and rotation of that bone. * `slope`: "Tints" the scene, affects brighter colors more (default: `{x=1.2, y=1.0, z=0.8}`) * `offset`: This can be used to brighten or darken the scene (default: `{x=0.0, y=0.0, z=0.0}`) * `power`: Tints mostly the darker parts of the scene (default: `{x=1.25, y=1.0, z=0.9}`) + * `artificial_light`: is a table that controls the color of artificial light (torches etc.). + * Values should be positive and vaguely around `1.0`, but can be higher or lower. + * Default: `{r=1.04, g=1.04, b=1.04}` * `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`. diff --git a/src/client/game.cpp b/src/client/game.cpp index f0d89548b..6babe0dcb 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -217,7 +217,6 @@ class GameGlobalShaderUniformSetter : public IShaderUniformSetter }}; float m_user_exposure_compensation; bool m_bloom_enabled; - bool m_color_grading_enabled; CachedPixelShaderSetting m_bloom_intensity_pixel{"bloomIntensity"}; CachedPixelShaderSetting m_bloom_strength_pixel{"bloomStrength"}; CachedPixelShaderSetting m_bloom_radius_pixel{"bloomRadius"}; @@ -234,9 +233,9 @@ class GameGlobalShaderUniformSetter : public IShaderUniformSetter CachedPixelShaderSetting m_volumetric_light_strength_pixel{"volumetricLightStrength"}; CachedPixelShaderSetting - m_volumetric_beta_r0_pixel{ "beta_r0_l" }; + m_atmospheric_scattering_coefficients_pixel{ "scattering_coefficients" }; CachedVertexShaderSetting - m_volumetric_beta_r0_vertex{ "beta_r0_l" }; + m_atmospheric_scattering_coefficients_vertex{ "scattering_coefficients" }; CachedPixelShaderSetting m_cdl_slope_pixel{"cdl_slope"}; CachedPixelShaderSetting m_cdl_offset_pixel{"cdl_offset"}; CachedPixelShaderSetting m_cdl_power_pixel{"cdl_power"}; @@ -275,7 +274,6 @@ public: m_bloom_enabled = g_settings->getBool("enable_bloom"); m_volumetric_light_enabled = g_settings->getBool("enable_volumetric_lighting") && m_bloom_enabled; m_gamma = g_settings->getFloat("secondstage_gamma"); - m_color_grading_enabled = g_settings->getBool("enable_color_grading"); } ~GameGlobalShaderUniformSetter() @@ -356,12 +354,10 @@ public: m_foliage_translucency_pixel.set(&lighting.foliage_translucency, services); m_specular_intensity_pixel.set(&lighting.specular_intensity, services); - if (m_color_grading_enabled) { - const ColorDecisionList& cdl_params = lighting.cdl; - m_cdl_slope_pixel.set(cdl_params.slope, services); - m_cdl_offset_pixel.set(cdl_params.offset, services); - m_cdl_power_pixel.set(cdl_params.power, services); - } + const ColorDecisionList& cdl_params = lighting.cdl; + m_cdl_slope_pixel.set(cdl_params.slope, services); + m_cdl_offset_pixel.set(cdl_params.offset, services); + m_cdl_power_pixel.set(cdl_params.power, services); if (m_volumetric_light_enabled) { // Map directional light to screen space @@ -407,9 +403,9 @@ public: m_volumetric_light_strength_pixel.set(&volumetric_light_strength, services); } - v3f beta_r0 = lighting.volumetric_beta_r0; - m_volumetric_beta_r0_vertex.set(beta_r0, services); - m_volumetric_beta_r0_pixel.set(beta_r0, services); + v3f scattering_coefficients = lighting.scattering_coefficients; + m_atmospheric_scattering_coefficients_vertex.set(scattering_coefficients, services); + m_atmospheric_scattering_coefficients_pixel.set(scattering_coefficients, services); } void onSetMaterial(const video::SMaterial &material) override @@ -504,8 +500,9 @@ public: #undef PROVIDE bool enable_waving_water = g_settings->getBool("enable_waving_water"); + bool enable_water_reflections = g_settings->getBool("enable_water_reflections"); constants["ENABLE_WAVING_WATER"] = enable_waving_water ? 1 : 0; - if (enable_waving_water) { + if (enable_waving_water || enable_water_reflections) { constants["WATER_WAVE_HEIGHT"] = g_settings->getFloat("water_wave_height"); constants["WATER_WAVE_LENGTH"] = g_settings->getFloat("water_wave_length"); constants["WATER_WAVE_SPEED"] = g_settings->getFloat("water_wave_speed"); diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 16dac3d87..3116ed236 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -225,6 +225,9 @@ public: float shadow_soft_radius = std::max(1.f, g_settings->getFloat("shadow_soft_radius")); constants["SOFTSHADOWRADIUS"] = shadow_soft_radius; + + if (g_settings->getBool("enable_sun_tint")) + constants["ENABLE_TINTED_SUNLIGHT"] = 1; } if (g_settings->getBool("enable_bloom")) { diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index f61f4c4c6..143d1eafe 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -333,7 +333,6 @@ void set_default_settings() settings->setDefault("enable_waving_plants", "false"); settings->setDefault("exposure_compensation", "0.0"); settings->setDefault("enable_auto_exposure", "false"); - settings->setDefault("enable_color_grading", "false"); settings->setDefault("secondstage_gamma", "1.6"); settings->setDefault("debanding", "true"); settings->setDefault("antialiasing", "none"); @@ -343,7 +342,6 @@ void set_default_settings() settings->setDefault("enable_volumetric_depth_attenuation", "false"); settings->setDefault("enable_water_reflections", "false"); settings->setDefault("enable_translucent_foliage", "false"); - settings->setDefault("enable_node_specular", "false"); settings->setDefault("enable_tinted_fog", "false"); // Effects Shadows diff --git a/src/lighting.h b/src/lighting.h index 864262aa3..8ec935b26 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -80,8 +80,8 @@ struct Lighting float specular_intensity{0.0f}; // These factors are calculated based on expected value of scattering factor of 1e-5 // for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere - v3f volumetric_beta_r0{ 3.3362176e-01f, 8.753783e-01f, 1.9534237f }; - video::SColor artificial_light_color{ 255, 133, 133, 133 }; + v3f scattering_coefficients{ 3.3362176e-01f, 8.753783e-01f, 1.9534237f }; + video::SColorf artificial_light_color{ 1.0f, 1.04f, 1.04f, 1.04f }; video::SColor shadow_tint {255, 0, 0, 0}; float bloom_intensity {0.05f}; float bloom_strength_factor {1.0f}; diff --git a/src/log.h b/src/log.h index 0e34b2c83..599c253e4 100644 --- a/src/log.h +++ b/src/log.h @@ -62,7 +62,7 @@ private: // These calls explicitly use the templated version of operator<<, // so that they won't use the overloads created by ADD_NULL_CHECK. if (arg == nullptr) - return this->operator<< ("(null)"); + return this->operator<< ((const char*) ("(null)")); else return this->operator<< (std::forward(arg)); } diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 18e35e3f2..2d7421190 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1795,8 +1795,10 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt) >> lighting.bloom_radius; } if (pkt->getRemainingBytes() >= 72) { - *pkt >> lighting.artificial_light_color; - *pkt >> lighting.volumetric_beta_r0; + *pkt >> lighting.artificial_light_color.r + >> lighting.artificial_light_color.g + >> lighting.artificial_light_color.b; + *pkt >> lighting.scattering_coefficients; *pkt >> lighting.vignette.dark >> lighting.vignette.bright >> lighting.vignette.power; diff --git a/src/network/networkprotocol.cpp b/src/network/networkprotocol.cpp index 9bf2fa7eb..020b939f3 100644 --- a/src/network/networkprotocol.cpp +++ b/src/network/networkprotocol.cpp @@ -61,10 +61,10 @@ [scheduled bump for 5.10.0] PROTOCOL VERSION 47 Add particle blend mode "clip" - Add artificial light color, beta_r0, vignette, specular intensity, foliage translucency and cdl parameters to Lighting packets [scheduled bump for 5.11.0] PROTOCOL VERSION 48 - Add compression to some existing packets + Add compression to some existing packets, artificial light color, scattering_coefficients, + vignette, specular intensity, foliage translucency and cdl parameters to Lighting packets [scheduled bump for 5.12.0] */ diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 1ee00ae39..21cea5436 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2660,8 +2660,10 @@ int ObjectRef::l_set_lighting(lua_State *L) lighting = player->getLighting(); lua_getfield(L, 2, "artificial_light"); - if (!lua_isnil(L, -1)) { - read_color(L, -1, &lighting.artificial_light_color); + if (lua_istable(L, -1)) { + getfloatfield(L, -1, "r", lighting.artificial_light_color.r); + getfloatfield(L, -1, "g", lighting.artificial_light_color.g); + getfloatfield(L, -1, "b", lighting.artificial_light_color.b); } lua_pop(L, 1); // artificial_light @@ -2694,11 +2696,11 @@ int ObjectRef::l_set_lighting(lua_State *L) getfloatfield(L, -1, "strength", lighting.volumetric_light_strength); lighting.volumetric_light_strength = rangelim(lighting.volumetric_light_strength, 0.0f, 1.0f); - lua_getfield(L, -1, "beta_r0"); + lua_getfield(L, -1, "scattering_coefficients"); if (!lua_isnil(L, -1)) { - lighting.volumetric_beta_r0 = read_v3f(L, -1); + lighting.scattering_coefficients = read_v3f(L, -1); } - lua_pop(L, 1); // beta_r0 + lua_pop(L, 1); // scattering_coefficients } lua_pop(L, 1); // volumetric_light @@ -2752,7 +2754,13 @@ int ObjectRef::l_get_lighting(lua_State *L) const Lighting &lighting = player->getLighting(); lua_newtable(L); // result - push_ARGB8(L, lighting.artificial_light_color); + lua_newtable(L); // artificial_light + lua_pushnumber(L, lighting.artificial_light_color.r); + lua_setfield(L, -2, "r"); + lua_pushnumber(L, lighting.artificial_light_color.g); + lua_setfield(L, -2, "g"); + lua_pushnumber(L, lighting.artificial_light_color.b); + lua_setfield(L, -2, "b"); lua_setfield(L, -2, "artificial_light"); lua_pushnumber(L, lighting.foliage_translucency); lua_setfield(L, -2, "foliage_translucency"); @@ -2783,8 +2791,8 @@ int ObjectRef::l_get_lighting(lua_State *L) lua_newtable(L); // "volumetric_light" lua_pushnumber(L, lighting.volumetric_light_strength); lua_setfield(L, -2, "strength"); - push_v3f(L, lighting.volumetric_beta_r0); - lua_setfield(L, -2, "beta_r0"); + push_v3f(L, lighting.scattering_coefficients); + lua_setfield(L, -2, "scattering_coefficients"); lua_setfield(L, -2, "volumetric_light"); lua_newtable(L); // "bloom" lua_pushnumber(L, lighting.bloom_intensity); diff --git a/src/server.cpp b/src/server.cpp index 6c0600b6b..c8ad9660a 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1947,8 +1947,10 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) pkt << lighting.volumetric_light_strength << lighting.shadow_tint; pkt << lighting.bloom_intensity << lighting.bloom_strength_factor << lighting.bloom_radius; - pkt << lighting.artificial_light_color; - pkt << lighting.volumetric_beta_r0; + pkt << lighting.artificial_light_color.r + << lighting.artificial_light_color.g + << lighting.artificial_light_color.b; + pkt << lighting.scattering_coefficients; pkt << lighting.vignette.dark << lighting.vignette.bright << lighting.vignette.power;