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.
# Default is 1.0 (1/2 node).
#
# Requires: enable_waving_water
water_wave_height (Waving liquids wave height) float 1.0 0.0 4.0
# Length of liquid waves.
#
# Requires: enable_waving_water
water_wave_length (Waving liquids wavelength) float 20.0 0.1
# How fast liquid waves will move. Higher = faster.
# If negative, liquid waves will move backwards.
#
# Requires: enable_waving_water
water_wave_speed (Waving liquids wave speed) float 5.0
# When enabled, crude liquid reflections are simulated.
# Wave height, length and speed will affect these reflections.
#
# Requires: enable_dynamic_shadows
enable_water_reflections (Liquid reflections) bool false
[**Dynamic shadows]
# 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
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]
# Enables the post processing pipeline.
@ -778,6 +786,19 @@ enable_auto_exposure (Enable Automatic Exposure) bool false
# Requires: enable_post_processing, enable_auto_exposure
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.
# Dithering significantly increases the size of losslessly-compressed
# 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").
#
# 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]
# Makes the color of light fog more saturated.
enable_tinted_fog (Tinted fog) bool false
# 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
enable_translucent_foliage (Translucent foliage) bool false

View file

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

View file

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

View file

@ -45,14 +45,21 @@ centroid varying float nightRatio;
#endif
varying highp vec3 eyeVec;
varying vec3 sunTint;
varying float nightFactor;
// Color of the light emitted by the light sources.
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
uniform vec3 artificialLight;
const float e = 2.718281828459;
const float BS = 10.0;
uniform float xyPerspectiveBias0;
uniform float xyPerspectiveBias1;
uniform float zPerspectiveBias;
#ifdef ENABLE_TINTED_SUNLIGHT
uniform vec3 scattering_coefficients;
#endif
#ifdef ENABLE_DYNAMIC_SHADOWS
vec4 getRelativePosition(in vec4 position)
@ -144,8 +151,17 @@ float snoise(vec3 p)
#endif
#ifdef ENABLE_TINTED_SUNLIGHT
vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection)
{
// Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham
const float 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)
{
@ -205,7 +221,7 @@ void main(void)
// The alpha gives the ratio of sunlight in the incoming light.
nightRatio = 1.0 - color.a;
color.rgb = color.rgb * (color.a * dayLight.rgb +
nightRatio * artificialLight.rgb) * 2.0;
nightRatio * max(artificialLight.rgb, vec3(0.0))) * 2.0;
color.a = 1.0;
// Emphase blue a bit in darker places
@ -255,16 +271,24 @@ void main(void)
#endif
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 *
(1.0 - mtsmoothstep(0.18, 0.2, f_timeofday));
} else if (f_timeofday >= 0.8) {
(1.0 - mtsmoothstep(0.178, 0.208, f_timeofday));
} else if (f_timeofday >= 0.792) {
adj_shadow_strength = f_shadow_strength * 0.5 *
mtsmoothstep(0.8, 0.83, f_timeofday);
mtsmoothstep(0.792, 0.822, f_timeofday);
} else {
adj_shadow_strength = f_shadow_strength *
mtsmoothstep(0.20, 0.25, f_timeofday) *
(1.0 - mtsmoothstep(0.7, 0.8, f_timeofday));
mtsmoothstep(0.208, 0.238, f_timeofday) *
(1.0 - mtsmoothstep(0.762, 0.792, f_timeofday));
nightFactor = adj_shadow_strength / f_shadow_strength;
#ifdef ENABLE_TINTED_SUNLIGHT
float tint_strength = 1.0 - mtsmoothstep(0.792, 0.5, f_timeofday) * mtsmoothstep(0.208, 0.5, f_timeofday);
sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), nightFactor * tint_strength);
#endif
}
}
#endif

View file

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

View file

@ -32,8 +32,9 @@ centroid varying vec2 varTexCoord;
varying highp vec3 eyeVec;
varying float nightRatio;
varying vec3 sunTint;
// Color of the light emitted by the light sources.
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
uniform vec3 artificialLight;
varying float vIDiff;
const float e = 2.718281828459;
const float BS = 10.0;
@ -41,6 +42,10 @@ uniform float xyPerspectiveBias0;
uniform float xyPerspectiveBias1;
uniform float zPerspectiveBias;
#ifdef ENABLE_TINTED_SUNLIGHT
uniform vec3 scattering_coefficients;
#endif
#ifdef ENABLE_DYNAMIC_SHADOWS
vec4 getRelativePosition(in vec4 position)
@ -89,6 +94,18 @@ float directional_ambient(vec3 normal)
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)
{
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.
nightRatio = 1.0 - color.a;
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;
// Emphase blue a bit in darker places
@ -158,16 +175,24 @@ void main(void)
shadow_position.z -= z_bias;
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 *
(1.0 - mtsmoothstep(0.18, 0.2, f_timeofday));
} else if (f_timeofday >= 0.8) {
(1.0 - mtsmoothstep(0.178, 0.208, f_timeofday));
} else if (f_timeofday >= 0.792) {
adj_shadow_strength = f_shadow_strength * 0.5 *
mtsmoothstep(0.8, 0.83, f_timeofday);
mtsmoothstep(0.792, 0.822, f_timeofday);
} else {
adj_shadow_strength = f_shadow_strength *
mtsmoothstep(0.20, 0.25, f_timeofday) *
(1.0 - mtsmoothstep(0.7, 0.8, f_timeofday));
mtsmoothstep(0.208, 0.238, f_timeofday) *
(1.0 - mtsmoothstep(0.762, 0.792, f_timeofday));
nightFactor = adj_shadow_strength / f_shadow_strength;
#ifdef ENABLE_TINTED_SUNLIGHT
float tint_strength = 1.0 - mtsmoothstep(0.792, 0.5, f_timeofday) * mtsmoothstep(0.208, 0.5, f_timeofday);
sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), nightFactor * tint_strength);
#endif
}
}
#endif

