1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00
This commit is contained in:
Gefüllte Taubenbrust 2025-06-26 20:27:51 +02:00 committed by GitHub
commit 82cc518b6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 413 additions and 69 deletions

View file

@ -676,20 +676,23 @@ enable_waving_water (Waving liquids) bool false
# 0.0 = Wave doesn't move at all. # 0.0 = Wave doesn't move at all.
# Default is 1.0 (1/2 node). # Default is 1.0 (1/2 node).
# #
# Requires: enable_waving_water
water_wave_height (Waving liquids wave height) float 1.0 0.0 4.0 water_wave_height (Waving liquids wave height) float 1.0 0.0 4.0
# Length of liquid waves. # Length of liquid waves.
# #
# Requires: enable_waving_water
water_wave_length (Waving liquids wavelength) float 20.0 0.1 water_wave_length (Waving liquids wavelength) float 20.0 0.1
# How fast liquid waves will move. Higher = faster. # How fast liquid waves will move. Higher = faster.
# If negative, liquid waves will move backwards. # If negative, liquid waves will move backwards.
# #
# Requires: 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, crude liquid reflections are simulated.
# Wave height, length and speed will affect these reflections.
#
# Requires: 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.
@ -750,6 +753,11 @@ shadow_soft_radius (Soft shadow radius) float 5.0 1.0 15.0
# Requires: enable_dynamic_shadows, opengl # Requires: enable_dynamic_shadows, opengl
shadow_sky_body_orbit_tilt (Sky Body Orbit Tilt) float 0.0 -60.0 60.0 shadow_sky_body_orbit_tilt (Sky Body Orbit Tilt) float 0.0 -60.0 60.0
# Tint sunlight during sunrise/sunset.
#
# Requires: enable_dynamic_shadows, opengl
enable_sun_tint (Tinted sunlight) bool false
[**Post Processing] [**Post Processing]
# Enables the post processing pipeline. # Enables the post processing pipeline.
@ -778,6 +786,19 @@ enable_auto_exposure (Enable Automatic Exposure) bool false
# Requires: enable_post_processing, enable_auto_exposure # Requires: enable_post_processing, enable_auto_exposure
exposure_compensation (Exposure compensation) float 0.0 -1.0 1.0 exposure_compensation (Exposure compensation) float 0.0 -1.0 1.0
# Set the post processing gamma value.
# Higher values give lower contrast and vice versa.
# Range: from 1.0 to 5.0
# Default: 1.6
#
# Requires: enable_post_processing, tone_mapping
secondstage_gamma (Gamma) float 1.6 1.0 5.0
# Apply ASL CDL color grading to make brighter colors warmer and darker colors cooler.
#
# Requires: enable_post_processing
enable_color_grading (Color grading) bool false
# Apply dithering to reduce color banding artifacts. # Apply dithering to reduce color banding artifacts.
# Dithering significantly increases the size of losslessly-compressed # Dithering significantly increases the size of losslessly-compressed
# screenshots and it works incorrectly if the display or operating system # screenshots and it works incorrectly if the display or operating system
@ -798,11 +819,20 @@ enable_bloom (Enable Bloom) bool false
# Set to true to enable volumetric lighting effect (a.k.a. "Godrays"). # Set to true to enable volumetric lighting effect (a.k.a. "Godrays").
# #
# Requires: enable_post_processing, enable_bloom # Requires: enable_post_processing, enable_bloom
enable_volumetric_lighting (Volumetric lighting) bool false enable_volumetric_lighting (Volumetric Lighting) bool false
# Make volumetrics weaker against closer objects to emulate physical volumetrics.
#
# Requires: enable_post_processing, enable_bloom, enable_volumetric_lighting
enable_volumetric_depth_attenuation (Volumetric Depth Attenuation) bool false
[**Other Effects] [**Other Effects]
# Makes the color of light fog more saturated.
enable_tinted_fog (Tinted fog) bool false
# Simulate translucency when looking at foliage in the sunlight. # Simulate translucency when looking at foliage in the sunlight.
# It is recommended to use this with the leaves style set to fancy.
# #
# Requires: enable_dynamic_shadows # Requires: enable_dynamic_shadows
enable_translucent_foliage (Translucent foliage) bool false enable_translucent_foliage (Translucent foliage) bool false

View file

@ -1,6 +1,7 @@
uniform sampler2D baseTexture; uniform sampler2D baseTexture;
uniform sampler2D normalTexture; uniform sampler2D normalTexture;
uniform vec3 yawVec; uniform vec3 yawVec;
uniform float mapSize;
varying lowp vec4 varColor; varying lowp vec4 varColor;
varying mediump vec2 varTexCoord; varying mediump vec2 varTexCoord;
@ -10,7 +11,7 @@ void main (void)
vec2 uv = varTexCoord.st; vec2 uv = varTexCoord.st;
//texture sampling rate //texture sampling rate
const float step = 1.0 / 256.0; float step = 1.0 / mapSize;
float tl = texture2D(normalTexture, vec2(uv.x - step, uv.y + step)).r; float tl = texture2D(normalTexture, vec2(uv.x - step, uv.y + step)).r;
float t = texture2D(normalTexture, vec2(uv.x, uv.y + step)).r; float t = texture2D(normalTexture, vec2(uv.x, uv.y + step)).r;
float tr = texture2D(normalTexture, vec2(uv.x + step, uv.y + step)).r; float tr = texture2D(normalTexture, vec2(uv.x + step, uv.y + step)).r;

View file

