1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Visual Effects Vol. 1 (#14610)

This PR adds a variety of effects to enhance the visual experience.

    "soft" clouds look
    Tinted shadows
    Crude water reflections (sky and sun) and waves
    Translucent foliage
    Node specular highlights
    Adjusted fog color (more saturated where the fog is lighter)
    Minor changes to volumetric lighting (crudely simulates the effect of depth)

Co-authored-by: sfan5 <sfan5@live.de>
This commit is contained in:
GefullteTaubenbrust2 2024-09-24 20:14:27 +02:00 committed by GitHub
parent 4ac86db8e3
commit d8f1daac25
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 356 additions and 53 deletions

View file

@ -403,6 +403,11 @@ enable_clouds (Clouds) bool true
# Requires: enable_clouds # Requires: enable_clouds
enable_3d_clouds (3D clouds) bool true 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] [**Filtering and Antialiasing]
# Use mipmaps when scaling textures. May slightly increase performance, # Use mipmaps when scaling textures. May slightly increase performance,
@ -505,6 +510,11 @@ water_wave_length (Waving liquids wavelength) float 20.0 0.1
# Requires: shaders, enable_waving_water # Requires: shaders, enable_waving_water
water_wave_speed (Waving liquids wave speed) float 5.0 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] [**Dynamic shadows]
# Set to true to enable Shadow Mapping. # Set to true to enable Shadow Mapping.
@ -661,6 +671,18 @@ bloom_radius (Bloom Radius) float 1 0.1 8
# Requires: shaders, enable_post_processing, enable_bloom # Requires: shaders, enable_post_processing, enable_bloom
enable_volumetric_lighting (Volumetric lighting) bool false enable_volumetric_lighting (Volumetric lighting) bool false
[**Other Effects]
# Simulate translucency when looking at foliage in the sunlight.
#
# Requires: shaders, enable_dynamic_shadows
enable_translucent_foliage (Translucent foliage) bool false
# Apply specular shading to nodes.
#
# Requires: shaders, enable_dynamic_shadows
enable_node_specular (Node specular) bool false
[*Audio] [*Audio]
# Volume of all sounds. # Volume of all sounds.

View file

