diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 610144067e0a3..002709d881304 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -404,6 +404,11 @@ enable_clouds (Clouds) bool true # Requires: enable_clouds enable_3d_clouds (3D clouds) bool true +# Use smooth cloud shading. +# +# Requires: enable_3d_clouds, enable_clouds +soft_clouds (Soft clouds) bool false + [**Filtering and Antialiasing] # Use mipmaps when scaling textures. May slightly increase performance, @@ -506,6 +511,11 @@ 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. +# +# Requires: shaders, enable_waving_water, enable_dynamic_shadows +enable_water_reflections (Liquid reflections) bool false + [**Dynamic shadows] # Set to true to enable Shadow Mapping. @@ -610,6 +620,16 @@ 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 +# 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 @@ -662,6 +682,36 @@ 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] + +# Simulate translucency when looking at foliage in the sunlight. +# +# Requires: enable_shaders, enable_dynamic_shadows +enable_translucent_foliage (Translucent foliage) bool false + +# Apply crude bump maps to nodes. It is recommended to use a tilted sun orbit to go with this (Sky Body Orbit Tilt). +# +# Requires: enable_shaders, enable_dynamic_shadows +enable_bumpmaps (Bump maps) bool false + +# Apply reflections to nodes. +# +# Requires: enable_shaders, enable_dynamic_shadows +enable_node_reflections (Node reflections) bool false + +# Tint sunlight orange during dusk and dawn. +# +# Requires: enable_shaders +tinted_sunlight (Tinted sunlight) bool false + +# The color of light that sources like lamps, torches etc. give off. +# - default: Neutral, white light. +# - medium: Slightly warmer color than default. +# - warm: Warm (yellowish-orangy) light. +# +# Requires: enable_shaders +artificial_light (Artificial light color) enum default default,medium,warm + [*Audio] # Volume of all sounds. diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 46977b147b02c..0f3dde07bbd9d 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; @@ -20,6 +28,7 @@ uniform float animationTimer; uniform vec4 CameraPos; uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias1; + uniform vec3 shadow_tint; varying float adj_shadow_strength; varying float cosLight; @@ -46,7 +55,75 @@ centroid varying vec2 varTexCoord; varying highp vec3 eyeVec; varying float nightRatio; +varying vec3 viewVec; + #ifdef ENABLE_DYNAMIC_SHADOWS +vec4 perm(vec4 x) +{ + return mod(((x * 34.0) + 1.0) * x, 289.0); +} + +#if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS)) || defined(ENABLE_BUMPMAPS) +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); +} + +// Corresponding gradient of snoise +vec3 gnoise(vec3 p){ + vec3 a = floor(p); + vec3 d = p - a; + vec3 dd = 6.0 * d * (1.0 - d); + 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); + + vec4 dz1 = (o2 - o1) * dd.z; + vec2 dz2 = dz1.yw * d.x + dz1.xz * (1.0 - d.x); + + vec2 dx = (o3.yw - o3.xz) * dd.x; + + return vec3( + dx.y * d.y + dx.x * (1. - d.y), + (o4.y - o4.x) * dd.y, + dz2.y * d.y + dz2.x * (1. - d.y) + ); +} + +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; +} +#endif // assuming near is always 1.0 float getLinearDepth() @@ -378,6 +455,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 +489,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; @@ -414,12 +511,18 @@ void main(void) // Power ratio was measured on torches in MTG (brightness = 14). float adjusted_night_ratio = pow(max(0.0, nightRatio), 0.6); + float shadow_uncorrected = shadow_int; + // 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); + +#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES) + shadow_uncorrected = mix(shadow_int, shadow_uncorrected, clamp(distance_rate * 4.0 - 3.0, 0.0, 1.0)); +#endif } shadow_int *= f_adj_shadow_strength; @@ -428,8 +531,62 @@ void main(void) col.rgb = adjusted_night_ratio * col.rgb + // artificial light (1.0 - adjusted_night_ratio) * ( // natural light - col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) + // filtered texture color + col.rgb * (1.0 - shadow_int * (1.0 - shadow_color) * (1.0 - shadow_tint)) + // filtered texture color dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight + + + vec3 reflect_ray = -normalize(v_LightDirection - fNormal * dot(v_LightDirection, fNormal) * 2.0); + +#if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS)) + 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; + wavePos.z /= WATER_WAVE_LENGTH * 2.0; + + // This is an analogous method to the bumpmap, except we get the gradient information directly from 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); + float fresnel_factor = dot(fNormal, viewVec); + + float brightness_factor = 1.0 - adjusted_night_ratio; + + // 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); + col.rgb *= 0.5; + 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; + 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); + + // 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.5, 1.0, 400.0); + col.rgb += water_reflect_color * f_adj_shadow_strength * brightness_factor; +#endif + +#if (defined(ENABLE_NODE_REFLECTIONS) && !defined(MATERIAL_WAVING_LIQUID)) + +#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES) +#define REFLECTION_INTENSITY 2.0 +#elif (defined(MATERIAL_WAVING_LIQUID)) +#define REFLECTION_INTENSITY 0.0 +#else +#define REFLECTION_INTENSITY 1.0 +#endif + // Apply reflections to blocks. + if (dot(v_LightDirection, vNormal) < 0.0) { + col.rgb += + 1.5 * dayLight * f_adj_shadow_strength * REFLECTION_INTENSITY * (1.0 - nightRatio) * + pow(max(dot(reflect_ray, viewVec), 0.0), 4.0) * pow(1.0 - abs(dot(viewVec, fNormal)), 5.0) * + (1.0 - shadow_uncorrected) * (1.0 - base.r); + } +#endif + +#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES) && defined(ENABLE_TRANSLUCENT_FOLIAGE) + // Simulate translucent foliage. + col.rgb += 3.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); +#endif } #endif @@ -444,7 +601,9 @@ void main(void) // Note: clarity = (1 - fogginess) float clarity = clamp(fogShadingParameter - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - col = mix(fogColor, col, clarity); + float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b); + if (fogColorMax < 0.0000001) fogColorMax = 1.0; + col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity); col = vec4(col.rgb, base.a); gl_FragData[0] = col; diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index d96164d76acdc..3816fc07590e4 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -1,6 +1,7 @@ uniform mat4 mWorld; // Color of the light emitted by the sun. uniform vec3 dayLight; +uniform vec3 eyePosition; // The cameraOffset is the current center of the visible world. uniform highp vec3 cameraOffset; @@ -43,10 +44,11 @@ centroid varying vec2 varTexCoord; varying float area_enable_parallax; +varying vec3 viewVec; 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; @@ -231,6 +233,8 @@ void main(void) #else vec4 shadow_pos = pos; #endif + viewVec = normalize(worldPosition + cameraOffset - eyePosition); + vec3 nNormal; f_normal_length = length(vNormal); @@ -261,14 +265,14 @@ void main(void) if (f_timeofday < 0.2) { adj_shadow_strength = f_shadow_strength * 0.5 * - (1.0 - mtsmoothstep(0.18, 0.2, f_timeofday)); + (1.0 - mtsmoothstep(0.15, 0.2, f_timeofday)); } else if (f_timeofday >= 0.8) { adj_shadow_strength = f_shadow_strength * 0.5 * - mtsmoothstep(0.8, 0.83, f_timeofday); + mtsmoothstep(0.8, 0.85, 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.18, 0.25, f_timeofday) * + (1.0 - mtsmoothstep(0.75, 0.8, f_timeofday)); } } #endif diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 2b8af3fa9d6c0..7bd0047571035 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -20,6 +20,7 @@ uniform float animationTimer; uniform vec4 CameraPos; uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias1; + uniform vec3 shadow_tint; varying float adj_shadow_strength; varying float cosLight; @@ -432,7 +433,7 @@ void main(void) col.rgb = adjusted_night_ratio * col.rgb + // artificial light (1.0 - adjusted_night_ratio) * ( // natural light - col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) + // filtered texture color + col.rgb * (1.0 - shadow_int * (1.0 - shadow_color) * (1.0 - shadow_tint)) + // filtered texture color dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight } #endif @@ -448,7 +449,9 @@ void main(void) // Note: clarity = (1 - fogginess) float clarity = clamp(fogShadingParameter - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - col = mix(fogColor, col, clarity); + float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b); + if (fogColorMax < 0.0000001) fogColorMax = 1.0; + col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity); col = vec4(col.rgb, base.a); gl_FragData[0] = col; diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index d5a434da52dd2..420a90b3147be 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; diff --git a/client/shaders/second_stage/opengl_fragment.glsl b/client/shaders/second_stage/opengl_fragment.glsl index 3b0d4c844aa79..52eb4bb2235fa 100644 --- a/client/shaders/second_stage/opengl_fragment.glsl +++ b/client/shaders/second_stage/opengl_fragment.glsl @@ -68,7 +68,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); @@ -76,7 +75,7 @@ vec4 applyToneMapping(vec4 color) //vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W)); vec3 whiteScale = vec3(1.036015346); color.rgb *= whiteScale; - return vec4(pow(color.rgb, vec3(1.0 / gamma)), color.a); + return color; } #endif @@ -135,20 +134,29 @@ void main(void) color.rgb = clamp(color.rgb, vec3(0.), vec3(1.)); - // return to sRGB colorspace (approximate) - color.rgb = pow(color.rgb, vec3(1.0 / 2.2)); - #ifdef ENABLE_BLOOM_DEBUG if (uv.x > 0.5 || uv.y > 0.5) #endif { + + #ifdef ENABLE_VIGNETTE + color.rgb *= pow(1.0 - length(uv - vec2(0.5)) * 1.4, 0.9) + 0.1; + #endif + #if ENABLE_TONE_MAPPING color = applyToneMapping(color); #endif color.rgb = applySaturation(color.rgb, saturation); + +#ifdef ENABLE_COLOR_GRADING + color.rgb = pow(color.rgb * vec3(1.5, 1.0, 0.7), vec3(1.35, 1.0, 0.8)); +#endif } + // return to sRGB colorspace (approximate) + color.rgb = pow(color.rgb, vec3(1.0 / 2.2)); + #ifdef ENABLE_DITHERING // Apply dithering just before quantisation color.rgb += screen_space_dither(gl_FragCoord.xy); diff --git a/client/shaders/volumetric_light/opengl_fragment.glsl b/client/shaders/volumetric_light/opengl_fragment.glsl index 9ed5fa9ba7e3e..5de0f185f8952 100644 --- a/client/shaders/volumetric_light/opengl_fragment.glsl +++ b/client/shaders/volumetric_light/opengl_fragment.glsl @@ -46,7 +46,7 @@ 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; } - return result / samples; + return result / samples * pow(texture2D(depthmap, uv).r, 128.0); } vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) diff --git a/doc/lua_api.md b/doc/lua_api.md index 796a0f39eea5b..096cad0e3c778 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8332,6 +8332,8 @@ child will follow movement and rotation of that bone. * `thickness`: cloud thickness in nodes (default `16`) * `speed`: 2D cloud speed + direction in nodes per second (default `{x=0, z=-2}`). + * `shadow`: shadow color, applied to the base of the cloud + (default `{a=255, r=204, g=204, b=204}`). * `get_clouds()`: returns a table with the current cloud parameters as in `set_clouds`. * `override_day_night_ratio(ratio or nil)` diff --git a/src/client/clientevent.h b/src/client/clientevent.h index 243a945969595..d78288116a378 100644 --- a/src/client/clientevent.h +++ b/src/client/clientevent.h @@ -136,6 +136,7 @@ struct ClientEvent f32 density; u32 color_bright; u32 color_ambient; + u32 color_shadow; f32 height; f32 thickness; f32 speed_x; diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 3ab504371010f..2376686a54a64 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -69,6 +69,8 @@ Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc, readSettings(); g_settings->registerChangedCallback("enable_3d_clouds", &cloud_3d_setting_changed, this); + g_settings->registerChangedCallback("soft_clouds", + &cloud_3d_setting_changed, this); updateBox(); @@ -80,6 +82,8 @@ Clouds::~Clouds() { g_settings->deregisterChangedCallback("enable_3d_clouds", &cloud_3d_setting_changed, this); + g_settings->deregisterChangedCallback("soft_clouds", + &cloud_3d_setting_changed, this); } void Clouds::OnRegisterSceneNode() @@ -145,15 +149,19 @@ void Clouds::updateMesh() // shader mixes the base color, set via EmissiveColor c_top_f = c_side_1_f = c_side_2_f = c_bottom_f = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); } - c_side_1_f.r *= 0.95f; - c_side_1_f.g *= 0.95f; - c_side_1_f.b *= 0.95f; - c_side_2_f.r *= 0.90f; - c_side_2_f.g *= 0.90f; - c_side_2_f.b *= 0.90f; - c_bottom_f.r *= 0.80f; - c_bottom_f.g *= 0.80f; - c_bottom_f.b *= 0.80f; + + video::SColorf shadow = m_params.color_shadow; + + c_side_1_f.r *= shadow.r * 0.33f + 0.66f; + c_side_1_f.g *= shadow.g * 0.33f + 0.66f; + c_side_1_f.b *= shadow.b * 0.33f + 0.66f; + c_side_2_f.r *= shadow.r * 0.66f + 0.33f; + c_side_2_f.g *= shadow.g * 0.66f + 0.33f; + c_side_2_f.b *= shadow.b * 0.66f + 0.33f; + c_bottom_f.r *= shadow.r; + c_bottom_f.g *= shadow.g; + c_bottom_f.b *= shadow.b; + video::SColor c_top = c_top_f.toSColor(); video::SColor c_side_1 = c_side_1_f.toSColor(); video::SColor c_side_2 = c_side_2_f.toSColor(); @@ -223,94 +231,131 @@ void Clouds::updateMesh() const f32 ry = m_enable_3d ? m_params.thickness * BS : 0.0f; const f32 rz = cloud_size / 2; - for(u32 i = 0; i < num_faces_to_draw; i++) + 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); + 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)) { u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); - if(grid[j]) + if (grid[j]) continue; } - for (video::S3DVertex &vertex : v) { - vertex.Color = c_side_1; - vertex.Normal.set(0,0,-1); + 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; } - 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); + 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]) + u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i); + if (grid[j]) continue; } - for (video::S3DVertex &vertex : v) { - vertex.Color = c_side_2; - vertex.Normal.set(1,0,0); + 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); + 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]) + if (grid[j]) continue; } - for (video::S3DVertex &vertex : v) { - vertex.Color = c_side_1; - vertex.Normal.set(0,0,-1); + 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; } - v[0].Pos.set( rx, ry, rz); + 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); + 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]) + if (INAREA(xi - 1, zi, m_cloud_radius_i)) { + u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i); + if (grid[j]) continue; } - for (video::S3DVertex &vertex : v) { - vertex.Color = c_side_2; - vertex.Normal.set(-1,0,0); + 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); + 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) { + for (video::S3DVertex& vertex : v) { vertex.Color = c_bottom; - vertex.Normal.set(0,-1,0); + 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; } v3f pos(p0.X, m_params.height * BS, p0.Y); - for (video::S3DVertex &vertex : v) { + for (video::S3DVertex& vertex : v) { vertex.Pos += pos; mb->Vertices.push_back(vertex); } diff --git a/src/client/clouds.h b/src/client/clouds.h index 23273a3c9c6af..3e05f09cb3916 100644 --- a/src/client/clouds.h +++ b/src/client/clouds.h @@ -101,6 +101,11 @@ class Clouds : public scene::ISceneNode m_params.color_ambient = color_ambient; } + void setColorShadow(video::SColor color_shadow) + { + m_params.color_shadow = color_shadow; + } + void setHeight(float height) { if (m_params.height == height) diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index f7cb7b473e1e0..231b6a8547426 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -713,8 +713,9 @@ void MapblockMeshGenerator::drawLiquidSides() if (data->m_smooth_lighting) cur_node.color = blendLightColor(pos); pos += cur_node.origin; - vertices[j] = video::S3DVertex(pos.X, pos.Y, pos.Z, 0, 0, 0, cur_node.color, vertex.u, v); + vertices[j] = video::S3DVertex(pos.X, pos.Y, pos.Z, face.dir.X, face.dir.Y, face.dir.Z, cur_node.color, vertex.u, v); }; + collector->append(cur_liquid.tile, vertices, 4, quad_indices, 6); } } @@ -775,6 +776,7 @@ void MapblockMeshGenerator::drawLiquidTop() vertex.TCoords += tcoord_center; vertex.TCoords += tcoord_translate; + vertex.Normal = v3f(dx, 1., dz).normalize(); } std::swap(vertices[0].TCoords, vertices[2].TCoords); diff --git a/src/client/game.cpp b/src/client/game.cpp index d89b6639c52c9..7535c88398f0e 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -382,6 +382,9 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_animation_timer_delta_pixel{"animationTimerDelta"}; CachedPixelShaderSetting m_day_light{"dayLight"}; + CachedPixelShaderSetting m_artificial_light{"artificialLight"}; + 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"}; @@ -482,6 +485,10 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter 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); @@ -569,6 +576,11 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter float volumetric_light_strength = lighting.volumetric_light_strength; m_volumetric_light_strength_pixel.set(&volumetric_light_strength, services); } + + std::string artificial_light_enum = g_settings->get("artificial_light"); + if (artificial_light_enum == "warm") m_artificial_light.set(v3f( 1.2, 0.95, 0.8 ), services); + else if (artificial_light_enum == "medium") m_artificial_light.set(v3f(1.1, 1., 0.95), services); + else m_artificial_light.set(v3f(1.04), services); } void onSetMaterial(const video::SMaterial &material) override @@ -1423,7 +1435,7 @@ void Game::copyServerClientCache() { // It would be possible to let the client directly read the media files // from where the server knows they are. But aside from being more complicated - // it would also *not* fill the media cache and cause slower joining of + // it would also *not* fill the media cache and cause slower joining of // remote servers. // (Imagine that you launch a game once locally and then connect to a server.) @@ -3126,6 +3138,7 @@ void Game::handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation * clouds->setDensity(event->cloud_params.density); clouds->setColorBright(video::SColor(event->cloud_params.color_bright)); clouds->setColorAmbient(video::SColor(event->cloud_params.color_ambient)); + clouds->setColorShadow(video::SColor(event->cloud_params.color_shadow)); clouds->setHeight(event->cloud_params.height); clouds->setThickness(event->cloud_params.thickness); clouds->setSpeed(v2f(event->cloud_params.speed_x, event->cloud_params.speed_y)); @@ -4248,6 +4261,7 @@ void Game::updateShadows() bool is_day = timeoftheday > 0.25 && timeoftheday < 0.75; bool is_shadow_visible = is_day ? sky->getSunVisible() : sky->getMoonVisible(); shadow->setShadowIntensity(is_shadow_visible ? client->getEnv().getLocalPlayer()->getLighting().shadow_intensity : 0.0f); + shadow->setShadowTint(client->getEnv().getLocalPlayer()->getLighting().shadow_tint); timeoftheday = std::fmod(timeoftheday + 0.75f, 0.5f) + 0.25f; const float offset_constant = 10000.0f; diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 1d74b70cbda5c..2a12106b37200 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -282,11 +282,25 @@ u16 getSmoothLightTransparent(const v3s16 &p, const v3s16 &corner, MeshMakeData } void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio){ - f32 rg = daynight_ratio / 1000.0f - 0.04f; - f32 b = (0.98f * daynight_ratio) / 1000.0f + 0.078f; - sunlight->r = rg; - sunlight->g = rg; - sunlight->b = b; + if (g_settings->getBool("tinted_sunlight")) { + f32 daynight_ratio_float = (daynight_ratio - 175) / 825.f; + sunlight->r = 1.f; + sunlight->g = core::clamp(std::pow(daynight_ratio_float, 0.7f), 0.f, 1.f); + sunlight->b = core::clamp(daynight_ratio_float * 1.5f - 0.5f, 0.f, 1.f); + + f32 fade_factor = core::clamp((0.6f - daynight_ratio_float) / 0.6f, 0.f, 1.f); + + sunlight->r = sunlight->r * (1.f - fade_factor) + 0.171f * fade_factor; + sunlight->g = sunlight->g * (1.f - fade_factor) + 0.171f * fade_factor; + sunlight->b = sunlight->b * (1.f - fade_factor) + 0.253f * fade_factor; + } + else { + f32 rg = daynight_ratio / 1000.0f - 0.04f; + f32 b = (0.98f * daynight_ratio) / 1000.0f + 0.078f; + sunlight->r = rg; + sunlight->g = rg; + sunlight->b = b; + } } void final_color_blend(video::SColor *result, diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 4f84ecbe79e30..94a63862a17d3 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -688,6 +688,18 @@ 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_water_reflections")) + shaders_header << "#define ENABLE_WATER_REFLECTIONS 1\n"; + + if (g_settings->getBool("enable_translucent_foliage")) + shaders_header << "#define ENABLE_TRANSLUCENT_FOLIAGE 1\n"; + + if (g_settings->getBool("enable_bumpmaps")) + shaders_header << "#define ENABLE_BUMPMAPS 1\n"; + + if (g_settings->getBool("enable_node_reflections")) + shaders_header << "#define ENABLE_NODE_REFLECTIONS 1\n"; + s32 shadow_filter = g_settings->getS32("shadow_filters"); shaders_header << "#define SHADOW_FILTER " << shadow_filter << "\n"; @@ -706,6 +718,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/client/shadows/dynamicshadowsrender.cpp b/src/client/shadows/dynamicshadowsrender.cpp index 08cdca0ad9fa7..74f498a4b69c1 100644 --- a/src/client/shadows/dynamicshadowsrender.cpp +++ b/src/client/shadows/dynamicshadowsrender.cpp @@ -187,6 +187,11 @@ void ShadowRenderer::setShadowIntensity(float shadow_intensity) disable(); } +void ShadowRenderer::setShadowTint(video::SColor shadow_tint) +{ + m_shadow_tint = shadow_tint; +} + void ShadowRenderer::addNodeToShadowList( scene::ISceneNode *node, E_SHADOW_MODE shadowMode) { diff --git a/src/client/shadows/dynamicshadowsrender.h b/src/client/shadows/dynamicshadowsrender.h index fc139e28b7009..7c7e05fbafe2d 100644 --- a/src/client/shadows/dynamicshadowsrender.h +++ b/src/client/shadows/dynamicshadowsrender.h @@ -93,9 +93,11 @@ class ShadowRenderer bool is_active() const { return m_shadows_enabled && shadowMapTextureFinal != nullptr; } void setTimeOfDay(float isDay) { m_time_day = isDay; }; void setShadowIntensity(float shadow_intensity); + void setShadowTint(video::SColor shadow_intensity); s32 getShadowSamples() const { return m_shadow_samples; } float getShadowStrength() const { return m_shadows_enabled ? m_shadow_strength : 0.0f; } + video::SColor getShadowTint() const { return m_shadow_tint; } float getTimeOfDay() const { return m_time_day; } f32 getPerspectiveBiasXY() { return m_perspective_bias_xy; } @@ -130,6 +132,7 @@ class ShadowRenderer std::vector m_shadow_node_array; float m_shadow_strength; + video::SColor m_shadow_tint{255, 0, 38, 128}; float m_shadow_strength_gamma; float m_shadow_map_max_distance; float m_shadow_map_texture_size; diff --git a/src/client/shadows/shadowsshadercallbacks.cpp b/src/client/shadows/shadowsshadercallbacks.cpp index 32d3e36bed553..fc4f7318634ee 100644 --- a/src/client/shadows/shadowsshadercallbacks.cpp +++ b/src/client/shadows/shadowsshadercallbacks.cpp @@ -40,6 +40,9 @@ void ShadowConstantSetter::onSetConstants(video::IMaterialRendererServices *serv f32 ShadowStrength = shadow->getShadowStrength(); m_shadow_strength.set(&ShadowStrength, services); + video::SColor ShadowTint = shadow->getShadowTint(); + m_shadow_tint.set(ShadowTint, services); + f32 timeOfDay = shadow->getTimeOfDay(); m_time_of_day.set(&timeOfDay, services); diff --git a/src/client/shadows/shadowsshadercallbacks.h b/src/client/shadows/shadowsshadercallbacks.h index af83f021ef136..beac25d72c0b9 100644 --- a/src/client/shadows/shadowsshadercallbacks.h +++ b/src/client/shadows/shadowsshadercallbacks.h @@ -31,6 +31,7 @@ class ShadowConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_light_direction{"v_LightDirection"}; CachedPixelShaderSetting m_texture_res{"f_textureresolution"}; CachedPixelShaderSetting m_shadow_strength{"f_shadow_strength"}; + CachedPixelShaderSetting m_shadow_tint{ "shadow_tint" }; CachedPixelShaderSetting m_time_of_day{"f_timeofday"}; CachedPixelShaderSetting m_shadowfar{"f_shadowfar"}; CachedPixelShaderSetting m_camera_pos{"CameraPos"}; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 0907c4c6dceeb..256b1f8fb5e59 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -207,6 +207,8 @@ void set_default_settings() settings->setDefault("connected_glass", "false"); settings->setDefault("smooth_lighting", "true"); settings->setDefault("performance_tradeoffs", "false"); + settings->setDefault("tinted_sunlight", "false"); + settings->setDefault("artificial_light", "default"); settings->setDefault("lighting_alpha", "0.0"); settings->setDefault("lighting_beta", "1.5"); settings->setDefault("display_gamma", "1.0"); @@ -223,6 +225,7 @@ void set_default_settings() settings->setDefault("view_bobbing_amount", "1.0"); settings->setDefault("fall_bobbing_amount", "0.03"); settings->setDefault("enable_3d_clouds", "true"); + settings->setDefault("soft_clouds", "false"); settings->setDefault("cloud_radius", "12"); settings->setDefault("menu_clouds", "true"); settings->setDefault("opaque_water", "false"); @@ -273,6 +276,8 @@ 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("debanding", "true"); settings->setDefault("antialiasing", "none"); settings->setDefault("enable_bloom", "false"); @@ -281,6 +286,10 @@ void set_default_settings() settings->setDefault("bloom_intensity", "0.05"); settings->setDefault("bloom_radius", "1"); settings->setDefault("enable_volumetric_lighting", "false"); + settings->setDefault("enable_water_reflections", "false"); + settings->setDefault("enable_translucent_foliage", "false"); + settings->setDefault("enable_bumpmaps", "false"); + settings->setDefault("enable_node_reflections", "false"); // Effects Shadows settings->setDefault("enable_dynamic_shadows", "false"); diff --git a/src/lighting.h b/src/lighting.h index 262a48b5da143..20f434112f7b6 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 "SColor.h" +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 shadow_tint; }; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 90f2bed5b914d..62a55235b2201 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1470,12 +1470,17 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt) f32 density; video::SColor color_bright; video::SColor color_ambient; + video::SColor color_shadow; f32 height; f32 thickness; v2f speed; *pkt >> density >> color_bright >> color_ambient - >> height >> thickness >> speed; + >> height >> thickness >> speed; + + if (pkt->getRemainingBytes() >= 4) { + *pkt >> color_shadow; + } ClientEvent *event = new ClientEvent(); event->type = CE_CLOUD_PARAMS; @@ -1485,6 +1490,7 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt) // we avoid using new() and delete() for no good reason event->cloud_params.color_bright = color_bright.color; event->cloud_params.color_ambient = color_ambient.color; + event->cloud_params.color_shadow = color_shadow.color; event->cloud_params.height = height; event->cloud_params.thickness = thickness; // same here: deconstruct to skip constructor @@ -1815,4 +1821,6 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt) } if (pkt->getRemainingBytes() >= 4) *pkt >> lighting.volumetric_light_strength; + if (pkt->getRemainingBytes() >= 4) + *pkt >> lighting.shadow_tint; } diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index add80b3b23364..ea6f1e2aafa81 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -223,6 +223,8 @@ with this program; if not, write to the Free Software Foundation, Inc., AO_CMD_SET_BONE_POSITION extended Add TOCLIENT_MOVE_PLAYER_REL Move default minimap from client-side C++ to server-side builtin Lua + Add shadow tint to Lighting packets + Add shadow color to CloudParam packets [scheduled bump for 5.9.0] */ diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index ad4b7af417adb..f1698c151efc1 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2354,6 +2354,10 @@ int ObjectRef::l_set_clouds(lua_State *L) if (!lua_isnil(L, -1)) read_color(L, -1, &cloud_params.color_ambient); lua_pop(L, 1); + lua_getfield(L, 2, "shadow"); + if (!lua_isnil(L, -1)) + read_color(L, -1, &cloud_params.color_shadow); + lua_pop(L, 1); cloud_params.height = getfloatfield_default(L, 2, "height", cloud_params.height); cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness); @@ -2389,6 +2393,8 @@ int ObjectRef::l_get_clouds(lua_State *L) lua_setfield(L, -2, "color"); push_ARGB8(L, cloud_params.color_ambient); lua_setfield(L, -2, "ambient"); + push_ARGB8(L, cloud_params.color_shadow); + lua_setfield(L, -2, "shadow"); lua_pushnumber(L, cloud_params.height); lua_setfield(L, -2, "height"); lua_pushnumber(L, cloud_params.thickness); @@ -2522,6 +2528,9 @@ int ObjectRef::l_set_lighting(lua_State *L) getfloatfield(L, -1, "saturation", lighting.saturation); + lua_getfield(L, -1, "shadow_tint"); + read_color(L, -1, &lighting.shadow_tint); + lua_getfield(L, 2, "exposure"); if (lua_istable(L, -1)) { lighting.exposure.luminance_min = getfloatfield_default(L, -1, "luminance_min", lighting.exposure.luminance_min); @@ -2563,6 +2572,8 @@ int ObjectRef::l_get_lighting(lua_State *L) lua_setfield(L, -2, "shadows"); lua_pushnumber(L, lighting.saturation); lua_setfield(L, -2, "saturation"); + push_ARGB8(L, lighting.shadow_tint); + lua_setfield(L, -2, "shdadow_tint"); lua_newtable(L); // "exposure" lua_pushnumber(L, lighting.exposure.luminance_min); lua_setfield(L, -2, "luminance_min"); diff --git a/src/server.cpp b/src/server.cpp index 5dd2d46913d45..684f4110b2e31 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1865,7 +1865,7 @@ void Server::SendCloudParams(session_t peer_id, const CloudParams ¶ms) { NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id); pkt << params.density << params.color_bright << params.color_ambient - << params.height << params.thickness << params.speed; + << params.height << params.thickness << params.speed << params.color_shadow; Send(&pkt); } @@ -1897,6 +1897,8 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) pkt << lighting.volumetric_light_strength; + pkt << lighting.shadow_tint; + Send(&pkt); } diff --git a/src/skyparams.h b/src/skyparams.h index a4d0fadac1349..0ba6859c19238 100644 --- a/src/skyparams.h +++ b/src/skyparams.h @@ -81,6 +81,7 @@ struct CloudParams float density; video::SColor color_bright; video::SColor color_ambient; + video::SColor color_shadow; float thickness; float height; v2f speed; @@ -160,6 +161,7 @@ class SkyboxDefaults clouds.density = 0.4f; clouds.color_bright = video::SColor(229, 240, 240, 255); clouds.color_ambient = video::SColor(255, 0, 0, 0); + clouds.color_shadow = video::SColor(255, 204, 204, 204); clouds.thickness = 16.0f; clouds.height = 120; clouds.speed = v2f(0.0f, -2.0f);