@ -22,15 +22,17 @@ uniform float animationTimer;
uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias0;
uniform float xyPerspectiveBias1; uniform float xyPerspectiveBias1;
uniform vec3 shadow_tint; uniform vec3 shadow_tint;
uniform float foliage_translucency;
uniform float specular_intensity;
varying float adj_shadow_strength; varying float adj_shadow_strength;
varying float cosLight; varying float cosLight;
varying float f_normal_length; varying float f_normal_length;
varying vec3 shadow_position; varying vec3 shadow_position;
varying float perspective_factor; varying float perspective_factor;
varying vec3 sunTint;
#endif #endif
varying vec3 vNormal; varying vec3 vNormal;
varying vec3 vPosition; varying vec3 vPosition;
// World position in the visible world (i.e. relative to the cameraOffset.) // World position in the visible world (i.e. relative to the cameraOffset.)
@ -49,9 +51,12 @@ centroid varying vec2 varTexCoord;
centroid varying float nightRatio; centroid varying float nightRatio;
#endif #endif
varying highp vec3 eyeVec; varying highp vec3 eyeVec;
varying float nightFactor;
#define PI 3.141592653589
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
#if (defined(ENABLE_WATER_REFLECTIONS) && MATERIAL_WATER_REFLECTIONS && ENABLE_WAVING_WATER) #if (MATERIAL_WAVING_LIQUID && defined(ENABLE_WATER_REFLECTIONS))
vec4 perm(vec4 x) vec4 perm(vec4 x)
{ {
return mod(((x * 34.0) + 1.0) * x, 289.0); return mod(((x * 34.0) + 1.0) * x, 289.0);
@ -115,7 +120,7 @@ float mtsmoothstep(in float edge0, in float edge1, in float x)
float shadowCutoff(float x) { float shadowCutoff(float x) {
#if defined(ENABLE_TRANSLUCENT_FOLIAGE) && MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES #if defined(ENABLE_TRANSLUCENT_FOLIAGE) && MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES
return mtsmoothstep(0.0, 0.002, x); return mtsmoothstep(0.0, 3.0 / f_shadowfar, x);
#else #else
return step(0.0, x); return step(0.0, x);
#endif #endif
@ -407,7 +412,6 @@ float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
} }
#endif #endif
#endif #endif
#endif #endif
@ -436,6 +440,8 @@ void main(void)
// Fragment normal, can differ from vNormal which is derived from vertex normals. // Fragment normal, can differ from vNormal which is derived from vertex normals.
vec3 fNormal = vNormal; vec3 fNormal = vNormal;
vec3 viewVec = normalize(worldPosition + cameraOffset - cameraPosition);
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);
@ -445,6 +451,7 @@ void main(void)
if (max(abs(posLightSpace.x - 0.5), abs(posLightSpace.y - 0.5)) > 0.5) if (max(abs(posLightSpace.x - 0.5), abs(posLightSpace.y - 0.5)) > 0.5)
distance_rate = 0.0; distance_rate = 0.0;
float f_adj_shadow_strength = max(adj_shadow_strength - mtsmoothstep(0.9, 1.1, posLightSpace.z),0.0); float f_adj_shadow_strength = max(adj_shadow_strength - mtsmoothstep(0.9, 1.1, posLightSpace.z),0.0);
float f_shadow_factor = adj_shadow_strength / f_shadow_strength;
if (distance_rate > 1e-7) { if (distance_rate > 1e-7) {
@ -477,6 +484,7 @@ void main(void)
// 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);
@ -492,29 +500,27 @@ void main(void)
// calculate fragment color from components: // calculate fragment color from components:
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 sunTint * (1.0 - adjusted_night_ratio) * ( // natural light
col.rgb * (1.0 - shadow_int * (1.0 - shadow_color) * (1.0 - shadow_tint)) + // filtered texture color 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 reflect_ray = -normalize(v_LightDirection - fNormal * dot(v_LightDirection, fNormal) * 2.0);
vec3 viewVec = normalize(worldPosition + cameraOffset - cameraPosition);
// Water reflections // Water reflections
#if (defined(ENABLE_WATER_REFLECTIONS) && MATERIAL_WATER_REFLECTIONS && ENABLE_WAVING_WATER) #if (MATERIAL_WAVING_LIQUID && defined(ENABLE_WATER_REFLECTIONS))
vec3 wavePos = worldPosition * vec3(2.0, 0.0, 2.0); vec3 wavePos = worldPosition * vec3(2.0, 0.0, 2.0);
float off = animationTimer * WATER_WAVE_SPEED * 10.0; float off = animationTimer * WATER_WAVE_SPEED * 10.0;
wavePos.x /= WATER_WAVE_LENGTH * 3.0; wavePos.x /= WATER_WAVE_LENGTH * 3.0;
wavePos.z /= WATER_WAVE_LENGTH * 2.0; wavePos.z /= WATER_WAVE_LENGTH * 2.0;
// This is an analogous method to the bumpmap, except we get the gradient information directly from gnoise. // We get the gradient information of the waves using gnoise.
vec2 gradient = wave_noise(wavePos, off); vec2 gradient = wave_noise(wavePos, off);
fNormal = normalize(normalize(fNormal) + vec3(gradient.x, 0., gradient.y) * WATER_WAVE_HEIGHT * abs(fNormal.y) * 0.25); 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); reflect_ray = -normalize(v_LightDirection - fNormal * dot(v_LightDirection, fNormal) * 2.0);
float fresnel_factor = dot(fNormal, viewVec); float fresnel_factor = dot(fNormal, viewVec);
float brightness_factor = 1.0 - adjusted_night_ratio; float brightness_factor = (1.0 - adjusted_night_ratio) / base.a;
// A little trig hack. We go from the dot product of viewVec and normal to the dot product of viewVec and tangent to apply a fresnel effect. // 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; fresnel_factor = clamp(pow(1.0 - fresnel_factor * fresnel_factor, 8.0), 0.0, 1.0) * 0.8 + 0.2;
@ -522,34 +528,52 @@ void main(void)
vec3 reflection_color = mix(vec3(max(fogColor.r, max(fogColor.g, fogColor.b))), fogColor.rgb, f_shadow_strength); vec3 reflection_color = mix(vec3(max(fogColor.r, max(fogColor.g, fogColor.b))), fogColor.rgb, f_shadow_strength);
// Sky reflection // Sky reflection
col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.5 * brightness_factor; col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.3 * brightness_factor;
vec3 water_reflect_color = 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. vec3 water_reflect_color =
water_reflect_color /= clamp(max(water_reflect_color.r, max(water_reflect_color.g, water_reflect_color.b)) * 0.375, 1.0, 400.0); 1.5 * specular_intensity * sunTint * dayLight * fresnel_factor * max(1.0 - shadow_uncorrected, 0.0) *
col.rgb += water_reflect_color * f_adj_shadow_strength * brightness_factor; mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0));
// Sun reflection
col.rgb += water_reflect_color * f_shadow_factor * brightness_factor;
#endif #endif
#if (defined(ENABLE_NODE_SPECULAR) && !MATERIAL_WATER_REFLECTIONS) #if (defined(ENABLE_NODE_SPECULAR) && !MATERIAL_WATER_REFLECTIONS)
// Apply specular to blocks. // Apply specular to nodes.
if (dot(v_LightDirection, vNormal) < 0.0) { if (dot(v_LightDirection, vNormal) < 0.0) {
float intensity = 2.0 * (1.0 - (base.r * varColor.r)); // This intensity/roughness is a placeholder and should be replaced by proper specular maps.
const float specular_exponent = 5.0; float intensity = 0.35 * min(1.0, length(varColor.rgb * base.rgb));
const float fresnel_exponent = 4.0; float roughness = 0.5;
float rms = 1.0 / (1.0 - roughness) - 1.0;
vec3 half_vector = normalize(viewVec + v_LightDirection);
const float F0 = 0.04;
float HV = dot(viewVec, half_vector);
float HN = dot(fNormal, half_vector);
float VN = dot(viewVec, normalize(fNormal));
float LN = dot(v_LightDirection, fNormal);
float HN2 = HN*HN;
float beckmann = exp((HN2 - 1.0) / (rms * rms * HN2)) / (PI * rms * rms * HN2*HN2);
float geometry = min(min(1.0, 2.0 * HN * VN / HV), 2.0 * HN * LN / HV);
float fresnel_schlick = F0 + (1.0 - F0) * pow(1.0 - HV, 5.0);
col.rgb += col.rgb +=
intensity * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) * f_adj_shadow_strength * sunTint * specular_intensity * f_shadow_factor * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) *
pow(max(dot(reflect_ray, viewVec), 0.0), fresnel_exponent) * pow(1.0 - abs(dot(viewVec, fNormal)), specular_exponent); intensity * beckmann * geometry * fresnel_schlick / (VN * LN * PI);
} }
#endif #endif
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES) && defined(ENABLE_TRANSLUCENT_FOLIAGE) #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES) && defined(ENABLE_TRANSLUCENT_FOLIAGE)
// Simulate translucent foliage. // Simulate translucent foliage.
col.rgb += 4.0 * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) * f_adj_shadow_strength * pow(max(-dot(v_LightDirection, viewVec), 0.0), 4.0) * max(1.0 - shadow_uncorrected, 0.0); col.rgb +=
foliage_translucency * nightFactor * sunTint * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) *
pow(max(-dot(v_LightDirection, viewVec), 0.0), 4.0) * max(1.0 - shadow_uncorrected, 0.0);
#endif #endif
} }
#endif #endif
// Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?), // Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?),
// the fog will only be rendered correctly if the last operation before the // the fog will only be rendered correctly if the last operation before the
// clamp() is an addition. Else, the clamp() seems to be ignored. // clamp() is an addition. Else, the clamp() seems to be ignored.
@ -561,6 +585,8 @@ 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);
#ifdef ENABLE_TINTED_FOG
float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b); float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b);
// Prevent zero division. // Prevent zero division.
if (fogColorMax < 0.0000001) fogColorMax = 1.0; if (fogColorMax < 0.0000001) fogColorMax = 1.0;
@ -568,6 +594,10 @@ void main(void)
// For this to not make the fog color artificially dark we need to normalize using the // 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. // fog color's brightest value. We then blend our base color with this to make the fog.
col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity); col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity);
#else
col = mix(fogColor, col, clarity);
#endif
col = vec4(col.rgb, base.a); col = vec4(col.rgb, base.a);
gl_FragData[0] = col; gl_FragData[0] = col;