@ -1,3 +1,7 @@
#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
#endif
uniform sampler2D baseTexture; uniform sampler2D baseTexture;
uniform vec3 dayLight; uniform vec3 dayLight;
@ -7,6 +11,7 @@ uniform float fogShadingParameter;
// The cameraOffset is the current center of the visible world. // The cameraOffset is the current center of the visible world.
uniform highp vec3 cameraOffset; uniform highp vec3 cameraOffset;
uniform vec3 cameraPosition;
uniform float animationTimer; uniform float animationTimer;
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
// shadow texture // shadow texture
@ -20,6 +25,7 @@ uniform float animationTimer;
uniform vec4 CameraPos; uniform vec4 CameraPos;
uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias0;
uniform float xyPerspectiveBias1; uniform float xyPerspectiveBias1;
uniform vec3 shadow_tint;
varying float adj_shadow_strength; varying float adj_shadow_strength;
varying float cosLight; varying float cosLight;
@ -47,6 +53,49 @@ varying highp vec3 eyeVec;
varying float nightRatio; varying float nightRatio;
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
#if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS) && ENABLE_WAVING_WATER)
vec4 perm(vec4 x)
{
return mod(((x * 34.0) + 1.0) * x, 289.0);
}
// 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 // assuming near is always 1.0
float getLinearDepth() float getLinearDepth()
@ -66,6 +115,14 @@ float mtsmoothstep(in float edge0, in float edge1, in float x)
return t * t * (3.0 - 2.0 * t); return t * t * (3.0 - 2.0 * t);
} }
float shadowCutoff(float x) {
#if defined(ENABLE_TRANSLUCENT_FOLIAGE) && MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES
return mtsmoothstep(0.0, 0.002, x);
#else
return step(0.0, x);
#endif
}
#ifdef COLORED_SHADOWS #ifdef COLORED_SHADOWS
// c_precision of 128 fits within 7 base-10 digits // c_precision of 128 fits within 7 base-10 digits
@ -92,10 +149,10 @@ vec4 getHardShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDist
{ {
vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy).rgba; vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy).rgba;
float visibility = step(0.0, realDistance - texDepth.r); float visibility = shadowCutoff(realDistance - texDepth.r);
vec4 result = vec4(visibility, vec3(0.0,0.0,0.0));//unpackColor(texDepth.g)); vec4 result = vec4(visibility, vec3(0.0,0.0,0.0));//unpackColor(texDepth.g));
if (visibility < 0.1) { if (visibility < 0.1) {
visibility = step(0.0, realDistance - texDepth.b); visibility = shadowCutoff(realDistance - texDepth.b);
result = vec4(visibility, unpackColor(texDepth.a)); result = vec4(visibility, unpackColor(texDepth.a));
} }
return result; return result;
@ -106,7 +163,7 @@ vec4 getHardShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDist
float getHardShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance) float getHardShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
{ {
float texDepth = texture2D(shadowsampler, smTexCoord.xy).r; float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
float visibility = step(0.0, realDistance - texDepth); float visibility = shadowCutoff(realDistance - texDepth);
return visibility; return visibility;
} }
@ -378,6 +435,9 @@ void main(void)
vec4 col = vec4(color.rgb * varColor.rgb, 1.0); vec4 col = vec4(color.rgb * varColor.rgb, 1.0);
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
// Fragment normal, can differ from vNormal which is derived from vertex normals.
vec3 fNormal = vNormal;
if (f_shadow_strength > 0.0) { if (f_shadow_strength > 0.0) {
float shadow_int = 0.0; float shadow_int = 0.0;
vec3 shadow_color = vec3(0.0, 0.0, 0.0); vec3 shadow_color = vec3(0.0, 0.0, 0.0);
@ -414,12 +474,19 @@ void main(void)
// Power ratio was measured on torches in MTG (brightness = 14). // Power ratio was measured on torches in MTG (brightness = 14).
float adjusted_night_ratio = pow(max(0.0, nightRatio), 0.6); 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 // Apply self-shadowing when light falls at a narrow angle to the surface
// Cosine of the cut-off angle. // Cosine of the cut-off angle.
const float self_shadow_cutoff_cosine = 0.035; const float self_shadow_cutoff_cosine = 0.035;
if (f_normal_length != 0 && cosLight < 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_int = max(shadow_int, 1 - clamp(cosLight, 0.0, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine);
shadow_color = mix(vec3(0.0), shadow_color, min(cosLight, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine); shadow_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.
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; shadow_int *= f_adj_shadow_strength;
@ -428,8 +495,60 @@ void main(void)
col.rgb = col.rgb =
adjusted_night_ratio * col.rgb + // artificial light adjusted_night_ratio * col.rgb + // artificial light
(1.0 - adjusted_night_ratio) * ( // natural 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 dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight
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) && ENABLE_WAVING_WATER)
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) * 0.8 + 0.2;
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.375, 1.0, 400.0);
col.rgb += water_reflect_color * f_adj_shadow_strength * brightness_factor;
#endif
#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));
const float specular_exponent = 5.0;
const float fresnel_exponent = 4.0;
col.rgb +=
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
#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);
#endif
} }
#endif #endif
@ -444,7 +563,13 @@ void main(void)
// Note: clarity = (1 - fogginess) // Note: clarity = (1 - fogginess)
float clarity = clamp(fogShadingParameter float clarity = clamp(fogShadingParameter
- fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
col = mix(fogColor, col, clarity); 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 = vec4(col.rgb, base.a); col = vec4(col.rgb, base.a);
gl_FragData[0] = col; gl_FragData[0] = col;

View file

@ -256,7 +256,9 @@ void main(void)
z_bias *= pFactor * pFactor / f_textureresolution / f_shadowfar; z_bias *= pFactor * pFactor / f_textureresolution / f_shadowfar;
shadow_position = applyPerspectiveDistortion(m_ShadowViewProj * mWorld * (shadow_pos + vec4(normalOffsetScale * nNormal, 0.0))).xyz; shadow_position = applyPerspectiveDistortion(m_ShadowViewProj * mWorld * (shadow_pos + vec4(normalOffsetScale * nNormal, 0.0))).xyz;
#if !defined(ENABLE_TRANSLUCENT_FOLIAGE) || MATERIAL_TYPE != TILE_MATERIAL_WAVING_LEAVES
shadow_position.z -= z_bias; shadow_position.z -= z_bias;
#endif
perspective_factor = pFactor; perspective_factor = pFactor;
if (f_timeofday < 0.2) { if (f_timeofday < 0.2) {

View file

@ -20,6 +20,7 @@ uniform float animationTimer;
uniform vec4 CameraPos; uniform vec4 CameraPos;
uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias0;
uniform float xyPerspectiveBias1; uniform float xyPerspectiveBias1;
uniform vec3 shadow_tint;
varying float adj_shadow_strength; varying float adj_shadow_strength;
varying float cosLight; varying float cosLight;
@ -432,7 +433,7 @@ void main(void)
col.rgb = col.rgb =
adjusted_night_ratio * col.rgb + // artificial light adjusted_night_ratio * col.rgb + // artificial light
(1.0 - adjusted_night_ratio) * ( // natural 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 dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight
} }
#endif #endif
@ -448,7 +449,13 @@ void main(void)
// Note: clarity = (1 - fogginess) // Note: clarity = (1 - fogginess)
float clarity = clamp(fogShadingParameter float clarity = clamp(fogShadingParameter
- fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
col = mix(fogColor, col, clarity); 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 = vec4(col.rgb, base.a); col = vec4(col.rgb, base.a);
gl_FragData[0] = col; gl_FragData[0] = col;

View file

@ -46,7 +46,9 @@ float sampleVolumetricLight(vec2 uv, vec3 lightVec, float rawDepth)
if (min(samplepos.x, samplepos.y) > 0. && max(samplepos.x, samplepos.y) < 1.) if (min(samplepos.x, samplepos.y) > 0. && max(samplepos.x, samplepos.y) < 1.)
result += texture2D(depthmap, samplepos).r < 1. ? 0.0 : 1.0; result += texture2D(depthmap, samplepos).r < 1. ? 0.0 : 1.0;
} }
return result / samples; // We use the depth map to approximate the effect of depth on the light intensity.
// The exponent was chosen based on aesthetic preference.
return result / samples * pow(texture2D(depthmap, uv).r, 128.0);
} }
vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection)