View file

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

View file

@ -24,6 +24,8 @@ varying mediump vec2 varTexCoord;
centroid varying vec2 varTexCoord;
#endif
uniform vec3 scattering_coefficients;
const float far = 1000.;
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.)
result += texture2D(depthmap, samplepos).r < 1. ? 0.0 : 1.0;
}
#ifdef VOLUMETRIC_DEPTH_ATTENUATION
// We use the depth map to approximate the effect of depth on the light intensity.
// The exponent was chosen based on aesthetic preference.
// To make this phsyically accurate, the brightness here should scale linearly with depth,
// but this would make the godrays either too faint or too strong in many cases.
return result / samples * pow(texture2D(depthmap, uv).r, 128.0);
#else
return result / samples;
#endif
}
vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection)
{
// Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham
const float beta_r0 = 1e-5; // Rayleigh scattering beta
// These factors are calculated based on expected value of scattering factor of 1e-5
// for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere
const vec3 beta_r0_l = vec3(3.3362176e-01, 8.75378289198826e-01, 1.95342379700656) * beta_r0; // wavelength-dependent scattering
const float unit_conversion = 1e-5; // Rayleigh scattering beta
const float atmosphere_height = 15000.; // height of the atmosphere in meters
// sun/moon light at the ground level, after going through the atmosphere
return exp(-beta_r0_l * 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)

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
(eg. -1 and 1 is the same saturation and luma, but different hues)
* This value has no effect on clients who have shaders or post-processing disabled.
* `foliage_translucency` controls the intensity of the foliage translucency effect (default: `1.5`).
* Subject to change and can be removed at any time.
* This has no effect when dynamic shadows are disabled and on clients who have the "Translucent foliage" effect disabled.
* `specular_intensity` controls the intensity of specular highlights on nodes and liquids (default: `0.0`).
* Subject to change and can be removed at any time.
* This has no effect when dynamic shadows are disabled.
* `shadows` is a table that controls ambient shadows
* This has no effect on clients who have the "Dynamic Shadows" effect disabled.
* `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness)
@ -9061,6 +9067,24 @@ child will follow movement and rotation of that bone.
* Currently, bloom `intensity` and `strength_factor` affect volumetric
lighting `strength` and vice versa. This behavior is to be changed
in the future, do not rely on it.
* `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.
* 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"};
CachedPixelShaderSetting<float>
m_animation_timer_delta_pixel{"animationTimerDelta"};
CachedPixelShaderSetting<float, 3> m_artificial_light{ "artificialLight" };
CachedPixelShaderSetting<float, 3> m_day_light{"dayLight"};
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"};
CachedPixelShaderSetting<float, 3> m_camera_position_pixel{ "cameraPosition" };
CachedVertexShaderSetting<float, 3> m_camera_position_vertex{ "cameraPosition" };
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel{ "cameraOffset" };
CachedVertexShaderSetting<float, 3> m_camera_position_vertex{"cameraPosition"};
CachedPixelShaderSetting<float, 3> m_camera_position_pixel{"cameraPosition"};
CachedVertexShaderSetting<float, 2> m_texel_size0_vertex{"texelSize0"};
CachedPixelShaderSetting<float, 2> m_texel_size0_pixel{"texelSize0"};
v2f m_texel_size0;
@ -221,6 +223,8 @@ class GameGlobalShaderUniformSetter : public IShaderUniformSetter
CachedPixelShaderSetting<float> m_bloom_strength_pixel{"bloomStrength"};
CachedPixelShaderSetting<float> m_bloom_radius_pixel{"bloomRadius"};
CachedPixelShaderSetting<float> m_saturation_pixel{"saturation"};
float m_gamma;
CachedPixelShaderSetting<float> m_gamma_pixel{"gamma"};
bool m_volumetric_light_enabled;
CachedPixelShaderSetting<float, 3>
m_sun_position_pixel{"sunPositionScreen"};
@ -230,6 +234,18 @@ class GameGlobalShaderUniformSetter : public IShaderUniformSetter
CachedPixelShaderSetting<float> m_moon_brightness_pixel{"moonBrightness"};
CachedPixelShaderSetting<float>
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 = {
"exposure_compensation",
@ -259,6 +275,7 @@ public:
m_user_exposure_compensation = g_settings->getFloat("exposure_compensation", -1.0f, 1.0f);
m_bloom_enabled = g_settings->getBool("enable_bloom");
m_volumetric_light_enabled = g_settings->getBool("enable_volumetric_lighting") && m_bloom_enabled;
m_gamma = g_settings->getFloat("secondstage_gamma");
}
~GameGlobalShaderUniformSetter()
@ -285,14 +302,16 @@ public:
if (m_client->getMinimap()) {
v3f minimap_yaw = m_client->getMinimap()->getYawVec();
m_minimap_yaw.set(minimap_yaw, services);
float minimap_size = m_client->getMinimap()->getModeDef().map_size;
m_minimap_size.set(&minimap_size, services);
}
v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS);
m_camera_offset_pixel.set(offset, services);
m_camera_offset_vertex.set(offset, services);
m_camera_offset_pixel.set(offset, services);
v3f camera_position = m_client->getCamera()->getPosition();
m_camera_position_pixel.set(camera_position, services);
m_camera_position_vertex.set(camera_position, services);
m_camera_position_pixel.set(camera_position, services);
m_texel_size0_vertex.set(m_texel_size0, services);
@ -323,6 +342,24 @@ public:
float saturation = lighting.saturation;
m_saturation_pixel.set(&saturation, services);
video::SColorf artificial_light = lighting.artificial_light_color;
m_artificial_light.set(artificial_light, services);
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) {
// Map directional light to screen space
@ -367,6 +404,10 @@ public:
float volumetric_light_strength = lighting.volumetric_light_strength;
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
@ -461,8 +502,9 @@ public:
#undef PROVIDE
bool enable_waving_water = g_settings->getBool("enable_waving_water");
bool enable_water_reflections = g_settings->getBool("enable_water_reflections");
constants["ENABLE_WAVING_WATER"] = enable_waving_water ? 1 : 0;
if (enable_waving_water) {
if (enable_waving_water || enable_water_reflections) {
constants["WATER_WAVE_HEIGHT"] = g_settings->getFloat("water_wave_height");
constants["WATER_WAVE_LENGTH"] = g_settings->getFloat("water_wave_length");
constants["WATER_WAVE_SPEED"] = g_settings->getFloat("water_wave_speed");

View file

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

View file

@ -225,6 +225,9 @@ public:
float shadow_soft_radius = std::max(1.f,
g_settings->getFloat("shadow_soft_radius"));
constants["SOFTSHADOWRADIUS"] = shadow_soft_radius;
if (g_settings->getBool("enable_sun_tint"))
constants["ENABLE_TINTED_SUNLIGHT"] = 1;
}
if (g_settings->getBool("enable_bloom")) {
@ -731,6 +734,10 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
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();
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("exposure_compensation", "0.0");
settings->setDefault("enable_auto_exposure", "false");
settings->setDefault("secondstage_gamma", "1.6");
settings->setDefault("debanding", "true");
settings->setDefault("antialiasing", "none");
settings->setDefault("enable_bloom", "false");
settings->setDefault("enable_bloom_debug", "false");
settings->setDefault("enable_volumetric_lighting", "false");
settings->setDefault("enable_volumetric_depth_attenuation", "false");
settings->setDefault("enable_water_reflections", "false");
settings->setDefault("enable_translucent_foliage", "false");
settings->setDefault("enable_tinted_fog", "false");
// Effects Shadows
settings->setDefault("enable_dynamic_shadows", "false");
@ -353,6 +356,7 @@ void set_default_settings()
settings->setDefault("shadow_update_frames", "16");
settings->setDefault("shadow_soft_radius", "5.0");
settings->setDefault("shadow_sky_body_orbit_tilt", "0.0");
settings->setDefault("enable_sun_tint", "false");
// Input
settings->setDefault("invert_mouse", "false");

View file

@ -4,8 +4,7 @@
#pragma once
#include "SColor.h"
using namespace irr;
#include "irr_v3d.h"
/**
* 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
*/
struct Lighting
{
AutoExposure exposure;
Vignette vignette;
ColorDecisionList cdl;
float shadow_intensity {0.0f};
float saturation {1.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};
float bloom_intensity {0.05f};
float bloom_strength_factor {1.0f};

View file

@ -62,7 +62,7 @@ private:
// These calls explicitly use the templated version of operator<<,
// so that they won't use the overloads created by ADD_NULL_CHECK.
if (arg == nullptr)
return this->operator<< <const char*> ("(null)");
return this->operator<< ((const char*) ("(null)"));
else
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_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"
[scheduled bump for 5.11.0]
PROTOCOL VERSION 48
Add compression to some existing packets
Add compression to some existing packets, artificial light color, scattering_coefficients,
vignette, specular intensity, foliage translucency and cdl parameters to Lighting packets
[scheduled bump for 5.12.0]
*/

View file

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

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.bloom_intensity << lighting.bloom_strength_factor <<
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);
}