View file

@ -45,14 +45,21 @@ centroid varying float nightRatio;
#endif #endif
varying highp vec3 eyeVec; varying highp vec3 eyeVec;
varying vec3 sunTint;
varying float nightFactor;
// Color of the light emitted by the light sources. // 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 e = 2.718281828459;
const float BS = 10.0; const float BS = 10.0;
uniform float xyPerspectiveBias0; uniform float xyPerspectiveBias0;
uniform float xyPerspectiveBias1; uniform float xyPerspectiveBias1;
uniform float zPerspectiveBias; uniform float zPerspectiveBias;
#ifdef ENABLE_TINTED_SUNLIGHT
uniform vec3 scattering_coefficients;
#endif
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
vec4 getRelativePosition(in vec4 position) vec4 getRelativePosition(in vec4 position)
@ -144,8 +151,17 @@ float snoise(vec3 p)
#endif #endif
#ifdef ENABLE_TINTED_SUNLIGHT
vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection)
{
// Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham
const float unit_conversion = 1e-5; // Rayleigh scattering beta
const float atmosphere_height = 15000.; // height of the atmosphere in meters
// sun/moon light at the ground level, after going through the atmosphere
return exp(-scattering_coefficients * unit_conversion * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.))));
}
#endif
void main(void) void main(void)
{ {
@ -205,7 +221,7 @@ void main(void)
// The alpha gives the ratio of sunlight in the incoming light. // The alpha gives the ratio of sunlight in the incoming light.
nightRatio = 1.0 - color.a; nightRatio = 1.0 - color.a;
color.rgb = color.rgb * (color.a * dayLight.rgb + color.rgb = color.rgb * (color.a * dayLight.rgb +
nightRatio * artificialLight.rgb) * 2.0; nightRatio * max(artificialLight.rgb, vec3(0.0))) * 2.0;
color.a = 1.0; color.a = 1.0;
// Emphase blue a bit in darker places // Emphase blue a bit in darker places
@ -255,16 +271,24 @@ void main(void)
#endif #endif
perspective_factor = pFactor; perspective_factor = pFactor;
if (f_timeofday < 0.2) { sunTint = vec3(1.0);
nightFactor = 0.;
// The sun rises at 5:00 and sets at 19:00, which corresponds to 5/24=0.208 and 19/24 = 0.792.
if (f_timeofday < 0.208) {
adj_shadow_strength = f_shadow_strength * 0.5 * adj_shadow_strength = f_shadow_strength * 0.5 *
(1.0 - mtsmoothstep(0.18, 0.2, f_timeofday)); (1.0 - mtsmoothstep(0.178, 0.208, f_timeofday));
} else if (f_timeofday >= 0.8) { } else if (f_timeofday >= 0.792) {
adj_shadow_strength = f_shadow_strength * 0.5 * adj_shadow_strength = f_shadow_strength * 0.5 *
mtsmoothstep(0.8, 0.83, f_timeofday); mtsmoothstep(0.792, 0.822, f_timeofday);
} else { } else {
adj_shadow_strength = f_shadow_strength * adj_shadow_strength = f_shadow_strength *
mtsmoothstep(0.20, 0.25, f_timeofday) * mtsmoothstep(0.208, 0.238, f_timeofday) *
(1.0 - mtsmoothstep(0.7, 0.8, f_timeofday)); (1.0 - mtsmoothstep(0.762, 0.792, f_timeofday));
nightFactor = adj_shadow_strength / f_shadow_strength;
#ifdef ENABLE_TINTED_SUNLIGHT
float tint_strength = 1.0 - mtsmoothstep(0.792, 0.5, f_timeofday) * mtsmoothstep(0.208, 0.5, f_timeofday);
sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), nightFactor * tint_strength);
#endif
} }
} }
#endif #endif

View file

@ -1,5 +1,6 @@
uniform sampler2D baseTexture; uniform sampler2D baseTexture;
varying vec3 sunTint;
uniform vec3 dayLight; uniform vec3 dayLight;
uniform lowp vec4 fogColor; uniform lowp vec4 fogColor;
uniform float fogDistance; uniform float fogDistance;
@ -20,7 +21,6 @@ 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,8 +432,8 @@ void main(void)
// calculate fragment color from components: // calculate fragment color from components:
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 sunTint * (1.0 - adjusted_night_ratio) * ( // natural light
col.rgb * (1.0 - shadow_int * (1.0 - shadow_color) * (1.0 - shadow_tint)) + // filtered texture color col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) + // filtered texture color
dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight
} }
#endif #endif
@ -449,6 +449,8 @@ 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);
#ifdef ENABLE_TINTED_FOG
float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b); float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b);
// Prevent zero division. // Prevent zero division.
if (fogColorMax < 0.0000001) fogColorMax = 1.0; if (fogColorMax < 0.0000001) fogColorMax = 1.0;
@ -456,6 +458,10 @@ void main(void)
// For this to not make the fog color artificially dark we need to normalize using the // 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. // fog color's brightest value. We then blend our base color with this to make the fog.
col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity); col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity);
#else
col = mix(fogColor, col, clarity);
#endif
col = vec4(col.rgb, base.a); col = vec4(col.rgb, base.a);
gl_FragData[0] = col; gl_FragData[0] = col;

View file

