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();