View file

@ -8518,6 +8518,8 @@ child will follow movement and rotation of that bone.
if set to zero the clouds are rendered flat. if set to zero the clouds are rendered flat.
* `speed`: 2D cloud speed + direction in nodes per second * `speed`: 2D cloud speed + direction in nodes per second
(default `{x=0, z=-2}`). (default `{x=0, z=-2}`).
* `shadow`: shadow color, applied to the base of the cloud
(default `#cccccc`).
* `get_clouds()`: returns a table with the current cloud parameters as in * `get_clouds()`: returns a table with the current cloud parameters as in
`set_clouds`. `set_clouds`.
* `override_day_night_ratio(ratio or nil)` * `override_day_night_ratio(ratio or nil)`
@ -8565,6 +8567,9 @@ child will follow movement and rotation of that bone.
* `shadows` is a table that controls ambient shadows * `shadows` is a table that controls ambient shadows
* `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness) * `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness)
* This value has no effect on clients who have the "Dynamic Shadows" shader disabled. * This value has no effect on clients who have the "Dynamic Shadows" shader disabled.
* `tint` tints the shadows with the provided color, with RGB values ranging from 0 to 255.
(default `{r=0, g=0, b=0}`)
* This value has no effect on clients who have the "Dynamic Shadows" shader disabled.
* `exposure` is a table that controls automatic exposure. * `exposure` is a table that controls automatic exposure.
The basic exposure factor equation is `e = 2^exposure_correction / clamp(luminance, 2^luminance_min, 2^luminance_max)` The basic exposure factor equation is `e = 2^exposure_correction / clamp(luminance, 2^luminance_min, 2^luminance_max)`
* `luminance_min` set the lower luminance boundary to use in the calculation (default: `-3.0`) * `luminance_min` set the lower luminance boundary to use in the calculation (default: `-3.0`)

View file

@ -137,6 +137,7 @@ struct ClientEvent
f32 density; f32 density;
u32 color_bright; u32 color_bright;
u32 color_ambient; u32 color_ambient;
u32 color_shadow;
f32 height; f32 height;
f32 thickness; f32 thickness;
f32 speed_x; f32 speed_x;

View file