@ -32,8 +32,9 @@ centroid varying vec2 varTexCoord;
varying highp vec3 eyeVec; varying highp vec3 eyeVec;
varying float nightRatio; varying float nightRatio;
varying vec3 sunTint;
// Color of the light emitted by the light sources. // 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; varying float vIDiff;
const float e = 2.718281828459; const float e = 2.718281828459;
const float BS = 10.0; const float BS = 10.0;
@ -41,6 +42,10 @@ uniform float xyPerspectiveBias0;
uniform float xyPerspectiveBias1; uniform float xyPerspectiveBias1;
uniform float zPerspectiveBias; uniform float zPerspectiveBias;
#ifdef ENABLE_TINTED_SUNLIGHT
uniform vec3 scattering_coefficients;
#endif
#ifdef ENABLE_DYNAMIC_SHADOWS #ifdef ENABLE_DYNAMIC_SHADOWS
vec4 getRelativePosition(in vec4 position) vec4 getRelativePosition(in vec4 position)
@ -89,6 +94,18 @@ float directional_ambient(vec3 normal)
return dot(v, vec3(0.670820, 1.000000, 0.836660)); return dot(v, vec3(0.670820, 1.000000, 0.836660));
} }
#ifdef ENABLE_TINTED_SUNLIGHT
vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection)
{
// Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham
const float unit_conversion = 1e-5; // Rayleigh scattering beta
const float atmosphere_height = 15000.; // height of the atmosphere in meters
// sun/moon light at the ground level, after going through the atmosphere
return exp(-scattering_coefficients * unit_conversion * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.))));
}
#endif
void main(void) void main(void)
{ {
varTexCoord = (mTexture * vec4(inTexCoord0.xy, 1.0, 1.0)).st; varTexCoord = (mTexture * vec4(inTexCoord0.xy, 1.0, 1.0)).st;
@ -116,7 +133,7 @@ void main(void)
// The alpha gives the ratio of sunlight in the incoming light. // The alpha gives the ratio of sunlight in the incoming light.
nightRatio = 1.0 - color.a; nightRatio = 1.0 - color.a;
color.rgb = color.rgb * (color.a * dayLight.rgb + color.rgb = color.rgb * (color.a * dayLight.rgb +
nightRatio * artificialLight.rgb) * 2.0; nightRatio * max(artificialLight.rgb, vec3(0.0))) * 2.0;
color.a = 1.0; color.a = 1.0;
// Emphase blue a bit in darker places // Emphase blue a bit in darker places
@ -158,16 +175,24 @@ void main(void)
shadow_position.z -= z_bias; shadow_position.z -= z_bias;
perspective_factor = pFactor; perspective_factor = pFactor;
if (f_timeofday < 0.2) { // The sun rises at 5:00 and sets at 19:00, which corresponds to 5/24=0.208 and 19/24 = 0.792.
float nightFactor = 0.;
sunTint = vec3(1.0);
if (f_timeofday < 0.208) {
adj_shadow_strength = f_shadow_strength * 0.5 * adj_shadow_strength = f_shadow_strength * 0.5 *
(1.0 - mtsmoothstep(0.18, 0.2, f_timeofday)); (1.0 - mtsmoothstep(0.178, 0.208, f_timeofday));
} else if (f_timeofday >= 0.8) { } else if (f_timeofday >= 0.792) {
adj_shadow_strength = f_shadow_strength * 0.5 * adj_shadow_strength = f_shadow_strength * 0.5 *
mtsmoothstep(0.8, 0.83, f_timeofday); mtsmoothstep(0.792, 0.822, f_timeofday);
} else { } else {
adj_shadow_strength = f_shadow_strength * adj_shadow_strength = f_shadow_strength *
mtsmoothstep(0.20, 0.25, f_timeofday) * mtsmoothstep(0.208, 0.238, f_timeofday) *
(1.0 - mtsmoothstep(0.7, 0.8, f_timeofday)); (1.0 - mtsmoothstep(0.762, 0.792, f_timeofday));
nightFactor = adj_shadow_strength / f_shadow_strength;
#ifdef ENABLE_TINTED_SUNLIGHT
float tint_strength = 1.0 - mtsmoothstep(0.792, 0.5, f_timeofday) * mtsmoothstep(0.208, 0.5, f_timeofday);
sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), nightFactor * tint_strength);
#endif
} }
} }
#endif #endif

View file

@ -12,6 +12,14 @@ struct ExposureParams {
float compensationFactor; float compensationFactor;
}; };
uniform vec3 cdl_slope;
uniform vec3 cdl_offset;
uniform vec3 cdl_power;
uniform float vignette_dark;
uniform float vignette_bright;
uniform float vignette_power;
uniform sampler2D rendered; uniform sampler2D rendered;
uniform sampler2D bloom; uniform sampler2D bloom;
@ -20,6 +28,7 @@ uniform vec2 texelSize0;
uniform ExposureParams exposureParams; uniform ExposureParams exposureParams;
uniform lowp float bloomIntensity; uniform lowp float bloomIntensity;
uniform lowp float saturation; uniform lowp float saturation;
uniform float gamma;
#ifdef GL_ES #ifdef GL_ES
varying mediump vec2 varTexCoord; varying mediump vec2 varTexCoord;
@ -70,7 +79,6 @@ highp vec3 uncharted2Tonemap(highp vec3 x)
vec4 applyToneMapping(vec4 color) vec4 applyToneMapping(vec4 color)
{ {
color = vec4(pow(color.rgb, vec3(2.2)), color.a); color = vec4(pow(color.rgb, vec3(2.2)), color.a);
const float gamma = 1.6;
const float exposureBias = 5.5; const float exposureBias = 5.5;
color.rgb = uncharted2Tonemap(exposureBias * color.rgb); color.rgb = uncharted2Tonemap(exposureBias * color.rgb);
// Precalculated white_scale from // Precalculated white_scale from
@ -132,8 +140,6 @@ void main(void)
#ifdef ENABLE_BLOOM #ifdef ENABLE_BLOOM
color = applyBloom(color, uv); color = applyBloom(color, uv);
#endif #endif
color.rgb = clamp(color.rgb, vec3(0.), vec3(1.)); color.rgb = clamp(color.rgb, vec3(0.), vec3(1.));
// return to sRGB colorspace (approximate) // return to sRGB colorspace (approximate)
@ -143,10 +149,17 @@ void main(void)
if (uv.x > 0.5 || uv.y > 0.5) if (uv.x > 0.5 || uv.y > 0.5)
#endif #endif
{ {
color.rgb *= (vignette_bright - vignette_dark) * (1.0 - pow(length(uv - vec2(0.5)) * 1.4, vignette_power)) + vignette_dark;
#if ENABLE_TONE_MAPPING #if ENABLE_TONE_MAPPING
color = applyToneMapping(color); color = applyToneMapping(color);
#endif #endif
#ifdef ENABLE_COLOR_GRADING
// ASC CDL color grading
color.rgb = mix(color.rgb, pow(max(color.rgb * cdl_slope + cdl_offset, 0.0), cdl_power), 1.);
#endif
color.rgb = applySaturation(color.rgb, saturation); color.rgb = applySaturation(color.rgb, saturation);
} }

View file

@ -24,6 +24,8 @@ varying mediump vec2 varTexCoord;
centroid varying vec2 varTexCoord; centroid varying vec2 varTexCoord;
#endif #endif
uniform vec3 scattering_coefficients;
const float far = 1000.; const float far = 1000.;
float mapDepth(float depth) float mapDepth(float depth)
{ {
@ -46,23 +48,26 @@ 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;
} }
#ifdef VOLUMETRIC_DEPTH_ATTENUATION
// We use the depth map to approximate the effect of depth on the light intensity. // We use the depth map to approximate the effect of depth on the light intensity.
// The exponent was chosen based on aesthetic preference. // The exponent was chosen based on aesthetic preference.
// To make this phsyically accurate, the brightness here should scale linearly with depth,
// but this would make the godrays either too faint or too strong in many cases.
return result / samples * pow(texture2D(depthmap, uv).r, 128.0); return result / samples * pow(texture2D(depthmap, uv).r, 128.0);
#else
return result / samples;
#endif
} }
vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection) vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection)
{ {
// Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham // Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham
const float beta_r0 = 1e-5; // Rayleigh scattering beta const float unit_conversion = 1e-5; // Rayleigh scattering beta
// 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 const float atmosphere_height = 15000.; // height of the atmosphere in meters
// sun/moon light at the ground level, after going through the atmosphere // sun/moon light at the ground level, after going through the atmosphere
return exp(-beta_r0_l * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.)))); return exp(-scattering_coefficients * unit_conversion * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.))));
} }
vec3 applyVolumetricLight(vec3 color, vec2 uv, float rawDepth) vec3 applyVolumetricLight(vec3 color, vec2 uv, float rawDepth)

