forked from Mirrorlandia_minetest/minetest
Make volumetric light effect strength server controllable
- Make volumetric light effect strength server controllable - Separate volumetric and bloom shader pipeline - Require bloom to be enable, scale godrays with bloom
This commit is contained in:
parent
04f0d545da
commit
e0d4a9d575
@ -627,6 +627,10 @@ bloom_strength_factor (Bloom Strength Factor) float 1.0 0.1 10.0
|
|||||||
# Requires: shaders, enable_bloom
|
# Requires: shaders, enable_bloom
|
||||||
bloom_radius (Bloom Radius) float 1 0.1 8
|
bloom_radius (Bloom Radius) float 1 0.1 8
|
||||||
|
|
||||||
|
# Set to true to enable volumetric lighting effect (a.k.a. "Godrays").
|
||||||
|
#
|
||||||
|
# Requires: shaders, enable_bloom
|
||||||
|
enable_volumetric_lighting (Volumetric lighting) bool false
|
||||||
|
|
||||||
[*Audio]
|
[*Audio]
|
||||||
|
|
||||||
|
@ -1,28 +1,13 @@
|
|||||||
#define rendered texture0
|
#define rendered texture0
|
||||||
#define depthmap texture2
|
|
||||||
|
|
||||||
struct ExposureParams {
|
struct ExposureParams {
|
||||||
float compensationFactor;
|
float compensationFactor;
|
||||||
};
|
};
|
||||||
|
|
||||||
uniform sampler2D rendered;
|
uniform sampler2D rendered;
|
||||||
uniform sampler2D depthmap;
|
|
||||||
|
|
||||||
uniform mediump float bloomStrength;
|
uniform mediump float bloomStrength;
|
||||||
uniform ExposureParams exposureParams;
|
uniform ExposureParams exposureParams;
|
||||||
|
|
||||||
uniform vec3 sunPositionScreen;
|
|
||||||
uniform float sunBrightness;
|
|
||||||
uniform vec3 moonPositionScreen;
|
|
||||||
uniform float moonBrightness;
|
|
||||||
|
|
||||||
uniform vec3 dayLight;
|
|
||||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
|
||||||
uniform vec3 v_LightDirection;
|
|
||||||
#else
|
|
||||||
const vec3 v_LightDirection = vec3(0.0, -1.0, 0.0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
varying mediump vec2 varTexCoord;
|
varying mediump vec2 varTexCoord;
|
||||||
#else
|
#else
|
||||||
@ -33,80 +18,6 @@ centroid varying vec2 varTexCoord;
|
|||||||
varying float exposure; // linear exposure factor, see vertex shader
|
varying float exposure; // linear exposure factor, see vertex shader
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const float far = 1000.;
|
|
||||||
const float near = 1.;
|
|
||||||
float mapDepth(float depth)
|
|
||||||
{
|
|
||||||
return min(1., 1. / (1.00001 - depth) / far);
|
|
||||||
}
|
|
||||||
|
|
||||||
float noise(vec3 uvd) {
|
|
||||||
return fract(dot(sin(uvd * vec3(13041.19699, 27723.29171, 61029.77801)), vec3(73137.11101, 37312.92319, 10108.89991)));
|
|
||||||
}
|
|
||||||
|
|
||||||
float sampleVolumetricLight(vec2 uv, vec3 lightVec, float rawDepth)
|
|
||||||
{
|
|
||||||
lightVec = 0.5 * lightVec / lightVec.z + 0.5;
|
|
||||||
const float samples = 30.;
|
|
||||||
float result = texture2D(depthmap, uv).r < 1. ? 0.0 : 1.0;
|
|
||||||
float bias = noise(vec3(uv, rawDepth));
|
|
||||||
vec2 samplepos;
|
|
||||||
for (float i = 1.; i < samples; i++) {
|
|
||||||
samplepos = mix(uv, lightVec.xy, (i + bias) / samples);
|
|
||||||
if (min(samplepos.x, samplepos.y) > 0. && max(samplepos.x, samplepos.y) < 1.)
|
|
||||||
result += texture2D(depthmap, samplepos).r < 1. ? 0.0 : 1.0;
|
|
||||||
}
|
|
||||||
return result / samples;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection)
|
|
||||||
{
|
|
||||||
// Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham
|
|
||||||
const float beta_r0 = 1e-5; // Rayleigh scattering beta
|
|
||||||
|
|
||||||
// These factors are calculated based on expected value of scattering factor of 1e-5
|
|
||||||
// for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere
|
|
||||||
const vec3 beta_r0_l = vec3(3.3362176e-01, 8.75378289198826e-01, 1.95342379700656) * beta_r0; // wavelength-dependent scattering
|
|
||||||
|
|
||||||
const float atmosphere_height = 15000.; // height of the atmosphere in meters
|
|
||||||
// sun/moon light at the ground level, after going through the atmosphere
|
|
||||||
return exp(-beta_r0_l * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.))));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 applyVolumetricLight(vec3 color, vec2 uv, float rawDepth)
|
|
||||||
{
|
|
||||||
vec3 lookDirection = normalize(vec3(uv.x * 2. - 1., uv.y * 2. - 1., rawDepth));
|
|
||||||
vec3 lightSourceTint = vec3(1.0, 0.98, 0.4);
|
|
||||||
|
|
||||||
const float boost = 4.0;
|
|
||||||
float brightness = 0.;
|
|
||||||
vec3 sourcePosition = vec3(-1., -1., -1);
|
|
||||||
|
|
||||||
if (sunPositionScreen.z > 0. && sunBrightness > 0.) {
|
|
||||||
brightness = sunBrightness;
|
|
||||||
sourcePosition = sunPositionScreen;
|
|
||||||
}
|
|
||||||
else if (moonPositionScreen.z > 0. && moonBrightness > 0.) {
|
|
||||||
lightSourceTint = vec3(0.4, 0.9, 1.);
|
|
||||||
brightness = moonBrightness * 0.05;
|
|
||||||
sourcePosition = moonPositionScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
float cameraDirectionFactor = pow(clamp(dot(sourcePosition, vec3(0., 0., 1.)), 0.0, 0.7), 2.5);
|
|
||||||
float viewAngleFactor = pow(max(0., dot(sourcePosition, lookDirection)), 8.);
|
|
||||||
|
|
||||||
float lightFactor = brightness * sampleVolumetricLight(uv, sourcePosition, rawDepth) *
|
|
||||||
(0.05 * cameraDirectionFactor + 0.95 * viewAngleFactor);
|
|
||||||
|
|
||||||
color = mix(color, boost * getDirectLightScatteringAtGround(v_LightDirection) * dayLight, lightFactor);
|
|
||||||
|
|
||||||
// if (sunPositionScreen.z < 0.)
|
|
||||||
// color.rg += 1. - clamp(abs((2. * uv.xy - 1.) - sunPositionScreen.xy / sunPositionScreen.z) * 1000., 0., 1.);
|
|
||||||
// if (moonPositionScreen.z < 0.)
|
|
||||||
// color.rg += 1. - clamp(abs((2. * uv.xy - 1.) - moonPositionScreen.xy / moonPositionScreen.z) * 1000., 0., 1.);
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
vec2 uv = varTexCoord.st;
|
vec2 uv = varTexCoord.st;
|
||||||
@ -120,9 +31,5 @@ void main(void)
|
|||||||
color *= exposure;
|
color *= exposure;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float rawDepth = texture2D(depthmap, uv).r;
|
|
||||||
|
|
||||||
color = applyVolumetricLight(color, uv, rawDepth);
|
|
||||||
|
|
||||||
gl_FragColor = vec4(color, 1.0); // force full alpha to avoid holes in the image.
|
gl_FragColor = vec4(color, 1.0); // force full alpha to avoid holes in the image.
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,6 @@ void main(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_BLOOM
|
#ifdef ENABLE_BLOOM
|
||||||
color = applyBloom(color, uv);
|
color = applyBloom(color, uv);
|
||||||
#endif
|
#endif
|
||||||
|
115
client/shaders/volumetric_light/opengl_fragment.glsl
Normal file
115
client/shaders/volumetric_light/opengl_fragment.glsl
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#define rendered texture0
|
||||||
|
#define depthmap texture1
|
||||||
|
|
||||||
|
uniform sampler2D rendered;
|
||||||
|
uniform sampler2D depthmap;
|
||||||
|
|
||||||
|
uniform vec3 sunPositionScreen;
|
||||||
|
uniform float sunBrightness;
|
||||||
|
uniform vec3 moonPositionScreen;
|
||||||
|
uniform float moonBrightness;
|
||||||
|
|
||||||
|
uniform lowp float volumetricLightStrength;
|
||||||
|
|
||||||
|
uniform vec3 dayLight;
|
||||||
|
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||||
|
uniform vec3 v_LightDirection;
|
||||||
|
#else
|
||||||
|
const vec3 v_LightDirection = vec3(0.0, -1.0, 0.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GL_ES
|
||||||
|
varying mediump vec2 varTexCoord;
|
||||||
|
#else
|
||||||
|
centroid varying vec2 varTexCoord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const float far = 1000.;
|
||||||
|
float mapDepth(float depth)
|
||||||
|
{
|
||||||
|
return min(1., 1. / (1.00001 - depth) / far);
|
||||||
|
}
|
||||||
|
|
||||||
|
float noise(vec3 uvd) {
|
||||||
|
return fract(dot(sin(uvd * vec3(13041.19699, 27723.29171, 61029.77801)), vec3(73137.11101, 37312.92319, 10108.89991)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float sampleVolumetricLight(vec2 uv, vec3 lightVec, float rawDepth)
|
||||||
|
{
|
||||||
|
lightVec = 0.5 * lightVec / lightVec.z + 0.5;
|
||||||
|
const float samples = 30.;
|
||||||
|
float result = texture2D(depthmap, uv).r < 1. ? 0.0 : 1.0;
|
||||||
|
float bias = noise(vec3(uv, rawDepth));
|
||||||
|
vec2 samplepos;
|
||||||
|
for (float i = 1.; i < samples; i++) {
|
||||||
|
samplepos = mix(uv, lightVec.xy, (i + bias) / samples);
|
||||||
|
if (min(samplepos.x, samplepos.y) > 0. && max(samplepos.x, samplepos.y) < 1.)
|
||||||
|
result += texture2D(depthmap, samplepos).r < 1. ? 0.0 : 1.0;
|
||||||
|
}
|
||||||
|
return result / samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection)
|
||||||
|
{
|
||||||
|
// Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham
|
||||||
|
const float beta_r0 = 1e-5; // Rayleigh scattering beta
|
||||||
|
|
||||||
|
// These factors are calculated based on expected value of scattering factor of 1e-5
|
||||||
|
// for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere
|
||||||
|
const vec3 beta_r0_l = vec3(3.3362176e-01, 8.75378289198826e-01, 1.95342379700656) * beta_r0; // wavelength-dependent scattering
|
||||||
|
|
||||||
|
const float atmosphere_height = 15000.; // height of the atmosphere in meters
|
||||||
|
// sun/moon light at the ground level, after going through the atmosphere
|
||||||
|
return exp(-beta_r0_l * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.))));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 applyVolumetricLight(vec3 color, vec2 uv, float rawDepth)
|
||||||
|
{
|
||||||
|
vec3 lookDirection = normalize(vec3(uv.x * 2. - 1., uv.y * 2. - 1., rawDepth));
|
||||||
|
|
||||||
|
const float boost = 4.0;
|
||||||
|
float brightness = 0.;
|
||||||
|
vec3 sourcePosition = vec3(-1., -1., -1);
|
||||||
|
|
||||||
|
if (sunPositionScreen.z > 0. && sunBrightness > 0.) {
|
||||||
|
brightness = sunBrightness;
|
||||||
|
sourcePosition = sunPositionScreen;
|
||||||
|
}
|
||||||
|
else if (moonPositionScreen.z > 0. && moonBrightness > 0.) {
|
||||||
|
brightness = moonBrightness * 0.05;
|
||||||
|
sourcePosition = moonPositionScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
float cameraDirectionFactor = pow(clamp(dot(sourcePosition, vec3(0., 0., 1.)), 0.0, 0.7), 2.5);
|
||||||
|
float viewAngleFactor = pow(max(0., dot(sourcePosition, lookDirection)), 8.);
|
||||||
|
|
||||||
|
float lightFactor = brightness * sampleVolumetricLight(uv, sourcePosition, rawDepth) *
|
||||||
|
(0.05 * cameraDirectionFactor + 0.95 * viewAngleFactor);
|
||||||
|
|
||||||
|
color = mix(color, boost * getDirectLightScatteringAtGround(v_LightDirection) * dayLight, lightFactor);
|
||||||
|
|
||||||
|
// a factor of 5 tested well
|
||||||
|
color *= volumetricLightStrength * 5.0;
|
||||||
|
|
||||||
|
// if (sunPositionScreen.z < 0.)
|
||||||
|
// color.rg += 1. - clamp(abs((2. * uv.xy - 1.) - sunPositionScreen.xy / sunPositionScreen.z) * 1000., 0., 1.);
|
||||||
|
// if (moonPositionScreen.z < 0.)
|
||||||
|
// color.rg += 1. - clamp(abs((2. * uv.xy - 1.) - moonPositionScreen.xy / moonPositionScreen.z) * 1000., 0., 1.);
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec2 uv = varTexCoord.st;
|
||||||
|
vec3 color = texture2D(rendered, uv).rgb;
|
||||||
|
// translate to linear colorspace (approximate)
|
||||||
|
color = pow(color, vec3(2.2));
|
||||||
|
|
||||||
|
if (volumetricLightStrength > 0.0) {
|
||||||
|
float rawDepth = texture2D(depthmap, uv).r;
|
||||||
|
|
||||||
|
color = applyVolumetricLight(color, uv, rawDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FragColor = vec4(color, 1.0); // force full alpha to avoid holes in the image.
|
||||||
|
}
|
12
client/shaders/volumetric_light/opengl_vertex.glsl
Normal file
12
client/shaders/volumetric_light/opengl_vertex.glsl
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifdef GL_ES
|
||||||
|
varying mediump vec2 varTexCoord;
|
||||||
|
#else
|
||||||
|
centroid varying vec2 varTexCoord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
varTexCoord.st = inTexCoord0.st;
|
||||||
|
gl_Position = inVertexPosition;
|
||||||
|
}
|
@ -8036,6 +8036,9 @@ child will follow movement and rotation of that bone.
|
|||||||
* `speed_dark_bright` set the speed of adapting to bright light (default: `1000.0`)
|
* `speed_dark_bright` set the speed of adapting to bright light (default: `1000.0`)
|
||||||
* `speed_bright_dark` set the speed of adapting to dark scene (default: `1000.0`)
|
* `speed_bright_dark` set the speed of adapting to dark scene (default: `1000.0`)
|
||||||
* `center_weight_power` set the power factor for center-weighted luminance measurement (default: `1.0`)
|
* `center_weight_power` set the power factor for center-weighted luminance measurement (default: `1.0`)
|
||||||
|
* `volumetric_light`: is a table that controls volumetric light (a.k.a. "godrays")
|
||||||
|
* `strength`: sets the strength of the volumetric light effect from 0 (off, default) to 1 (strongest)
|
||||||
|
* This value has no effect on clients who have the "Volumetric Lighting" or "Bloom" shaders disabled.
|
||||||
|
|
||||||
* `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`.
|
||||||
|
@ -404,10 +404,12 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
|||||||
CachedPixelShaderSetting<float> m_bloom_radius_pixel;
|
CachedPixelShaderSetting<float> m_bloom_radius_pixel;
|
||||||
float m_bloom_radius;
|
float m_bloom_radius;
|
||||||
CachedPixelShaderSetting<float> m_saturation_pixel;
|
CachedPixelShaderSetting<float> m_saturation_pixel;
|
||||||
|
bool m_volumetric_light_enabled;
|
||||||
CachedPixelShaderSetting<float, 3> m_sun_position_pixel;
|
CachedPixelShaderSetting<float, 3> m_sun_position_pixel;
|
||||||
CachedPixelShaderSetting<float> m_sun_brightness_pixel;
|
CachedPixelShaderSetting<float> m_sun_brightness_pixel;
|
||||||
CachedPixelShaderSetting<float, 3> m_moon_position_pixel;
|
CachedPixelShaderSetting<float, 3> m_moon_position_pixel;
|
||||||
CachedPixelShaderSetting<float> m_moon_brightness_pixel;
|
CachedPixelShaderSetting<float> m_moon_brightness_pixel;
|
||||||
|
CachedPixelShaderSetting<float> m_volumetric_light_strength_pixel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void onSettingsChange(const std::string &name)
|
void onSettingsChange(const std::string &name)
|
||||||
@ -469,7 +471,8 @@ public:
|
|||||||
m_sun_position_pixel("sunPositionScreen"),
|
m_sun_position_pixel("sunPositionScreen"),
|
||||||
m_sun_brightness_pixel("sunBrightness"),
|
m_sun_brightness_pixel("sunBrightness"),
|
||||||
m_moon_position_pixel("moonPositionScreen"),
|
m_moon_position_pixel("moonPositionScreen"),
|
||||||
m_moon_brightness_pixel("moonBrightness")
|
m_moon_brightness_pixel("moonBrightness"),
|
||||||
|
m_volumetric_light_strength_pixel("volumetricLightStrength")
|
||||||
{
|
{
|
||||||
g_settings->registerChangedCallback("enable_fog", settingsCallback, this);
|
g_settings->registerChangedCallback("enable_fog", settingsCallback, this);
|
||||||
g_settings->registerChangedCallback("exposure_compensation", settingsCallback, this);
|
g_settings->registerChangedCallback("exposure_compensation", settingsCallback, this);
|
||||||
@ -483,6 +486,7 @@ public:
|
|||||||
m_bloom_intensity = g_settings->getFloat("bloom_intensity", 0.01f, 1.0f);
|
m_bloom_intensity = g_settings->getFloat("bloom_intensity", 0.01f, 1.0f);
|
||||||
m_bloom_strength = RenderingEngine::BASE_BLOOM_STRENGTH * g_settings->getFloat("bloom_strength_factor", 0.1f, 10.0f);
|
m_bloom_strength = RenderingEngine::BASE_BLOOM_STRENGTH * g_settings->getFloat("bloom_strength_factor", 0.1f, 10.0f);
|
||||||
m_bloom_radius = g_settings->getFloat("bloom_radius", 0.1f, 8.0f);
|
m_bloom_radius = g_settings->getFloat("bloom_radius", 0.1f, 8.0f);
|
||||||
|
m_volumetric_light_enabled = g_settings->getBool("enable_volumetric_lighting") && m_bloom_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
~GameGlobalShaderConstantSetter()
|
~GameGlobalShaderConstantSetter()
|
||||||
@ -588,49 +592,52 @@ public:
|
|||||||
float saturation = m_client->getEnv().getLocalPlayer()->getLighting().saturation;
|
float saturation = m_client->getEnv().getLocalPlayer()->getLighting().saturation;
|
||||||
m_saturation_pixel.set(&saturation, services);
|
m_saturation_pixel.set(&saturation, services);
|
||||||
|
|
||||||
// Map directional light to screen space
|
if (m_volumetric_light_enabled) {
|
||||||
auto camera_node = m_client->getCamera()->getCameraNode();
|
// Map directional light to screen space
|
||||||
core::matrix4 transform = camera_node->getProjectionMatrix();
|
auto camera_node = m_client->getCamera()->getCameraNode();
|
||||||
transform *= camera_node->getViewMatrix();
|
core::matrix4 transform = camera_node->getProjectionMatrix();
|
||||||
|
transform *= camera_node->getViewMatrix();
|
||||||
|
|
||||||
if (m_sky->getSunVisible()) {
|
if (m_sky->getSunVisible()) {
|
||||||
v3f sun_position = camera_node->getAbsolutePosition() +
|
v3f sun_position = camera_node->getAbsolutePosition() +
|
||||||
10000. * m_sky->getSunDirection();
|
10000. * m_sky->getSunDirection();
|
||||||
transform.transformVect(sun_position);
|
transform.transformVect(sun_position);
|
||||||
sun_position.normalize();
|
sun_position.normalize();
|
||||||
|
|
||||||
float sun_position_array[3] = { sun_position.X, sun_position.Y, sun_position.Z};
|
float sun_position_array[3] = { sun_position.X, sun_position.Y, sun_position.Z};
|
||||||
m_sun_position_pixel.set(sun_position_array, services);
|
m_sun_position_pixel.set(sun_position_array, services);
|
||||||
|
|
||||||
float sun_brightness = rangelim(107.143f * m_sky->getSunDirection().dotProduct(v3f(0.f, 1.f, 0.f)), 0.f, 1.f);
|
float sun_brightness = rangelim(107.143f * m_sky->getSunDirection().dotProduct(v3f(0.f, 1.f, 0.f)), 0.f, 1.f);
|
||||||
m_sun_brightness_pixel.set(&sun_brightness, services);
|
m_sun_brightness_pixel.set(&sun_brightness, services);
|
||||||
}
|
} else {
|
||||||
else {
|
float sun_position_array[3] = { 0.f, 0.f, -1.f };
|
||||||
float sun_position_array[3] = { 0.f, 0.f, -1.f };
|
m_sun_position_pixel.set(sun_position_array, services);
|
||||||
m_sun_position_pixel.set(sun_position_array, services);
|
|
||||||
|
|
||||||
float sun_brightness = 0.f;
|
float sun_brightness = 0.f;
|
||||||
m_sun_brightness_pixel.set(&sun_brightness, services);
|
m_sun_brightness_pixel.set(&sun_brightness, services);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_sky->getMoonVisible()) {
|
if (m_sky->getMoonVisible()) {
|
||||||
v3f moon_position = camera_node->getAbsolutePosition() +
|
v3f moon_position = camera_node->getAbsolutePosition() +
|
||||||
10000. * m_sky->getMoonDirection();
|
10000. * m_sky->getMoonDirection();
|
||||||
transform.transformVect(moon_position);
|
transform.transformVect(moon_position);
|
||||||
moon_position.normalize();
|
moon_position.normalize();
|
||||||
|
|
||||||
float moon_position_array[3] = { moon_position.X, moon_position.Y, moon_position.Z};
|
float moon_position_array[3] = { moon_position.X, moon_position.Y, moon_position.Z};
|
||||||
m_moon_position_pixel.set(moon_position_array, services);
|
m_moon_position_pixel.set(moon_position_array, services);
|
||||||
|
|
||||||
float moon_brightness = rangelim(107.143f * m_sky->getMoonDirection().dotProduct(v3f(0.f, 1.f, 0.f)), 0.f, 1.f);
|
float moon_brightness = rangelim(107.143f * m_sky->getMoonDirection().dotProduct(v3f(0.f, 1.f, 0.f)), 0.f, 1.f);
|
||||||
m_moon_brightness_pixel.set(&moon_brightness, services);
|
m_moon_brightness_pixel.set(&moon_brightness, services);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float moon_position_array[3] = { 0.f, 0.f, -1.f };
|
float moon_position_array[3] = { 0.f, 0.f, -1.f };
|
||||||
m_moon_position_pixel.set(moon_position_array, services);
|
m_moon_position_pixel.set(moon_position_array, services);
|
||||||
|
|
||||||
float moon_brightness = 0.f;
|
float moon_brightness = 0.f;
|
||||||
m_moon_brightness_pixel.set(&moon_brightness, services);
|
m_moon_brightness_pixel.set(&moon_brightness, services);
|
||||||
|
}
|
||||||
|
float volumetric_light_strength = m_client->getEnv().getLocalPlayer()->getLighting().volumetric_light_strength;
|
||||||
|
m_volumetric_light_strength_pixel.set(&volumetric_light_strength, services);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3089,7 +3096,6 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam)
|
|||||||
else
|
else
|
||||||
sky->setFogStart(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f));
|
sky->setFogStart(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f));
|
||||||
|
|
||||||
|
|
||||||
delete event->set_sky;
|
delete event->set_sky;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,8 +120,9 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
|||||||
static const u8 TEXTURE_EXPOSURE_1 = 3;
|
static const u8 TEXTURE_EXPOSURE_1 = 3;
|
||||||
static const u8 TEXTURE_EXPOSURE_2 = 4;
|
static const u8 TEXTURE_EXPOSURE_2 = 4;
|
||||||
static const u8 TEXTURE_FXAA = 5;
|
static const u8 TEXTURE_FXAA = 5;
|
||||||
static const u8 TEXTURE_BLOOM_DOWN = 10;
|
static const u8 TEXTURE_VOLUME = 6;
|
||||||
static const u8 TEXTURE_BLOOM_UP = 20;
|
static const u8 TEXTURE_SCALE_DOWN = 10;
|
||||||
|
static const u8 TEXTURE_SCALE_UP = 20;
|
||||||
|
|
||||||
// Super-sampling is simply rendering into a larger texture.
|
// Super-sampling is simply rendering into a larger texture.
|
||||||
// Downscaling is done by the final step when rendering to the screen.
|
// Downscaling is done by the final step when rendering to the screen.
|
||||||
@ -130,6 +131,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
|||||||
const bool enable_auto_exposure = g_settings->getBool("enable_auto_exposure");
|
const bool enable_auto_exposure = g_settings->getBool("enable_auto_exposure");
|
||||||
const bool enable_ssaa = antialiasing == "ssaa";
|
const bool enable_ssaa = antialiasing == "ssaa";
|
||||||
const bool enable_fxaa = antialiasing == "fxaa";
|
const bool enable_fxaa = antialiasing == "fxaa";
|
||||||
|
const bool enable_volumetric_light = g_settings->getBool("enable_volumetric_lighting") && enable_bloom;
|
||||||
|
|
||||||
if (enable_ssaa) {
|
if (enable_ssaa) {
|
||||||
u16 ssaa_scale = MYMAX(2, g_settings->getU16("fsaa"));
|
u16 ssaa_scale = MYMAX(2, g_settings->getU16("fsaa"));
|
||||||
@ -160,9 +162,9 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
|||||||
|
|
||||||
v2f downscale = scale * 0.5;
|
v2f downscale = scale * 0.5;
|
||||||
for (u8 i = 0; i < MIPMAP_LEVELS; i++) {
|
for (u8 i = 0; i < MIPMAP_LEVELS; i++) {
|
||||||
buffer->setTexture(TEXTURE_BLOOM_DOWN + i, downscale, std::string("downsample") + std::to_string(i), color_format);
|
buffer->setTexture(TEXTURE_SCALE_DOWN + i, downscale, std::string("downsample") + std::to_string(i), color_format);
|
||||||
if (enable_bloom)
|
if (enable_bloom)
|
||||||
buffer->setTexture(TEXTURE_BLOOM_UP + i, downscale, std::string("upsample") + std::to_string(i), color_format);
|
buffer->setTexture(TEXTURE_SCALE_UP + i, downscale, std::string("upsample") + std::to_string(i), color_format);
|
||||||
downscale *= 0.5;
|
downscale *= 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,20 +173,30 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
|||||||
|
|
||||||
// get bright spots
|
// get bright spots
|
||||||
u32 shader_id = client->getShaderSource()->getShader("extract_bloom", TILE_MATERIAL_PLAIN, NDT_MESH);
|
u32 shader_id = client->getShaderSource()->getShader("extract_bloom", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||||
RenderStep *extract_bloom = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_COLOR, TEXTURE_EXPOSURE_1, TEXTURE_DEPTH });
|
RenderStep *extract_bloom = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { source, TEXTURE_EXPOSURE_1 });
|
||||||
extract_bloom->setRenderSource(buffer);
|
extract_bloom->setRenderSource(buffer);
|
||||||
extract_bloom->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_BLOOM));
|
extract_bloom->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_BLOOM));
|
||||||
source = TEXTURE_BLOOM;
|
source = TEXTURE_BLOOM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enable_volumetric_light) {
|
||||||
|
buffer->setTexture(TEXTURE_VOLUME, scale, "volume", color_format);
|
||||||
|
|
||||||
|
shader_id = client->getShaderSource()->getShader("volumetric_light", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||||
|
auto volume = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { source, TEXTURE_DEPTH });
|
||||||
|
volume->setRenderSource(buffer);
|
||||||
|
volume->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_VOLUME));
|
||||||
|
source = TEXTURE_VOLUME;
|
||||||
|
}
|
||||||
|
|
||||||
// downsample
|
// downsample
|
||||||
shader_id = client->getShaderSource()->getShader("bloom_downsample", TILE_MATERIAL_PLAIN, NDT_MESH);
|
shader_id = client->getShaderSource()->getShader("bloom_downsample", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||||
for (u8 i = 0; i < MIPMAP_LEVELS; i++) {
|
for (u8 i = 0; i < MIPMAP_LEVELS; i++) {
|
||||||
auto step = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { source });
|
auto step = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { source });
|
||||||
step->setRenderSource(buffer);
|
step->setRenderSource(buffer);
|
||||||
step->setBilinearFilter(0, true);
|
step->setBilinearFilter(0, true);
|
||||||
step->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_BLOOM_DOWN + i));
|
step->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_SCALE_DOWN + i));
|
||||||
source = TEXTURE_BLOOM_DOWN + i;
|
source = TEXTURE_SCALE_DOWN + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,19 +205,19 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
|||||||
// upsample
|
// upsample
|
||||||
shader_id = client->getShaderSource()->getShader("bloom_upsample", TILE_MATERIAL_PLAIN, NDT_MESH);
|
shader_id = client->getShaderSource()->getShader("bloom_upsample", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||||
for (u8 i = MIPMAP_LEVELS - 1; i > 0; i--) {
|
for (u8 i = MIPMAP_LEVELS - 1; i > 0; i--) {
|
||||||
auto step = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { u8(TEXTURE_BLOOM_DOWN + i - 1), source });
|
auto step = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { u8(TEXTURE_SCALE_DOWN + i - 1), source });
|
||||||
step->setRenderSource(buffer);
|
step->setRenderSource(buffer);
|
||||||
step->setBilinearFilter(0, true);
|
step->setBilinearFilter(0, true);
|
||||||
step->setBilinearFilter(1, true);
|
step->setBilinearFilter(1, true);
|
||||||
step->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, u8(TEXTURE_BLOOM_UP + i - 1)));
|
step->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, u8(TEXTURE_SCALE_UP + i - 1)));
|
||||||
source = TEXTURE_BLOOM_UP + i - 1;
|
source = TEXTURE_SCALE_UP + i - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic Exposure pt2
|
// Dynamic Exposure pt2
|
||||||
if (enable_auto_exposure) {
|
if (enable_auto_exposure) {
|
||||||
shader_id = client->getShaderSource()->getShader("update_exposure", TILE_MATERIAL_PLAIN, NDT_MESH);
|
shader_id = client->getShaderSource()->getShader("update_exposure", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||||
auto update_exposure = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_EXPOSURE_1, u8(TEXTURE_BLOOM_DOWN + MIPMAP_LEVELS - 1) });
|
auto update_exposure = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_EXPOSURE_1, u8(TEXTURE_SCALE_DOWN + MIPMAP_LEVELS - 1) });
|
||||||
update_exposure->setBilinearFilter(1, true);
|
update_exposure->setBilinearFilter(1, true);
|
||||||
update_exposure->setRenderSource(buffer);
|
update_exposure->setRenderSource(buffer);
|
||||||
update_exposure->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_EXPOSURE_2));
|
update_exposure->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_EXPOSURE_2));
|
||||||
@ -228,7 +240,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
|||||||
|
|
||||||
// final merge
|
// final merge
|
||||||
shader_id = client->getShaderSource()->getShader("second_stage", TILE_MATERIAL_PLAIN, NDT_MESH);
|
shader_id = client->getShaderSource()->getShader("second_stage", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||||
PostProcessingStep *effect = pipeline->createOwned<PostProcessingStep>(shader_id, std::vector<u8> { final_stage_source, TEXTURE_BLOOM_UP, TEXTURE_EXPOSURE_2 });
|
PostProcessingStep *effect = pipeline->createOwned<PostProcessingStep>(shader_id, std::vector<u8> { final_stage_source, TEXTURE_SCALE_UP, TEXTURE_EXPOSURE_2 });
|
||||||
pipeline->addStep(effect);
|
pipeline->addStep(effect);
|
||||||
if (enable_ssaa)
|
if (enable_ssaa)
|
||||||
effect->setBilinearFilter(0, true);
|
effect->setBilinearFilter(0, true);
|
||||||
|
@ -770,6 +770,10 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
|
|||||||
if (g_settings->getBool("debanding"))
|
if (g_settings->getBool("debanding"))
|
||||||
shaders_header << "#define ENABLE_DITHERING 1\n";
|
shaders_header << "#define ENABLE_DITHERING 1\n";
|
||||||
|
|
||||||
|
if (g_settings->getBool("enable_volumetric_lighting")) {
|
||||||
|
shaders_header << "#define VOLUMETRIC_LIGHT 1\n";
|
||||||
|
}
|
||||||
|
|
||||||
shaders_header << "#line 0\n"; // reset the line counter for meaningful diagnostics
|
shaders_header << "#line 0\n"; // reset the line counter for meaningful diagnostics
|
||||||
|
|
||||||
std::string common_header = shaders_header.str();
|
std::string common_header = shaders_header.str();
|
||||||
|
@ -120,6 +120,9 @@ public:
|
|||||||
void setFogStart(float fog_start) { m_sky_params.fog_start = fog_start; }
|
void setFogStart(float fog_start) { m_sky_params.fog_start = fog_start; }
|
||||||
float getFogStart() const { return m_sky_params.fog_start; }
|
float getFogStart() const { return m_sky_params.fog_start; }
|
||||||
|
|
||||||
|
void setVolumetricLightStrength(float volumetric_light_strength) { m_sky_params.volumetric_light_strength = volumetric_light_strength; }
|
||||||
|
float getVolumetricLightStrength() const { return m_sky_params.volumetric_light_strength; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
aabb3f m_box;
|
aabb3f m_box;
|
||||||
video::SMaterial m_materials[SKY_MATERIAL_COUNT];
|
video::SMaterial m_materials[SKY_MATERIAL_COUNT];
|
||||||
|
@ -271,6 +271,7 @@ void set_default_settings()
|
|||||||
settings->setDefault("bloom_strength_factor", "1.0");
|
settings->setDefault("bloom_strength_factor", "1.0");
|
||||||
settings->setDefault("bloom_intensity", "0.05");
|
settings->setDefault("bloom_intensity", "0.05");
|
||||||
settings->setDefault("bloom_radius", "1");
|
settings->setDefault("bloom_radius", "1");
|
||||||
|
settings->setDefault("enable_volumetric_lighting", "false");
|
||||||
|
|
||||||
// Effects Shadows
|
// Effects Shadows
|
||||||
settings->setDefault("enable_dynamic_shadows", "false");
|
settings->setDefault("enable_dynamic_shadows", "false");
|
||||||
|
@ -53,4 +53,5 @@ struct Lighting
|
|||||||
AutoExposure exposure;
|
AutoExposure exposure;
|
||||||
float shadow_intensity {0.0f};
|
float shadow_intensity {0.0f};
|
||||||
float saturation {1.0f};
|
float saturation {1.0f};
|
||||||
|
float volumetric_light_strength {0.0f};
|
||||||
};
|
};
|
||||||
|
@ -1804,4 +1804,6 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
|
|||||||
>> lighting.exposure.speed_bright_dark
|
>> lighting.exposure.speed_bright_dark
|
||||||
>> lighting.exposure.center_weight_power;
|
>> lighting.exposure.center_weight_power;
|
||||||
}
|
}
|
||||||
|
if (pkt->getRemainingBytes() >= 4)
|
||||||
|
*pkt >> lighting.volumetric_light_strength;
|
||||||
}
|
}
|
||||||
|
@ -2495,7 +2495,14 @@ int ObjectRef::l_set_lighting(lua_State *L)
|
|||||||
lighting.exposure.center_weight_power = getfloatfield_default(L, -1, "center_weight_power", lighting.exposure.center_weight_power);
|
lighting.exposure.center_weight_power = getfloatfield_default(L, -1, "center_weight_power", lighting.exposure.center_weight_power);
|
||||||
}
|
}
|
||||||
lua_pop(L, 1); // exposure
|
lua_pop(L, 1); // exposure
|
||||||
}
|
|
||||||
|
lua_getfield(L, 2, "volumetric_light");
|
||||||
|
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_pop(L, 1); // volumetric_light
|
||||||
|
}
|
||||||
|
|
||||||
getServer(L)->setLighting(player, lighting);
|
getServer(L)->setLighting(player, lighting);
|
||||||
return 0;
|
return 0;
|
||||||
@ -2533,6 +2540,10 @@ int ObjectRef::l_get_lighting(lua_State *L)
|
|||||||
lua_pushnumber(L, lighting.exposure.center_weight_power);
|
lua_pushnumber(L, lighting.exposure.center_weight_power);
|
||||||
lua_setfield(L, -2, "center_weight_power");
|
lua_setfield(L, -2, "center_weight_power");
|
||||||
lua_setfield(L, -2, "exposure");
|
lua_setfield(L, -2, "exposure");
|
||||||
|
lua_newtable(L); // "volumetric_light"
|
||||||
|
lua_pushnumber(L, lighting.volumetric_light_strength);
|
||||||
|
lua_setfield(L, -2, "strength");
|
||||||
|
lua_setfield(L, -2, "volumetric_light");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1919,6 +1919,8 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
|
|||||||
<< lighting.exposure.speed_bright_dark
|
<< lighting.exposure.speed_bright_dark
|
||||||
<< lighting.exposure.center_weight_power;
|
<< lighting.exposure.center_weight_power;
|
||||||
|
|
||||||
|
pkt << lighting.volumetric_light_strength;
|
||||||
|
|
||||||
Send(&pkt);
|
Send(&pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ struct SkyboxParams
|
|||||||
float body_orbit_tilt { INVALID_SKYBOX_TILT };
|
float body_orbit_tilt { INVALID_SKYBOX_TILT };
|
||||||
s16 fog_distance { -1 };
|
s16 fog_distance { -1 };
|
||||||
float fog_start { -1.0f };
|
float fog_start { -1.0f };
|
||||||
|
float volumetric_light_strength { 0.0f };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SunParams
|
struct SunParams
|
||||||
|
Loading…
Reference in New Issue
Block a user