@ -1209,11 +1209,22 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
// Render all mesh buffers in order // Render all mesh buffers in order
drawcall_count += draw_order.size(); drawcall_count += draw_order.size();
bool translucent_foliage = g_settings->getBool("enable_translucent_foliage");
video::E_MATERIAL_TYPE leaves_material = video::EMT_SOLID;
// For translucent leaves, we want to use backface culling instead of frontface.
if (translucent_foliage) {
// this is the material leaves would use, compare to nodedef.cpp
auto* shdsrc = m_client->getShaderSource();
const u32 leaves_shader = shdsrc->getShader("nodes_shader", TILE_MATERIAL_WAVING_LEAVES, NDT_ALLFACES);
leaves_material = shdsrc->getShaderInfo(leaves_shader).material;
}
for (auto &descriptor : draw_order) { for (auto &descriptor : draw_order) {
if (!descriptor.m_reuse_material) { if (!descriptor.m_reuse_material) {
// override some material properties // override some material properties
video::SMaterial local_material = descriptor.getMaterial(); video::SMaterial local_material = descriptor.getMaterial();
local_material.MaterialType = material.MaterialType;
// do not override culling if the original material renders both back // do not override culling if the original material renders both back
// and front faces in solid mode (e.g. plantlike) // and front faces in solid mode (e.g. plantlike)
// Transparent plants would still render shadows only from one side, // Transparent plants would still render shadows only from one side,
@ -1222,6 +1233,11 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
local_material.BackfaceCulling = material.BackfaceCulling; local_material.BackfaceCulling = material.BackfaceCulling;
local_material.FrontfaceCulling = material.FrontfaceCulling; local_material.FrontfaceCulling = material.FrontfaceCulling;
} }
if (local_material.MaterialType == leaves_material && translucent_foliage) {
local_material.BackfaceCulling = true;
local_material.FrontfaceCulling = false;
}
local_material.MaterialType = material.MaterialType;
local_material.BlendOperation = material.BlendOperation; local_material.BlendOperation = material.BlendOperation;
driver->setMaterial(local_material); driver->setMaterial(local_material);
++material_swaps; ++material_swaps;

View file

@ -65,6 +65,8 @@ Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc,
readSettings(); readSettings();
g_settings->registerChangedCallback("enable_3d_clouds", g_settings->registerChangedCallback("enable_3d_clouds",
&cloud_3d_setting_changed, this); &cloud_3d_setting_changed, this);
g_settings->registerChangedCallback("soft_clouds",
&cloud_3d_setting_changed, this);
updateBox(); updateBox();
@ -76,6 +78,8 @@ Clouds::~Clouds()
{ {
g_settings->deregisterChangedCallback("enable_3d_clouds", g_settings->deregisterChangedCallback("enable_3d_clouds",
&cloud_3d_setting_changed, this); &cloud_3d_setting_changed, this);
g_settings->deregisterChangedCallback("soft_clouds",
&cloud_3d_setting_changed, this);
} }
void Clouds::OnRegisterSceneNode() void Clouds::OnRegisterSceneNode()
@ -141,15 +145,18 @@ void Clouds::updateMesh()
// shader mixes the base color, set via ColorParam // shader mixes the base color, set via ColorParam
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_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; video::SColorf shadow = m_params.color_shadow;
c_side_1_f.g *= 0.95f;
c_side_1_f.b *= 0.95f; c_side_1_f.r *= shadow.r * 0.25f + 0.75f;
c_side_2_f.r *= 0.90f; c_side_1_f.g *= shadow.g * 0.25f + 0.75f;
c_side_2_f.g *= 0.90f; c_side_1_f.b *= shadow.b * 0.25f + 0.75f;
c_side_2_f.b *= 0.90f; c_side_2_f.r *= shadow.r * 0.5f + 0.5f;
c_bottom_f.r *= 0.80f; c_side_2_f.g *= shadow.g * 0.5f + 0.5f;
c_bottom_f.g *= 0.80f; c_side_2_f.b *= shadow.b * 0.5f + 0.5f;
c_bottom_f.b *= 0.80f; 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_top = c_top_f.toSColor();
video::SColor c_side_1 = c_side_1_f.toSColor(); video::SColor c_side_1 = c_side_1_f.toSColor();
video::SColor c_side_2 = c_side_2_f.toSColor(); video::SColor c_side_2 = c_side_2_f.toSColor();
@ -221,13 +228,14 @@ void Clouds::updateMesh()
const f32 ry = is3D() ? m_params.thickness * BS : 0.0f; const f32 ry = is3D() ? m_params.thickness * BS : 0.0f;
const f32 rz = cloud_size / 2; 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 case 0: // top
for (video::S3DVertex &vertex : v) { for (video::S3DVertex& vertex : v) {
vertex.Normal.set(0,1,0); 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[1].Pos.set(-rx, ry, rz);
@ -237,12 +245,20 @@ void Clouds::updateMesh()
case 1: // back case 1: // back
if (INAREA(xi, zi - 1, m_cloud_radius_i)) { if (INAREA(xi, zi - 1, m_cloud_radius_i)) {
u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i); u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i);
if(grid[j]) if (grid[j])
continue; continue;
} }
for (video::S3DVertex &vertex : v) { if (soft_clouds_enabled) {
vertex.Color = c_side_1; for (video::S3DVertex& vertex : v) {
vertex.Normal.set(0,0,-1); 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[0].Pos.set(-rx, ry,-rz);
v[1].Pos.set( rx, ry,-rz); v[1].Pos.set( rx, ry,-rz);
@ -251,28 +267,45 @@ void Clouds::updateMesh()
break; break;
case 2: //right case 2: //right
if (INAREA(xi + 1, zi, m_cloud_radius_i)) { if (INAREA(xi + 1, zi, m_cloud_radius_i)) {
u32 j = GETINDEX(xi+1, zi, m_cloud_radius_i); u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i);
if(grid[j]) if (grid[j])
continue; continue;
} }
for (video::S3DVertex &vertex : v) { if (soft_clouds_enabled) {
vertex.Color = c_side_2; for (video::S3DVertex& vertex : v) {
vertex.Normal.set(1,0,0); vertex.Normal.set(1, 0, 0);
}
v[2].Color = c_bottom;
v[3].Color = c_bottom;
} }
v[0].Pos.set( rx, ry,-rz); else {
v[1].Pos.set( rx, ry, rz); for (video::S3DVertex& vertex : v) {
v[2].Pos.set( rx, 0, rz); vertex.Color = c_side_2;
v[3].Pos.set( rx, 0,-rz); 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; break;
case 3: // front case 3: // front
if (INAREA(xi, zi + 1, m_cloud_radius_i)) { if (INAREA(xi, zi + 1, m_cloud_radius_i)) {
u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i); u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i);
if(grid[j]) if (grid[j])
continue; continue;
} }
for (video::S3DVertex &vertex : v) { if (soft_clouds_enabled) {
vertex.Color = c_side_1; for (video::S3DVertex& vertex : v) {
vertex.Normal.set(0,0,-1); 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[0].Pos.set( rx, ry, rz);
v[1].Pos.set(-rx, ry, rz); v[1].Pos.set(-rx, ry, rz);
@ -280,14 +313,22 @@ void Clouds::updateMesh()
v[3].Pos.set( rx, 0, rz); v[3].Pos.set( rx, 0, rz);
break; break;
case 4: // left case 4: // left
if (INAREA(xi-1, zi, m_cloud_radius_i)) { if (INAREA(xi - 1, zi, m_cloud_radius_i)) {
u32 j = GETINDEX(xi-1, zi, m_cloud_radius_i); u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i);
if(grid[j]) if (grid[j])
continue; continue;
} }
for (video::S3DVertex &vertex : v) { if (soft_clouds_enabled) {
vertex.Color = c_side_2; for (video::S3DVertex& vertex : v) {
vertex.Normal.set(-1,0,0); 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[0].Pos.set(-rx, ry, rz);
v[1].Pos.set(-rx, ry,-rz); v[1].Pos.set(-rx, ry,-rz);
@ -295,9 +336,9 @@ void Clouds::updateMesh()
v[3].Pos.set(-rx, 0, rz); v[3].Pos.set(-rx, 0, rz);
break; break;
case 5: // bottom case 5: // bottom
for (video::S3DVertex &vertex : v) { for (video::S3DVertex& vertex : v) {
vertex.Color = c_bottom; vertex.Color = c_bottom;
vertex.Normal.set(0,-1,0); vertex.Normal.set(0, -1, 0);
} }
v[0].Pos.set( rx, 0, rz); v[0].Pos.set( rx, 0, rz);
v[1].Pos.set(-rx, 0, rz); v[1].Pos.set(-rx, 0, rz);

View file

@ -109,6 +109,14 @@ public:
m_params.color_ambient = color_ambient; m_params.color_ambient = color_ambient;
} }
void setColorShadow(video::SColor color_shadow)
{
if (m_params.color_shadow == color_shadow)
return;
m_params.color_shadow = color_shadow;
invalidateMesh();
}
void setHeight(float height) void setHeight(float height)
{ {
if (m_params.height == height) if (m_params.height == height)

View file

@ -83,7 +83,8 @@ MapblockMeshGenerator::MapblockMeshGenerator(MeshMakeData *input, MeshCollector
meshmanip(mm), meshmanip(mm),
blockpos_nodes(data->m_blockpos * MAP_BLOCKSIZE), blockpos_nodes(data->m_blockpos * MAP_BLOCKSIZE),
enable_mesh_cache(g_settings->getBool("enable_mesh_cache") && enable_mesh_cache(g_settings->getBool("enable_mesh_cache") &&
!data->m_smooth_lighting) // Mesh cache is not supported with smooth lighting !data->m_smooth_lighting), // Mesh cache is not supported with smooth lighting
smooth_liquids(g_settings->getBool("enable_water_reflections"))
{ {
} }
@ -717,7 +718,7 @@ void MapblockMeshGenerator::drawLiquidSides()
if (data->m_smooth_lighting) if (data->m_smooth_lighting)
cur_node.color = blendLightColor(pos); cur_node.color = blendLightColor(pos);
pos += cur_node.origin; 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); collector->append(cur_liquid.tile, vertices, 4, quad_indices, 6);
} }
@ -740,6 +741,19 @@ void MapblockMeshGenerator::drawLiquidTop()
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
int u = corner_resolve[i][0]; int u = corner_resolve[i][0];
int w = corner_resolve[i][1]; int w = corner_resolve[i][1];
if (smooth_liquids) {
int x = vertices[i].Pos.X > 0;
int z = vertices[i].Pos.Z > 0;
f32 dx = 0.5f * (cur_liquid.neighbors[z][x].level - cur_liquid.neighbors[z][x + 1].level +
cur_liquid.neighbors[z + 1][x].level - cur_liquid.neighbors[z + 1][x + 1].level);
f32 dz = 0.5f * (cur_liquid.neighbors[z][x].level - cur_liquid.neighbors[z + 1][x].level +
cur_liquid.neighbors[z][x + 1].level - cur_liquid.neighbors[z + 1][x + 1].level);
vertices[i].Normal = v3f(dx, 1., dz).normalize();
}
vertices[i].Pos.Y += cur_liquid.corner_levels[w][u] * BS; vertices[i].Pos.Y += cur_liquid.corner_levels[w][u] * BS;
if (data->m_smooth_lighting) if (data->m_smooth_lighting)
vertices[i].Color = blendLightColor(vertices[i].Pos); vertices[i].Color = blendLightColor(vertices[i].Pos);
@ -779,6 +793,10 @@ void MapblockMeshGenerator::drawLiquidTop()
vertex.TCoords += tcoord_center; vertex.TCoords += tcoord_center;
vertex.TCoords += tcoord_translate; vertex.TCoords += tcoord_translate;
if (!smooth_liquids) {
vertex.Normal = v3f(dx, 1., dz).normalize();
}
} }
std::swap(vertices[0].TCoords, vertices[2].TCoords); std::swap(vertices[0].TCoords, vertices[2].TCoords);

View file

@ -134,6 +134,7 @@ private:
f32 corner_levels[2][2]; f32 corner_levels[2][2];
}; };
LiquidData cur_liquid; LiquidData cur_liquid;
bool smooth_liquids = false;
void prepareLiquidNodeDrawing(); void prepareLiquidNodeDrawing();
void getLiquidNeighborhood(); void getLiquidNeighborhood();

View file

@ -386,6 +386,8 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
CachedPixelShaderSetting<float, 3> m_minimap_yaw{"yawVec"}; CachedPixelShaderSetting<float, 3> m_minimap_yaw{"yawVec"};
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel{"cameraOffset"}; CachedPixelShaderSetting<float, 3> m_camera_offset_pixel{"cameraOffset"};
CachedVertexShaderSetting<float, 3> m_camera_offset_vertex{"cameraOffset"}; CachedVertexShaderSetting<float, 3> m_camera_offset_vertex{"cameraOffset"};
CachedPixelShaderSetting<float, 3> m_camera_position_pixel{ "cameraPosition" };
CachedVertexShaderSetting<float, 3> m_camera_position_vertex{ "cameraPosition" };
CachedPixelShaderSetting<SamplerLayer_t> m_texture0{"texture0"}; CachedPixelShaderSetting<SamplerLayer_t> m_texture0{"texture0"};
CachedPixelShaderSetting<SamplerLayer_t> m_texture1{"texture1"}; CachedPixelShaderSetting<SamplerLayer_t> m_texture1{"texture1"};
CachedPixelShaderSetting<SamplerLayer_t> m_texture2{"texture2"}; CachedPixelShaderSetting<SamplerLayer_t> m_texture2{"texture2"};
@ -492,6 +494,10 @@ public:
m_camera_offset_pixel.set(offset, services); m_camera_offset_pixel.set(offset, services);
m_camera_offset_vertex.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);
m_camera_position_pixel.set(camera_position, services);
SamplerLayer_t tex_id; SamplerLayer_t tex_id;
tex_id = 0; tex_id = 0;
m_texture0.set(&tex_id, services); m_texture0.set(&tex_id, services);
@ -3184,6 +3190,7 @@ void Game::handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *
clouds->setDensity(event->cloud_params.density); clouds->setDensity(event->cloud_params.density);
clouds->setColorBright(video::SColor(event->cloud_params.color_bright)); clouds->setColorBright(video::SColor(event->cloud_params.color_bright));
clouds->setColorAmbient(video::SColor(event->cloud_params.color_ambient)); 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->setHeight(event->cloud_params.height);
clouds->setThickness(event->cloud_params.thickness); clouds->setThickness(event->cloud_params.thickness);
clouds->setSpeed(v2f(event->cloud_params.speed_x, event->cloud_params.speed_y)); clouds->setSpeed(v2f(event->cloud_params.speed_x, event->cloud_params.speed_y));
@ -4315,7 +4322,9 @@ void Game::updateShadows()
float timeoftheday = getWickedTimeOfDay(in_timeofday); float timeoftheday = getWickedTimeOfDay(in_timeofday);
bool is_day = timeoftheday > 0.25 && timeoftheday < 0.75; bool is_day = timeoftheday > 0.25 && timeoftheday < 0.75;
bool is_shadow_visible = is_day ? sky->getSunVisible() : sky->getMoonVisible(); bool is_shadow_visible = is_day ? sky->getSunVisible() : sky->getMoonVisible();
shadow->setShadowIntensity(is_shadow_visible ? client->getEnv().getLocalPlayer()->getLighting().shadow_intensity : 0.0f); const auto &lighting = client->getEnv().getLocalPlayer()->getLighting();
shadow->setShadowIntensity(is_shadow_visible ? lighting.shadow_intensity : 0.0f);
shadow->setShadowTint(lighting.shadow_tint);
timeoftheday = std::fmod(timeoftheday + 0.75f, 0.5f) + 0.25f; timeoftheday = std::fmod(timeoftheday + 0.75f, 0.5f) + 0.25f;
const float offset_constant = 10000.0f; const float offset_constant = 10000.0f;

View file

@ -689,6 +689,15 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
if (g_settings->getBool("shadow_poisson_filter")) if (g_settings->getBool("shadow_poisson_filter"))
shaders_header << "#define POISSON_FILTER 1\n"; 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_node_specular"))
shaders_header << "#define ENABLE_NODE_SPECULAR 1\n";
s32 shadow_filter = g_settings->getS32("shadow_filters"); s32 shadow_filter = g_settings->getS32("shadow_filters");
shaders_header << "#define SHADOW_FILTER " << shadow_filter << "\n"; shaders_header << "#define SHADOW_FILTER " << shadow_filter << "\n";

View file

@ -94,9 +94,11 @@ public:
bool is_active() const { return m_shadows_enabled && shadowMapTextureFinal != nullptr; } bool is_active() const { return m_shadows_enabled && shadowMapTextureFinal != nullptr; }
void setTimeOfDay(float isDay) { m_time_day = isDay; }; void setTimeOfDay(float isDay) { m_time_day = isDay; };
void setShadowIntensity(float shadow_intensity); void setShadowIntensity(float shadow_intensity);
void setShadowTint(video::SColor shadow_tint) { m_shadow_tint = shadow_tint; }
s32 getShadowSamples() const { return m_shadow_samples; } s32 getShadowSamples() const { return m_shadow_samples; }
float getShadowStrength() const { return m_shadows_enabled ? m_shadow_strength : 0.0f; } 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; } float getTimeOfDay() const { return m_time_day; }
f32 getPerspectiveBiasXY() { return m_perspective_bias_xy; } f32 getPerspectiveBiasXY() { return m_perspective_bias_xy; }
@ -131,6 +133,7 @@ private:
std::vector<NodeToApply> m_shadow_node_array; std::vector<NodeToApply> m_shadow_node_array;
float m_shadow_strength; float m_shadow_strength;
video::SColor m_shadow_tint{ 255, 0, 0, 0 };
float m_shadow_strength_gamma; float m_shadow_strength_gamma;
float m_shadow_map_max_distance; float m_shadow_map_max_distance;
float m_shadow_map_texture_size; float m_shadow_map_texture_size;

View file

@ -40,6 +40,9 @@ void ShadowConstantSetter::onSetConstants(video::IMaterialRendererServices *serv
f32 ShadowStrength = shadow->getShadowStrength(); f32 ShadowStrength = shadow->getShadowStrength();
m_shadow_strength.set(&ShadowStrength, services); m_shadow_strength.set(&ShadowStrength, services);
video::SColor ShadowTint = shadow->getShadowTint();
m_shadow_tint.set(ShadowTint, services);
f32 timeOfDay = shadow->getTimeOfDay(); f32 timeOfDay = shadow->getTimeOfDay();
m_time_of_day.set(&timeOfDay, services); m_time_of_day.set(&timeOfDay, services);

View file

@ -31,6 +31,7 @@ class ShadowConstantSetter : public IShaderConstantSetter
CachedPixelShaderSetting<f32, 3> m_light_direction{"v_LightDirection"}; CachedPixelShaderSetting<f32, 3> m_light_direction{"v_LightDirection"};
CachedPixelShaderSetting<f32> m_texture_res{"f_textureresolution"}; CachedPixelShaderSetting<f32> m_texture_res{"f_textureresolution"};
CachedPixelShaderSetting<f32> m_shadow_strength{"f_shadow_strength"}; CachedPixelShaderSetting<f32> m_shadow_strength{"f_shadow_strength"};
CachedPixelShaderSetting<f32, 3> m_shadow_tint{ "shadow_tint" };
CachedPixelShaderSetting<f32> m_time_of_day{"f_timeofday"}; CachedPixelShaderSetting<f32> m_time_of_day{"f_timeofday"};
CachedPixelShaderSetting<f32> m_shadowfar{"f_shadowfar"}; CachedPixelShaderSetting<f32> m_shadowfar{"f_shadowfar"};
CachedPixelShaderSetting<f32, 4> m_camera_pos{"CameraPos"}; CachedPixelShaderSetting<f32, 4> m_camera_pos{"CameraPos"};

View file

@ -275,6 +275,7 @@ void set_default_settings()
settings->setDefault("view_bobbing_amount", "1.0"); settings->setDefault("view_bobbing_amount", "1.0");
settings->setDefault("fall_bobbing_amount", "0.03"); settings->setDefault("fall_bobbing_amount", "0.03");
settings->setDefault("enable_3d_clouds", "true"); settings->setDefault("enable_3d_clouds", "true");
settings->setDefault("soft_clouds", "false");
settings->setDefault("cloud_radius", "12"); settings->setDefault("cloud_radius", "12");
settings->setDefault("menu_clouds", "true"); settings->setDefault("menu_clouds", "true");
settings->setDefault("translucent_liquids", "true"); settings->setDefault("translucent_liquids", "true");
@ -335,6 +336,9 @@ void set_default_settings()
settings->setDefault("bloom_intensity", "0.05"); settings->setDefault("bloom_intensity", "0.05");
settings->setDefault("bloom_radius", "1"); settings->setDefault("bloom_radius", "1");
settings->setDefault("enable_volumetric_lighting", "false"); settings->setDefault("enable_volumetric_lighting", "false");
settings->setDefault("enable_water_reflections", "false");
settings->setDefault("enable_translucent_foliage", "false");
settings->setDefault("enable_node_specular", "false");
// Effects Shadows // Effects Shadows
settings->setDefault("enable_dynamic_shadows", "false"); settings->setDefault("enable_dynamic_shadows", "false");

View file

@ -18,7 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/ */
#pragma once #pragma once
#include "SColor.h"
using namespace irr;
/** /**
* Parameters for automatic exposure compensation * Parameters for automatic exposure compensation
@ -54,4 +56,5 @@ struct Lighting
float shadow_intensity {0.0f}; float shadow_intensity {0.0f};
float saturation {1.0f}; float saturation {1.0f};
float volumetric_light_strength {0.0f}; float volumetric_light_strength {0.0f};
video::SColor shadow_tint;
}; };

View file

@ -1476,6 +1476,7 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt)
f32 density; f32 density;
video::SColor color_bright; video::SColor color_bright;
video::SColor color_ambient; video::SColor color_ambient;
video::SColor color_shadow = video::SColor(255, 204, 204, 204);
f32 height; f32 height;
f32 thickness; f32 thickness;
v2f speed; v2f speed;
@ -1483,6 +1484,10 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt)
*pkt >> density >> color_bright >> color_ambient *pkt >> density >> color_bright >> color_ambient
>> height >> thickness >> speed; >> height >> thickness >> speed;
if (pkt->getRemainingBytes() >= 4) {
*pkt >> color_shadow;
}
ClientEvent *event = new ClientEvent(); ClientEvent *event = new ClientEvent();
event->type = CE_CLOUD_PARAMS; event->type = CE_CLOUD_PARAMS;
event->cloud_params.density = density; event->cloud_params.density = density;
@ -1491,6 +1496,7 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt)
// we avoid using new() and delete() for no good reason // we avoid using new() and delete() for no good reason
event->cloud_params.color_bright = color_bright.color; event->cloud_params.color_bright = color_bright.color;
event->cloud_params.color_ambient = color_ambient.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.height = height;
event->cloud_params.thickness = thickness; event->cloud_params.thickness = thickness;
// same here: deconstruct to skip constructor // same here: deconstruct to skip constructor
@ -1821,4 +1827,6 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
} }
if (pkt->getRemainingBytes() >= 4) if (pkt->getRemainingBytes() >= 4)
*pkt >> lighting.volumetric_light_strength; *pkt >> lighting.volumetric_light_strength;
if (pkt->getRemainingBytes() >= 4)
*pkt >> lighting.shadow_tint;
} }

View file

@ -229,10 +229,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
[bump for 5.9.1] [bump for 5.9.1]
PROTOCOL VERSION 46: PROTOCOL VERSION 46:
Move default hotbar from client-side C++ to server-side builtin Lua Move default hotbar 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.10.0] [scheduled bump for 5.10.0]
*/ */
#define LATEST_PROTOCOL_VERSION 46 #define LATEST_PROTOCOL_VERSION 46
#define LATEST_PROTOCOL_VERSION_STRING TOSTRING(LATEST_PROTOCOL_VERSION) #define LATEST_PROTOCOL_VERSION_STRING TOSTRING(LATEST_PROTOCOL_VERSION)
// Server's supported network protocol range // Server's supported network protocol range

View file

@ -2448,6 +2448,10 @@ int ObjectRef::l_set_clouds(lua_State *L)
if (!lua_isnil(L, -1)) if (!lua_isnil(L, -1))
read_color(L, -1, &cloud_params.color_ambient); read_color(L, -1, &cloud_params.color_ambient);
lua_pop(L, 1); 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.height = getfloatfield_default(L, 2, "height", cloud_params.height);
cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness); cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness);
@ -2483,6 +2487,8 @@ int ObjectRef::l_get_clouds(lua_State *L)
lua_setfield(L, -2, "color"); lua_setfield(L, -2, "color");
push_ARGB8(L, cloud_params.color_ambient); push_ARGB8(L, cloud_params.color_ambient);
lua_setfield(L, -2, "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_pushnumber(L, cloud_params.height);
lua_setfield(L, -2, "height"); lua_setfield(L, -2, "height");
lua_pushnumber(L, cloud_params.thickness); lua_pushnumber(L, cloud_params.thickness);
@ -2611,6 +2617,8 @@ int ObjectRef::l_set_lighting(lua_State *L)
lua_getfield(L, 2, "shadows"); lua_getfield(L, 2, "shadows");
if (lua_istable(L, -1)) { if (lua_istable(L, -1)) {
getfloatfield(L, -1, "intensity", lighting.shadow_intensity); getfloatfield(L, -1, "intensity", lighting.shadow_intensity);
lua_getfield(L, -1, "tint");
read_color(L, -1, &lighting.shadow_tint);
} }
lua_pop(L, 1); // shadows lua_pop(L, 1); // shadows
@ -2654,6 +2662,8 @@ int ObjectRef::l_get_lighting(lua_State *L)
lua_newtable(L); // "shadows" lua_newtable(L); // "shadows"
lua_pushnumber(L, lighting.shadow_intensity); lua_pushnumber(L, lighting.shadow_intensity);
lua_setfield(L, -2, "intensity"); lua_setfield(L, -2, "intensity");
push_ARGB8(L, lighting.shadow_tint);
lua_setfield(L, -2, "tint");
lua_setfield(L, -2, "shadows"); lua_setfield(L, -2, "shadows");
lua_pushnumber(L, lighting.saturation); lua_pushnumber(L, lighting.saturation);
lua_setfield(L, -2, "saturation"); lua_setfield(L, -2, "saturation");

View file

@ -1843,7 +1843,7 @@ void Server::SendCloudParams(session_t peer_id, const CloudParams &params)
{ {
NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id); NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
pkt << params.density << params.color_bright << params.color_ambient 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); Send(&pkt);
} }
@ -1873,7 +1873,7 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
<< lighting.exposure.speed_bright_dark << lighting.exposure.speed_bright_dark
<< lighting.exposure.center_weight_power; << lighting.exposure.center_weight_power;
pkt << lighting.volumetric_light_strength; pkt << lighting.volumetric_light_strength << lighting.shadow_tint;
Send(&pkt); Send(&pkt);
} }

View file

@ -81,6 +81,7 @@ struct CloudParams
float density; float density;
video::SColor color_bright; video::SColor color_bright;
video::SColor color_ambient; video::SColor color_ambient;
video::SColor color_shadow;
float thickness; float thickness;
float height; float height;
v2f speed; v2f speed;
@ -160,6 +161,7 @@ public:
clouds.density = 0.4f; clouds.density = 0.4f;
clouds.color_bright = video::SColor(229, 240, 240, 255); clouds.color_bright = video::SColor(229, 240, 240, 255);
clouds.color_ambient = video::SColor(255, 0, 0, 0); clouds.color_ambient = video::SColor(255, 0, 0, 0);
clouds.color_shadow = video::SColor(255, 204, 204, 204);
clouds.thickness = 16.0f; clouds.thickness = 16.0f;
clouds.height = 120; clouds.height = 120;
clouds.speed = v2f(0.0f, -2.0f); clouds.speed = v2f(0.0f, -2.0f);