View file

@ -9025,6 +9025,12 @@ child will follow movement and rotation of that bone.
but keeping original luma and being symmetrical in terms of saturation but keeping original luma and being symmetrical in terms of saturation
(eg. -1 and 1 is the same saturation and luma, but different hues) (eg. -1 and 1 is the same saturation and luma, but different hues)
* This value has no effect on clients who have shaders or post-processing disabled. * This value has no effect on clients who have shaders or post-processing disabled.
* `foliage_translucency` controls the intensity of the foliage translucency effect (default: `1.5`).
* Subject to change and can be removed at any time.
* This has no effect when dynamic shadows are disabled and on clients who have the "Translucent foliage" effect disabled.
* `specular_intensity` controls the intensity of specular highlights on nodes and liquids (default: `0.0`).
* Subject to change and can be removed at any time.
* This has no effect when dynamic shadows are disabled.
* `shadows` is a table that controls ambient shadows * `shadows` is a table that controls ambient shadows
* This has no effect on clients who have the "Dynamic Shadows" effect disabled. * This has no effect on clients who have the "Dynamic Shadows" effect disabled.
* `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness) * `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness)
@ -9061,6 +9067,24 @@ child will follow movement and rotation of that bone.
* Currently, bloom `intensity` and `strength_factor` affect volumetric * Currently, bloom `intensity` and `strength_factor` affect volumetric
lighting `strength` and vice versa. This behavior is to be changed lighting `strength` and vice versa. This behavior is to be changed
in the future, do not rely on it. in the future, do not rely on it.
* `scattering_coefficients`: the scattering coefficients that control the tint of sunlight during sunrise and sunset.
* Defaults to { x = 3.3362176e-01, y = 8.75378289198826e-01, z = 1.95342379700656} which is physically accurate.
* This may be used to create effects like differently colored sunsets on alien planets.
* Setting all components to zero effectively disables tinted sunlight.
* `vignette`: is a table that controls the vignette post-processing effect.
* This has no effect on clients who have post processing disabled.
* `dark`: brightness of the vignette's darkest part (default: `1.0`)
* `bright`: brightness of the vignette's brightest part (default: `1.0`)
* `power`: the higher this is set, the more the vignette "retreats" to the edges of the screen (default: `1.0`)
* `cdl`: is a table that controls the ASL CDL color grading effect.
* This has no effect on clients who have the "Color grading" effect disabled.
* The output color follows the equation: `out = pow(in*slope+offset, power)`
* `slope`: "Tints" the scene, affects brighter colors more (default: `{x=1.2, y=1.0, z=0.8}`)
* `offset`: This can be used to brighten or darken the scene (default: `{x=0.0, y=0.0, z=0.0}`)
* `power`: Tints mostly the darker parts of the scene (default: `{x=1.25, y=1.0, z=0.9}`)
* `artificial_light`: is a table that controls the color of artificial light (torches etc.).
* Values should be positive and vaguely around `1.0`, but can be higher or lower.
* Default: `{r=1.04, g=1.04, b=1.04}`
* `get_lighting()`: returns the current state of lighting for the player. * `get_lighting()`: returns the current state of lighting for the player.
* Result is a table with the same fields as `light_definition` in `set_lighting`. * Result is a table with the same fields as `light_definition` in `set_lighting`.

View file

@ -199,12 +199,14 @@ class GameGlobalShaderUniformSetter : public IShaderUniformSetter
m_animation_timer_delta_vertex{"animationTimerDelta"}; m_animation_timer_delta_vertex{"animationTimerDelta"};
CachedPixelShaderSetting<float> CachedPixelShaderSetting<float>
m_animation_timer_delta_pixel{"animationTimerDelta"}; m_animation_timer_delta_pixel{"animationTimerDelta"};
CachedPixelShaderSetting<float, 3> m_artificial_light{ "artificialLight" };
CachedPixelShaderSetting<float, 3> m_day_light{"dayLight"}; CachedPixelShaderSetting<float, 3> m_day_light{"dayLight"};
CachedPixelShaderSetting<float, 3> m_minimap_yaw{"yawVec"}; CachedPixelShaderSetting<float, 3> m_minimap_yaw{"yawVec"};
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel{"cameraOffset"}; CachedPixelShaderSetting<float> m_minimap_size{"mapSize"};
CachedVertexShaderSetting<float, 3> m_camera_offset_vertex{"cameraOffset"}; CachedVertexShaderSetting<float, 3> m_camera_offset_vertex{"cameraOffset"};
CachedPixelShaderSetting<float, 3> m_camera_position_pixel{ "cameraPosition" }; CachedPixelShaderSetting<float, 3> m_camera_offset_pixel{ "cameraOffset" };
CachedVertexShaderSetting<float, 3> m_camera_position_vertex{"cameraPosition"}; CachedVertexShaderSetting<float, 3> m_camera_position_vertex{"cameraPosition"};
CachedPixelShaderSetting<float, 3> m_camera_position_pixel{"cameraPosition"};
CachedVertexShaderSetting<float, 2> m_texel_size0_vertex{"texelSize0"}; CachedVertexShaderSetting<float, 2> m_texel_size0_vertex{"texelSize0"};
CachedPixelShaderSetting<float, 2> m_texel_size0_pixel{"texelSize0"}; CachedPixelShaderSetting<float, 2> m_texel_size0_pixel{"texelSize0"};
v2f m_texel_size0; v2f m_texel_size0;
@ -221,6 +223,8 @@ class GameGlobalShaderUniformSetter : public IShaderUniformSetter
CachedPixelShaderSetting<float> m_bloom_strength_pixel{"bloomStrength"}; CachedPixelShaderSetting<float> m_bloom_strength_pixel{"bloomStrength"};
CachedPixelShaderSetting<float> m_bloom_radius_pixel{"bloomRadius"}; CachedPixelShaderSetting<float> m_bloom_radius_pixel{"bloomRadius"};
CachedPixelShaderSetting<float> m_saturation_pixel{"saturation"}; CachedPixelShaderSetting<float> m_saturation_pixel{"saturation"};
float m_gamma;
CachedPixelShaderSetting<float> m_gamma_pixel{"gamma"};
bool m_volumetric_light_enabled; bool m_volumetric_light_enabled;
CachedPixelShaderSetting<float, 3> CachedPixelShaderSetting<float, 3>
m_sun_position_pixel{"sunPositionScreen"}; m_sun_position_pixel{"sunPositionScreen"};
@ -230,6 +234,18 @@ class GameGlobalShaderUniformSetter : public IShaderUniformSetter
CachedPixelShaderSetting<float> m_moon_brightness_pixel{"moonBrightness"}; CachedPixelShaderSetting<float> m_moon_brightness_pixel{"moonBrightness"};
CachedPixelShaderSetting<float> CachedPixelShaderSetting<float>
m_volumetric_light_strength_pixel{"volumetricLightStrength"}; m_volumetric_light_strength_pixel{"volumetricLightStrength"};
CachedPixelShaderSetting<float, 3>
m_atmospheric_scattering_coefficients_pixel{ "scattering_coefficients" };
CachedVertexShaderSetting<float, 3>
m_atmospheric_scattering_coefficients_vertex{ "scattering_coefficients" };
CachedPixelShaderSetting<float, 3> m_cdl_slope_pixel{"cdl_slope"};
CachedPixelShaderSetting<float, 3> m_cdl_offset_pixel{"cdl_offset"};
CachedPixelShaderSetting<float, 3> m_cdl_power_pixel{"cdl_power"};
CachedPixelShaderSetting<float> m_vignette_dark_pixel{"vignette_dark"};
CachedPixelShaderSetting<float> m_vignette_bright_pixel{"vignette_bright"};
CachedPixelShaderSetting<float> m_vignette_power_pixel{"vignette_power"};
CachedPixelShaderSetting<float> m_foliage_translucency_pixel{ "foliage_translucency" };
CachedPixelShaderSetting<float> m_specular_intensity_pixel{ "specular_intensity" };
static constexpr std::array<const char*, 1> SETTING_CALLBACKS = { static constexpr std::array<const char*, 1> SETTING_CALLBACKS = {
"exposure_compensation", "exposure_compensation",
@ -259,6 +275,7 @@ public:
m_user_exposure_compensation = g_settings->getFloat("exposure_compensation", -1.0f, 1.0f); m_user_exposure_compensation = g_settings->getFloat("exposure_compensation", -1.0f, 1.0f);
m_bloom_enabled = g_settings->getBool("enable_bloom"); m_bloom_enabled = g_settings->getBool("enable_bloom");
m_volumetric_light_enabled = g_settings->getBool("enable_volumetric_lighting") && m_bloom_enabled; m_volumetric_light_enabled = g_settings->getBool("enable_volumetric_lighting") && m_bloom_enabled;
m_gamma = g_settings->getFloat("secondstage_gamma");
} }
~GameGlobalShaderUniformSetter() ~GameGlobalShaderUniformSetter()
@ -285,14 +302,16 @@ public:
if (m_client->getMinimap()) { if (m_client->getMinimap()) {
v3f minimap_yaw = m_client->getMinimap()->getYawVec(); v3f minimap_yaw = m_client->getMinimap()->getYawVec();
m_minimap_yaw.set(minimap_yaw, services); m_minimap_yaw.set(minimap_yaw, services);
float minimap_size = m_client->getMinimap()->getModeDef().map_size;
m_minimap_size.set(&minimap_size, services);
} }
v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS); v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS);
m_camera_offset_pixel.set(offset, services);
m_camera_offset_vertex.set(offset, services); m_camera_offset_vertex.set(offset, services);
m_camera_offset_pixel.set(offset, services);
v3f camera_position = m_client->getCamera()->getPosition(); v3f camera_position = m_client->getCamera()->getPosition();
m_camera_position_pixel.set(camera_position, services); m_camera_position_vertex.set(camera_position, services);
m_camera_position_pixel.set(camera_position, services); m_camera_position_pixel.set(camera_position, services);
m_texel_size0_vertex.set(m_texel_size0, services); m_texel_size0_vertex.set(m_texel_size0, services);
@ -323,6 +342,24 @@ public:
float saturation = lighting.saturation; float saturation = lighting.saturation;
m_saturation_pixel.set(&saturation, services); m_saturation_pixel.set(&saturation, services);
video::SColorf artificial_light = lighting.artificial_light_color;
m_artificial_light.set(artificial_light, services);
float gamma = m_gamma;
m_gamma_pixel.set(&gamma, services);
const Vignette &vignette_params = lighting.vignette;
m_vignette_dark_pixel.set(&vignette_params.dark, services);
m_vignette_bright_pixel.set(&vignette_params.bright, services);
m_vignette_power_pixel.set(&vignette_params.power, services);
m_foliage_translucency_pixel.set(&lighting.foliage_translucency, services);
m_specular_intensity_pixel.set(&lighting.specular_intensity, services);
const ColorDecisionList& cdl_params = lighting.cdl;
m_cdl_slope_pixel.set(cdl_params.slope, services);
m_cdl_offset_pixel.set(cdl_params.offset, services);
m_cdl_power_pixel.set(cdl_params.power, services);
if (m_volumetric_light_enabled) { if (m_volumetric_light_enabled) {
// Map directional light to screen space // Map directional light to screen space
@ -367,6 +404,10 @@ public:
float volumetric_light_strength = lighting.volumetric_light_strength; float volumetric_light_strength = lighting.volumetric_light_strength;
m_volumetric_light_strength_pixel.set(&volumetric_light_strength, services); m_volumetric_light_strength_pixel.set(&volumetric_light_strength, services);
} }
v3f scattering_coefficients = lighting.scattering_coefficients;
m_atmospheric_scattering_coefficients_vertex.set(scattering_coefficients, services);
m_atmospheric_scattering_coefficients_pixel.set(scattering_coefficients, services);
} }
void onSetMaterial(const video::SMaterial &material) override void onSetMaterial(const video::SMaterial &material) override
@ -461,8 +502,9 @@ public:
#undef PROVIDE #undef PROVIDE
bool enable_waving_water = g_settings->getBool("enable_waving_water"); bool enable_waving_water = g_settings->getBool("enable_waving_water");
bool enable_water_reflections = g_settings->getBool("enable_water_reflections");
constants["ENABLE_WAVING_WATER"] = enable_waving_water ? 1 : 0; constants["ENABLE_WAVING_WATER"] = enable_waving_water ? 1 : 0;
if (enable_waving_water) { if (enable_waving_water || enable_water_reflections) {
constants["WATER_WAVE_HEIGHT"] = g_settings->getFloat("water_wave_height"); constants["WATER_WAVE_HEIGHT"] = g_settings->getFloat("water_wave_height");
constants["WATER_WAVE_LENGTH"] = g_settings->getFloat("water_wave_length"); constants["WATER_WAVE_LENGTH"] = g_settings->getFloat("water_wave_length");
constants["WATER_WAVE_SPEED"] = g_settings->getFloat("water_wave_speed"); constants["WATER_WAVE_SPEED"] = g_settings->getFloat("water_wave_speed");

View file

@ -589,8 +589,8 @@ void Minimap::drawMinimap(core::rect<s32> rect)
video::SMaterial &material = m_meshbuffer->getMaterial(); video::SMaterial &material = m_meshbuffer->getMaterial();
material.forEachTexture([] (auto &tex) { material.forEachTexture([] (auto &tex) {
tex.MinFilter = video::ETMINF_LINEAR_MIPMAP_LINEAR; tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
tex.MagFilter = video::ETMAGF_LINEAR; tex.MagFilter = video::ETMAGF_NEAREST;
}); });
material.TextureLayers[0].Texture = minimap_texture; material.TextureLayers[0].Texture = minimap_texture;
material.TextureLayers[1].Texture = data->heightmap_texture; material.TextureLayers[1].Texture = data->heightmap_texture;

View file

@ -225,6 +225,9 @@ public:
float shadow_soft_radius = std::max(1.f, float shadow_soft_radius = std::max(1.f,
g_settings->getFloat("shadow_soft_radius")); g_settings->getFloat("shadow_soft_radius"));
constants["SOFTSHADOWRADIUS"] = shadow_soft_radius; constants["SOFTSHADOWRADIUS"] = shadow_soft_radius;
if (g_settings->getBool("enable_sun_tint"))
constants["ENABLE_TINTED_SUNLIGHT"] = 1;
} }
if (g_settings->getBool("enable_bloom")) { if (g_settings->getBool("enable_bloom")) {
@ -731,6 +734,10 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
shaders_header << '\n'; shaders_header << '\n';
} }
if (g_settings->getBool("enable_volumetric_depth_attenuation")) {
shaders_header << "#define VOLUMETRIC_DEPTH_ATTENUATION 1\n";
}
std::string common_header = shaders_header.str(); std::string common_header = shaders_header.str();
const char *final_header = "#line 0\n"; // reset the line counter for meaningful diagnostics const char *final_header = "#line 0\n"; // reset the line counter for meaningful diagnostics

View file

@ -333,13 +333,16 @@ void set_default_settings()
settings->setDefault("enable_waving_plants", "false"); settings->setDefault("enable_waving_plants", "false");
settings->setDefault("exposure_compensation", "0.0"); settings->setDefault("exposure_compensation", "0.0");
settings->setDefault("enable_auto_exposure", "false"); settings->setDefault("enable_auto_exposure", "false");
settings->setDefault("secondstage_gamma", "1.6");
settings->setDefault("debanding", "true"); settings->setDefault("debanding", "true");
settings->setDefault("antialiasing", "none"); settings->setDefault("antialiasing", "none");
settings->setDefault("enable_bloom", "false"); settings->setDefault("enable_bloom", "false");
settings->setDefault("enable_bloom_debug", "false"); settings->setDefault("enable_bloom_debug", "false");
settings->setDefault("enable_volumetric_lighting", "false"); settings->setDefault("enable_volumetric_lighting", "false");
settings->setDefault("enable_volumetric_depth_attenuation", "false");
settings->setDefault("enable_water_reflections", "false"); settings->setDefault("enable_water_reflections", "false");
settings->setDefault("enable_translucent_foliage", "false"); settings->setDefault("enable_translucent_foliage", "false");
settings->setDefault("enable_tinted_fog", "false");
// Effects Shadows // Effects Shadows
settings->setDefault("enable_dynamic_shadows", "false"); settings->setDefault("enable_dynamic_shadows", "false");
@ -353,6 +356,7 @@ void set_default_settings()
settings->setDefault("shadow_update_frames", "16"); settings->setDefault("shadow_update_frames", "16");
settings->setDefault("shadow_soft_radius", "5.0"); settings->setDefault("shadow_soft_radius", "5.0");
settings->setDefault("shadow_sky_body_orbit_tilt", "0.0"); settings->setDefault("shadow_sky_body_orbit_tilt", "0.0");
settings->setDefault("enable_sun_tint", "false");
// Input // Input
settings->setDefault("invert_mouse", "false"); settings->setDefault("invert_mouse", "false");

View file

@ -4,8 +4,7 @@
#pragma once #pragma once
#include "SColor.h" #include "SColor.h"
#include "irr_v3d.h"
using namespace irr;
/** /**
* Parameters for automatic exposure compensation * Parameters for automatic exposure compensation
@ -40,14 +39,49 @@ struct AutoExposure
{} {}
}; };
/**
* Parameters for vignette in post-processing
*
*/
struct Vignette {
/// @brief The darkest part of the vignette will be darkened/brightened by this factor.
float dark = 1.0f;
/// @brief The brightest part of the vignette will be darkened/brightened by this factor.
float bright = 1.0f;
/// @brief Describes the blending between dark and bright. Higher values mean darkening is more intense at the screen edges.
float power = 1.0f;
};
/**
* ASL CDL parameters
*
* Colors in ASL CDL follow the following equation:
*
* out = pow(in * slope + offset, power)
*
*/
struct ColorDecisionList {
v3f slope{1.0, 1.0, 1.0};
v3f offset{0.0, 0.0, 0.0};
v3f power{1.0, 1.0, 1.0};
};
/** Describes ambient light settings for a player /** Describes ambient light settings for a player
*/ */
struct Lighting struct Lighting
{ {
AutoExposure exposure; AutoExposure exposure;
Vignette vignette;
ColorDecisionList cdl;
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};
float foliage_translucency{1.5f};
float specular_intensity{0.0f};
// These factors are calculated based on expected value of scattering factor of 1e-5
// for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere
v3f scattering_coefficients{ 3.3362176e-01f, 8.753783e-01f, 1.9534237f };
video::SColorf artificial_light_color{ 1.0f, 1.04f, 1.04f, 1.04f };
video::SColor shadow_tint {255, 0, 0, 0}; video::SColor shadow_tint {255, 0, 0, 0};
float bloom_intensity {0.05f}; float bloom_intensity {0.05f};
float bloom_strength_factor {1.0f}; float bloom_strength_factor {1.0f};

View file

@ -62,7 +62,7 @@ private:
// These calls explicitly use the templated version of operator<<, // These calls explicitly use the templated version of operator<<,
// so that they won't use the overloads created by ADD_NULL_CHECK. // so that they won't use the overloads created by ADD_NULL_CHECK.
if (arg == nullptr) if (arg == nullptr)
return this->operator<< <const char*> ("(null)"); return this->operator<< ((const char*) ("(null)"));
else else
return this->operator<< <T>(std::forward<T>(arg)); return this->operator<< <T>(std::forward<T>(arg));
} }

View file

@ -1795,4 +1795,18 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
>> lighting.bloom_strength_factor >> lighting.bloom_strength_factor
>> lighting.bloom_radius; >> lighting.bloom_radius;
} }
if (pkt->getRemainingBytes() >= 72) {
*pkt >> lighting.artificial_light_color.r
>> lighting.artificial_light_color.g
>> lighting.artificial_light_color.b;
*pkt >> lighting.scattering_coefficients;
*pkt >> lighting.vignette.dark
>> lighting.vignette.bright
>> lighting.vignette.power;
*pkt >> lighting.cdl.slope;
*pkt >> lighting.cdl.offset;
*pkt >> lighting.cdl.power;
*pkt >> lighting.foliage_translucency;
*pkt >> lighting.specular_intensity;
}
} }

View file

@ -63,7 +63,8 @@
Add particle blend mode "clip" Add particle blend mode "clip"
[scheduled bump for 5.11.0] [scheduled bump for 5.11.0]
PROTOCOL VERSION 48 PROTOCOL VERSION 48
Add compression to some existing packets Add compression to some existing packets, artificial light color, scattering_coefficients,
vignette, specular intensity, foliage translucency and cdl parameters to Lighting packets
[scheduled bump for 5.12.0] [scheduled bump for 5.12.0]
*/ */

View file

@ -2660,6 +2660,15 @@ int ObjectRef::l_set_lighting(lua_State *L)
if (!lua_isnoneornil(L, 2)) { if (!lua_isnoneornil(L, 2)) {
luaL_checktype(L, 2, LUA_TTABLE); luaL_checktype(L, 2, LUA_TTABLE);
lighting = player->getLighting(); lighting = player->getLighting();
lua_getfield(L, 2, "artificial_light");
if (lua_istable(L, -1)) {
getfloatfield(L, -1, "r", lighting.artificial_light_color.r);
getfloatfield(L, -1, "g", lighting.artificial_light_color.g);
getfloatfield(L, -1, "b", lighting.artificial_light_color.b);
}
lua_pop(L, 1); // artificial_light
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);
@ -2670,6 +2679,8 @@ int ObjectRef::l_set_lighting(lua_State *L)
lua_pop(L, 1); // shadows lua_pop(L, 1); // shadows
getfloatfield(L, -1, "saturation", lighting.saturation); getfloatfield(L, -1, "saturation", lighting.saturation);
getfloatfield(L, -1, "foliage_translucency", lighting.foliage_translucency);
getfloatfield(L, -1, "specular_intensity", lighting.specular_intensity);
lua_getfield(L, 2, "exposure"); lua_getfield(L, 2, "exposure");
if (lua_istable(L, -1)) { if (lua_istable(L, -1)) {
@ -2686,6 +2697,12 @@ int ObjectRef::l_set_lighting(lua_State *L)
if (lua_istable(L, -1)) { if (lua_istable(L, -1)) {
getfloatfield(L, -1, "strength", lighting.volumetric_light_strength); getfloatfield(L, -1, "strength", lighting.volumetric_light_strength);
lighting.volumetric_light_strength = rangelim(lighting.volumetric_light_strength, 0.0f, 1.0f); lighting.volumetric_light_strength = rangelim(lighting.volumetric_light_strength, 0.0f, 1.0f);
lua_getfield(L, -1, "scattering_coefficients");
if (!lua_isnil(L, -1)) {
lighting.scattering_coefficients = read_v3f(L, -1);
}
lua_pop(L, 1); // scattering_coefficients
} }
lua_pop(L, 1); // volumetric_light lua_pop(L, 1); // volumetric_light
@ -2696,6 +2713,31 @@ int ObjectRef::l_set_lighting(lua_State *L)
lighting.bloom_radius = getfloatfield_default(L, -1, "radius", lighting.bloom_radius); lighting.bloom_radius = getfloatfield_default(L, -1, "radius", lighting.bloom_radius);
} }
lua_pop(L, 1); // bloom lua_pop(L, 1); // bloom
lua_getfield(L, 2, "vignette");
if (lua_istable(L, -1)) {
getfloatfield(L, -1, "dark", lighting.vignette.dark);
getfloatfield(L, -1, "bright", lighting.vignette.bright);
getfloatfield(L, -1, "power", lighting.vignette.power);
}
lua_pop(L, 1); // vignette
lua_getfield(L, 2, "cdl");
if (lua_istable(L, -1)) {
lua_getfield(L, -1, "slope");
if (!lua_isnil(L, -1))
lighting.cdl.slope = read_v3f(L, -1);
lua_pop(L, 1); // slope
lua_getfield(L, -1, "offset");
if (!lua_isnil(L, -1))
lighting.cdl.offset = read_v3f(L, -1);
lua_pop(L, 1); // offset
lua_getfield(L, -1, "power");
if (!lua_isnil(L, -1))
lighting.cdl.power = read_v3f(L, -1);
lua_pop(L, 1); // power
}
lua_pop(L, 1); // cdl
} }
getServer(L)->setLighting(player, lighting); getServer(L)->setLighting(player, lighting);
@ -2714,6 +2756,18 @@ int ObjectRef::l_get_lighting(lua_State *L)
const Lighting &lighting = player->getLighting(); const Lighting &lighting = player->getLighting();
lua_newtable(L); // result lua_newtable(L); // result
lua_newtable(L); // artificial_light
lua_pushnumber(L, lighting.artificial_light_color.r);
lua_setfield(L, -2, "r");
lua_pushnumber(L, lighting.artificial_light_color.g);
lua_setfield(L, -2, "g");
lua_pushnumber(L, lighting.artificial_light_color.b);
lua_setfield(L, -2, "b");
lua_setfield(L, -2, "artificial_light");
lua_pushnumber(L, lighting.foliage_translucency);
lua_setfield(L, -2, "foliage_translucency");
lua_pushnumber(L, lighting.specular_intensity);
lua_setfield(L, -2, "specular_intensity");
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");
@ -2739,6 +2793,8 @@ int ObjectRef::l_get_lighting(lua_State *L)
lua_newtable(L); // "volumetric_light" lua_newtable(L); // "volumetric_light"
lua_pushnumber(L, lighting.volumetric_light_strength); lua_pushnumber(L, lighting.volumetric_light_strength);
lua_setfield(L, -2, "strength"); lua_setfield(L, -2, "strength");
push_v3f(L, lighting.scattering_coefficients);
lua_setfield(L, -2, "scattering_coefficients");
lua_setfield(L, -2, "volumetric_light"); lua_setfield(L, -2, "volumetric_light");
lua_newtable(L); // "bloom" lua_newtable(L); // "bloom"
lua_pushnumber(L, lighting.bloom_intensity); lua_pushnumber(L, lighting.bloom_intensity);
@ -2748,6 +2804,22 @@ int ObjectRef::l_get_lighting(lua_State *L)
lua_pushnumber(L, lighting.bloom_radius); lua_pushnumber(L, lighting.bloom_radius);
lua_setfield(L, -2, "radius"); lua_setfield(L, -2, "radius");
lua_setfield(L, -2, "bloom"); lua_setfield(L, -2, "bloom");
lua_newtable(L); // "vignette"
lua_pushnumber(L, lighting.vignette.dark);
lua_setfield(L, -2, "dark");
lua_pushnumber(L, lighting.vignette.bright);
lua_setfield(L, -2, "bright");
lua_pushnumber(L, lighting.vignette.power);
lua_setfield(L, -2, "power");
lua_setfield(L, -2, "vignette");
lua_newtable(L); // "cdl"
push_v3f(L, lighting.cdl.slope);
lua_setfield(L, -2, "slope");
push_v3f(L, lighting.cdl.offset);
lua_setfield(L, -2, "offset");
push_v3f(L, lighting.cdl.power);
lua_setfield(L, -2, "power");
lua_setfield(L, -2, "cdl");
return 1; return 1;
} }

View file

@ -1951,6 +1951,18 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
pkt << lighting.volumetric_light_strength << lighting.shadow_tint; pkt << lighting.volumetric_light_strength << lighting.shadow_tint;
pkt << lighting.bloom_intensity << lighting.bloom_strength_factor << pkt << lighting.bloom_intensity << lighting.bloom_strength_factor <<
lighting.bloom_radius; lighting.bloom_radius;
pkt << lighting.artificial_light_color.r
<< lighting.artificial_light_color.g
<< lighting.artificial_light_color.b;
pkt << lighting.scattering_coefficients;
pkt << lighting.vignette.dark
<< lighting.vignette.bright
<< lighting.vignette.power;
pkt << lighting.cdl.slope;
pkt << lighting.cdl.offset;
pkt << lighting.cdl.power;
pkt << lighting.foliage_translucency;
pkt << lighting.specular_intensity;
Send(&pkt); Send(&pkt);
} }