forked from Mirrorlandia_minetest/minetest
Bloom (#12791)
Adds configurable light exposure control and bloom effect (light bleeding) with client-side settings.
This commit is contained in:
parent
3978b9b8ed
commit
9df79a4b2d
@ -449,6 +449,44 @@ shadow_soft_radius (Soft shadow radius) float 5.0 1.0 15.0
|
|||||||
# Minimum value: 0.0; maximum value: 60.0
|
# Minimum value: 0.0; maximum value: 60.0
|
||||||
shadow_sky_body_orbit_tilt (Sky Body Orbit Tilt) float 0.0 0.0 60.0
|
shadow_sky_body_orbit_tilt (Sky Body Orbit Tilt) float 0.0 0.0 60.0
|
||||||
|
|
||||||
|
[**Post processing]
|
||||||
|
|
||||||
|
# Set the exposure compensation factor.
|
||||||
|
# This factor is applied to linear color value
|
||||||
|
# before all other post-processing effects.
|
||||||
|
# Value of 1.0 (default) means no exposure compensation.
|
||||||
|
# Range: from 0.1 to 10.0
|
||||||
|
exposure_factor (Exposure Factor) float 1.0 0.1 10.0
|
||||||
|
|
||||||
|
[**Bloom]
|
||||||
|
|
||||||
|
# Set to true to enable bloom effect.
|
||||||
|
# Bright colors will bleed over the neighboring objects.
|
||||||
|
enable_bloom (Enable Bloom) bool false
|
||||||
|
|
||||||
|
# Set to true to render debugging breakdown of the bloom effect.
|
||||||
|
# In debug mode, the screen is split into 4 quadrants:
|
||||||
|
# top-left - processed base image, top-right - final image
|
||||||
|
# bottom-left - raw base image, bottom-right - bloom texture.
|
||||||
|
enable_bloom_debug (Enable Bloom Debug) bool false
|
||||||
|
|
||||||
|
# Set to true to use dedicated texture at each step of bloom effect.
|
||||||
|
# This is a compatibility setting to avoid visual artifacts
|
||||||
|
# on certain GPUs and video drivers.
|
||||||
|
enable_bloom_dedicated_texture (Enable Bloom Dedicated Texture) bool false
|
||||||
|
|
||||||
|
# Set the intensity of bloom
|
||||||
|
# Smaller values make bloom more subtle
|
||||||
|
# Range: from 0.01 to 1.0, default: 0.05
|
||||||
|
bloom_intensity (Bloom Intensity) float 0.05 0.01 1.0
|
||||||
|
|
||||||
|
# Set the radius of the bloom filter in pixels.
|
||||||
|
# Larger values render more glow around bright objects
|
||||||
|
# at the cost of higher resource consumption.
|
||||||
|
# Range: from 1 to 64, default: 16
|
||||||
|
bloom_radius (Bloom Radius) int 16 1 64
|
||||||
|
|
||||||
|
|
||||||
[*Audio]
|
[*Audio]
|
||||||
|
|
||||||
# Volume of all sounds.
|
# Volume of all sounds.
|
||||||
|
29
client/shaders/blur_h/opengl_fragment.glsl
Normal file
29
client/shaders/blur_h/opengl_fragment.glsl
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#define rendered texture0
|
||||||
|
|
||||||
|
uniform sampler2D rendered;
|
||||||
|
uniform vec2 texelSize0;
|
||||||
|
uniform mediump float bloomRadius = 3.0;
|
||||||
|
|
||||||
|
#ifdef GL_ES
|
||||||
|
varying mediump vec2 varTexCoord;
|
||||||
|
#else
|
||||||
|
centroid varying vec2 varTexCoord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
// kernel distance and linear size
|
||||||
|
mediump float n = 2. * bloomRadius + 1.;
|
||||||
|
|
||||||
|
vec2 uv = varTexCoord.st - vec2(bloomRadius * texelSize0.x, 0.);
|
||||||
|
vec4 color = vec4(0.);
|
||||||
|
mediump float sum = 0.;
|
||||||
|
for (mediump float i = 0.; i < n; i++) {
|
||||||
|
mediump float weight = pow(1. - (abs(i / bloomRadius - 1.)), 1.3);
|
||||||
|
color += texture2D(rendered, uv).rgba * weight;
|
||||||
|
sum += weight;
|
||||||
|
uv += vec2(texelSize0.x, 0.);
|
||||||
|
}
|
||||||
|
color /= sum;
|
||||||
|
gl_FragColor = vec4(color.rgb, 1.0); // force full alpha to avoid holes in the image.
|
||||||
|
}
|
11
client/shaders/blur_h/opengl_vertex.glsl
Normal file
11
client/shaders/blur_h/opengl_vertex.glsl
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifdef GL_ES
|
||||||
|
varying mediump vec2 varTexCoord;
|
||||||
|
#else
|
||||||
|
centroid varying vec2 varTexCoord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
varTexCoord.st = inTexCoord0.st;
|
||||||
|
gl_Position = inVertexPosition;
|
||||||
|
}
|
29
client/shaders/blur_v/opengl_fragment.glsl
Normal file
29
client/shaders/blur_v/opengl_fragment.glsl
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#define rendered texture0
|
||||||
|
|
||||||
|
uniform sampler2D rendered;
|
||||||
|
uniform vec2 texelSize0;
|
||||||
|
uniform mediump float bloomRadius = 3.0;
|
||||||
|
|
||||||
|
#ifdef GL_ES
|
||||||
|
varying mediump vec2 varTexCoord;
|
||||||
|
#else
|
||||||
|
centroid varying vec2 varTexCoord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
// kernel distance and linear size
|
||||||
|
mediump float n = 2. * bloomRadius + 1.;
|
||||||
|
|
||||||
|
vec2 uv = varTexCoord.st - vec2(0., bloomRadius * texelSize0.y);
|
||||||
|
vec4 color = vec4(0.);
|
||||||
|
mediump float sum = 0.;
|
||||||
|
for (mediump float i = 0.; i < n; i++) {
|
||||||
|
mediump float weight = pow(1. - (abs(i / bloomRadius - 1.)), 1.3);
|
||||||
|
color += texture2D(rendered, uv).rgba * weight;
|
||||||
|
sum += weight;
|
||||||
|
uv += vec2(0., texelSize0.y);
|
||||||
|
}
|
||||||
|
color /= sum;
|
||||||
|
gl_FragColor = vec4(color.rgb, 1.0); // force full alpha to avoid holes in the image.
|
||||||
|
}
|
11
client/shaders/blur_v/opengl_vertex.glsl
Normal file
11
client/shaders/blur_v/opengl_vertex.glsl
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifdef GL_ES
|
||||||
|
varying mediump vec2 varTexCoord;
|
||||||
|
#else
|
||||||
|
centroid varying vec2 varTexCoord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
varTexCoord.st = inTexCoord0.st;
|
||||||
|
gl_Position = inVertexPosition;
|
||||||
|
}
|
21
client/shaders/extract_bloom/opengl_fragment.glsl
Normal file
21
client/shaders/extract_bloom/opengl_fragment.glsl
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#define rendered texture0
|
||||||
|
|
||||||
|
uniform sampler2D rendered;
|
||||||
|
uniform mediump float exposureFactor = 2.5;
|
||||||
|
uniform float bloomLuminanceThreshold = 1.0;
|
||||||
|
|
||||||
|
#ifdef GL_ES
|
||||||
|
varying mediump vec2 varTexCoord;
|
||||||
|
#else
|
||||||
|
centroid varying vec2 varTexCoord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec2 uv = varTexCoord.st;
|
||||||
|
vec4 color = texture2D(rendered, uv).rgba;
|
||||||
|
// translate to linear colorspace (approximate)
|
||||||
|
color.rgb = pow(color.rgb, vec3(2.2)) * exposureFactor;
|
||||||
|
gl_FragColor = vec4(color.rgb, 1.0); // force full alpha to avoid holes in the image.
|
||||||
|
}
|
11
client/shaders/extract_bloom/opengl_vertex.glsl
Normal file
11
client/shaders/extract_bloom/opengl_vertex.glsl
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifdef GL_ES
|
||||||
|
varying mediump vec2 varTexCoord;
|
||||||
|
#else
|
||||||
|
centroid varying vec2 varTexCoord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
varTexCoord.st = inTexCoord0.st;
|
||||||
|
gl_Position = inVertexPosition;
|
||||||
|
}
|
@ -1,6 +1,10 @@
|
|||||||
uniform sampler2D baseTexture;
|
#define rendered texture0
|
||||||
|
#define bloom texture1
|
||||||
|
|
||||||
#define rendered baseTexture
|
uniform sampler2D rendered;
|
||||||
|
uniform sampler2D bloom;
|
||||||
|
uniform mediump float exposureFactor = 2.5;
|
||||||
|
uniform lowp float bloomIntensity = 1.0;
|
||||||
|
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
varying mediump vec2 varTexCoord;
|
varying mediump vec2 varTexCoord;
|
||||||
@ -8,6 +12,24 @@ varying mediump vec2 varTexCoord;
|
|||||||
centroid varying vec2 varTexCoord;
|
centroid varying vec2 varTexCoord;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_BLOOM
|
||||||
|
|
||||||
|
vec4 applyBloom(vec4 color, vec2 uv)
|
||||||
|
{
|
||||||
|
float bias = bloomIntensity;
|
||||||
|
vec4 bloom = texture2D(bloom, uv);
|
||||||
|
#if ENABLE_BLOOM_DEBUG
|
||||||
|
if (uv.x > 0.5 && uv.y < 0.5)
|
||||||
|
return vec4(bloom.rgb, color.a);
|
||||||
|
if (uv.x < 0.5)
|
||||||
|
return color;
|
||||||
|
#endif
|
||||||
|
color.rgb = mix(color.rgb, bloom.rgb, bias);
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLE_TONE_MAPPING
|
#if ENABLE_TONE_MAPPING
|
||||||
|
|
||||||
/* Hable's UC2 Tone mapping parameters
|
/* Hable's UC2 Tone mapping parameters
|
||||||
@ -28,15 +50,13 @@ vec3 uncharted2Tonemap(vec3 x)
|
|||||||
|
|
||||||
vec4 applyToneMapping(vec4 color)
|
vec4 applyToneMapping(vec4 color)
|
||||||
{
|
{
|
||||||
color = vec4(pow(color.rgb, vec3(2.2)), color.a);
|
const float exposureBias = 2.0;
|
||||||
const float gamma = 1.6;
|
|
||||||
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
|
||||||
//vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
|
//vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
|
||||||
vec3 whiteScale = vec3(1.036015346);
|
vec3 whiteScale = vec3(1.036015346);
|
||||||
color.rgb *= whiteScale;
|
color.rgb *= whiteScale;
|
||||||
return vec4(pow(color.rgb, vec3(1.0 / gamma)), color.a);
|
return color;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -45,9 +65,36 @@ void main(void)
|
|||||||
vec2 uv = varTexCoord.st;
|
vec2 uv = varTexCoord.st;
|
||||||
vec4 color = texture2D(rendered, uv).rgba;
|
vec4 color = texture2D(rendered, uv).rgba;
|
||||||
|
|
||||||
#if ENABLE_TONE_MAPPING
|
// translate to linear colorspace (approximate)
|
||||||
color = applyToneMapping(color);
|
color.rgb = pow(color.rgb, vec3(2.2));
|
||||||
|
|
||||||
|
#if ENABLE_BLOOM_DEBUG
|
||||||
|
if (uv.x > 0.5 || uv.y > 0.5)
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
color.rgb *= exposureFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if ENABLE_BLOOM
|
||||||
|
color = applyBloom(color, uv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_BLOOM_DEBUG
|
||||||
|
if (uv.x > 0.5 || uv.y > 0.5)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if ENABLE_TONE_MAPPING
|
||||||
|
color = applyToneMapping(color);
|
||||||
|
#else
|
||||||
|
color.rgb /= 2.5; // default exposure factor, see also RenderingEngine::DEFAULT_EXPOSURE_FACTOR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
color.rgb = clamp(color.rgb, vec3(0.), vec3(1.));
|
||||||
|
|
||||||
|
// return to sRGB colorspace (approximate)
|
||||||
|
color.rgb = pow(color.rgb, vec3(1.0 / 2.2));
|
||||||
|
|
||||||
gl_FragColor = vec4(color.rgb, 1.0); // force full alpha to avoid holes in the image.
|
gl_FragColor = vec4(color.rgb, 1.0); // force full alpha to avoid holes in the image.
|
||||||
}
|
}
|
||||||
|
@ -405,6 +405,7 @@ typedef s32 SamplerLayer_t;
|
|||||||
class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
||||||
{
|
{
|
||||||
Sky *m_sky;
|
Sky *m_sky;
|
||||||
|
Client *m_client;
|
||||||
bool *m_force_fog_off;
|
bool *m_force_fog_off;
|
||||||
f32 *m_fog_range;
|
f32 *m_fog_range;
|
||||||
bool m_fog_enabled;
|
bool m_fog_enabled;
|
||||||
@ -419,16 +420,31 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
|||||||
CachedPixelShaderSetting<float, 3> m_minimap_yaw;
|
CachedPixelShaderSetting<float, 3> m_minimap_yaw;
|
||||||
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel;
|
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel;
|
||||||
CachedPixelShaderSetting<float, 3> m_camera_offset_vertex;
|
CachedPixelShaderSetting<float, 3> m_camera_offset_vertex;
|
||||||
CachedPixelShaderSetting<SamplerLayer_t> m_base_texture;
|
CachedPixelShaderSetting<SamplerLayer_t> m_texture0;
|
||||||
CachedPixelShaderSetting<SamplerLayer_t> m_normal_texture;
|
CachedPixelShaderSetting<SamplerLayer_t> m_texture1;
|
||||||
CachedPixelShaderSetting<SamplerLayer_t> m_texture_flags;
|
CachedPixelShaderSetting<SamplerLayer_t> m_texture2;
|
||||||
Client *m_client;
|
CachedPixelShaderSetting<SamplerLayer_t> m_texture3;
|
||||||
|
CachedPixelShaderSetting<float, 2> m_texel_size0;
|
||||||
|
std::array<float, 2> m_texel_size0_values;
|
||||||
|
CachedPixelShaderSetting<float> m_exposure_factor_pixel;
|
||||||
|
float m_user_exposure_factor;
|
||||||
|
bool m_bloom_enabled;
|
||||||
|
CachedPixelShaderSetting<float> m_bloom_intensity_pixel;
|
||||||
|
float m_bloom_intensity;
|
||||||
|
CachedPixelShaderSetting<float> m_bloom_radius_pixel;
|
||||||
|
float m_bloom_radius;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void onSettingsChange(const std::string &name)
|
void onSettingsChange(const std::string &name)
|
||||||
{
|
{
|
||||||
if (name == "enable_fog")
|
if (name == "enable_fog")
|
||||||
m_fog_enabled = g_settings->getBool("enable_fog");
|
m_fog_enabled = g_settings->getBool("enable_fog");
|
||||||
|
if (name == "exposure_factor")
|
||||||
|
m_user_exposure_factor = g_settings->getFloat("exposure_factor", 0.1f, 10.0f);
|
||||||
|
if (name == "bloom_intensity")
|
||||||
|
m_bloom_intensity = g_settings->getFloat("bloom_intensity", 0.01f, 1.0f);
|
||||||
|
if (name == "bloom_radius")
|
||||||
|
m_bloom_radius = g_settings->getFloat("bloom_radius", 1.0f, 64.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void settingsCallback(const std::string &name, void *userdata)
|
static void settingsCallback(const std::string &name, void *userdata)
|
||||||
@ -441,6 +457,7 @@ public:
|
|||||||
GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off,
|
GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off,
|
||||||
f32 *fog_range, Client *client) :
|
f32 *fog_range, Client *client) :
|
||||||
m_sky(sky),
|
m_sky(sky),
|
||||||
|
m_client(client),
|
||||||
m_force_fog_off(force_fog_off),
|
m_force_fog_off(force_fog_off),
|
||||||
m_fog_range(fog_range),
|
m_fog_range(fog_range),
|
||||||
m_sky_bg_color("skyBgColor"),
|
m_sky_bg_color("skyBgColor"),
|
||||||
@ -454,13 +471,24 @@ public:
|
|||||||
m_minimap_yaw("yawVec"),
|
m_minimap_yaw("yawVec"),
|
||||||
m_camera_offset_pixel("cameraOffset"),
|
m_camera_offset_pixel("cameraOffset"),
|
||||||
m_camera_offset_vertex("cameraOffset"),
|
m_camera_offset_vertex("cameraOffset"),
|
||||||
m_base_texture("baseTexture"),
|
m_texture0("texture0"),
|
||||||
m_normal_texture("normalTexture"),
|
m_texture1("texture1"),
|
||||||
m_texture_flags("textureFlags"),
|
m_texture2("texture2"),
|
||||||
m_client(client)
|
m_texture3("texture3"),
|
||||||
|
m_texel_size0("texelSize0"),
|
||||||
|
m_exposure_factor_pixel("exposureFactor"),
|
||||||
|
m_bloom_intensity_pixel("bloomIntensity"),
|
||||||
|
m_bloom_radius_pixel("bloomRadius")
|
||||||
{
|
{
|
||||||
g_settings->registerChangedCallback("enable_fog", settingsCallback, this);
|
g_settings->registerChangedCallback("enable_fog", settingsCallback, this);
|
||||||
|
g_settings->registerChangedCallback("exposure_factor", settingsCallback, this);
|
||||||
|
g_settings->registerChangedCallback("bloom_intensity", settingsCallback, this);
|
||||||
|
g_settings->registerChangedCallback("bloom_radius", settingsCallback, this);
|
||||||
m_fog_enabled = g_settings->getBool("enable_fog");
|
m_fog_enabled = g_settings->getBool("enable_fog");
|
||||||
|
m_user_exposure_factor = g_settings->getFloat("exposure_factor", 0.1f, 10.0f);
|
||||||
|
m_bloom_enabled = g_settings->getBool("enable_bloom");
|
||||||
|
m_bloom_intensity = g_settings->getFloat("bloom_intensity", 0.01f, 1.0f);
|
||||||
|
m_bloom_radius = g_settings->getFloat("bloom_radius", 1.0f, 64.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
~GameGlobalShaderConstantSetter()
|
~GameGlobalShaderConstantSetter()
|
||||||
@ -526,12 +554,41 @@ public:
|
|||||||
m_camera_offset_pixel.set(camera_offset_array, services);
|
m_camera_offset_pixel.set(camera_offset_array, services);
|
||||||
m_camera_offset_vertex.set(camera_offset_array, services);
|
m_camera_offset_vertex.set(camera_offset_array, services);
|
||||||
|
|
||||||
SamplerLayer_t base_tex = 0,
|
SamplerLayer_t tex_id;
|
||||||
normal_tex = 1,
|
tex_id = 0;
|
||||||
flags_tex = 2;
|
m_texture0.set(&tex_id, services);
|
||||||
m_base_texture.set(&base_tex, services);
|
tex_id = 1;
|
||||||
m_normal_texture.set(&normal_tex, services);
|
m_texture1.set(&tex_id, services);
|
||||||
m_texture_flags.set(&flags_tex, services);
|
tex_id = 2;
|
||||||
|
m_texture2.set(&tex_id, services);
|
||||||
|
tex_id = 3;
|
||||||
|
m_texture3.set(&tex_id, services);
|
||||||
|
|
||||||
|
m_texel_size0.set(m_texel_size0_values.data(), services);
|
||||||
|
|
||||||
|
float exposure_factor = RenderingEngine::DEFAULT_EXPOSURE_FACTOR * m_user_exposure_factor;
|
||||||
|
if (std::isnan(exposure_factor))
|
||||||
|
exposure_factor = RenderingEngine::DEFAULT_EXPOSURE_FACTOR;
|
||||||
|
m_exposure_factor_pixel.set(&exposure_factor, services);
|
||||||
|
|
||||||
|
if (m_bloom_enabled) {
|
||||||
|
m_bloom_intensity_pixel.set(&m_bloom_intensity, services);
|
||||||
|
m_bloom_radius_pixel.set(&m_bloom_radius, services);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSetMaterial(const video::SMaterial &material)
|
||||||
|
{
|
||||||
|
video::ITexture *texture = material.getTexture(0);
|
||||||
|
if (texture) {
|
||||||
|
core::dimension2du size = texture->getSize();
|
||||||
|
m_texel_size0_values[0] = 1.f / size.Width;
|
||||||
|
m_texel_size0_values[1] = 1.f / size.Height;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_texel_size0_values[0] = 0.f;
|
||||||
|
m_texel_size0_values[1] = 0.f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,9 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
TextureBuffer::~TextureBuffer()
|
TextureBuffer::~TextureBuffer()
|
||||||
{
|
{
|
||||||
if (m_render_target)
|
|
||||||
m_driver->removeRenderTarget(m_render_target);
|
|
||||||
m_render_target = nullptr;
|
|
||||||
for (u32 index = 0; index < m_textures.size(); index++)
|
for (u32 index = 0; index < m_textures.size(); index++)
|
||||||
m_driver->removeTexture(m_textures[index]);
|
m_driver->removeTexture(m_textures[index]);
|
||||||
m_textures.clear();
|
m_textures.clear();
|
||||||
@ -37,8 +34,6 @@ TextureBuffer::~TextureBuffer()
|
|||||||
|
|
||||||
video::ITexture *TextureBuffer::getTexture(u8 index)
|
video::ITexture *TextureBuffer::getTexture(u8 index)
|
||||||
{
|
{
|
||||||
if (index == m_depth_texture_index)
|
|
||||||
return m_depth_texture;
|
|
||||||
if (index >= m_textures.size())
|
if (index >= m_textures.size())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return m_textures[index];
|
return m_textures[index];
|
||||||
@ -52,9 +47,6 @@ void TextureBuffer::setTexture(u8 index, core::dimension2du size, const std::str
|
|||||||
if (m_definitions.size() <= index)
|
if (m_definitions.size() <= index)
|
||||||
m_definitions.resize(index + 1);
|
m_definitions.resize(index + 1);
|
||||||
|
|
||||||
if (m_depth_texture_index == index)
|
|
||||||
m_depth_texture_index = NO_DEPTH_TEXTURE;
|
|
||||||
|
|
||||||
auto &definition = m_definitions[index];
|
auto &definition = m_definitions[index];
|
||||||
definition.valid = true;
|
definition.valid = true;
|
||||||
definition.dirty = true;
|
definition.dirty = true;
|
||||||
@ -71,9 +63,6 @@ void TextureBuffer::setTexture(u8 index, v2f scale_factor, const std::string &na
|
|||||||
if (m_definitions.size() <= index)
|
if (m_definitions.size() <= index)
|
||||||
m_definitions.resize(index + 1);
|
m_definitions.resize(index + 1);
|
||||||
|
|
||||||
if (m_depth_texture_index == index)
|
|
||||||
m_depth_texture_index = NO_DEPTH_TEXTURE;
|
|
||||||
|
|
||||||
auto &definition = m_definitions[index];
|
auto &definition = m_definitions[index];
|
||||||
definition.valid = true;
|
definition.valid = true;
|
||||||
definition.dirty = true;
|
definition.dirty = true;
|
||||||
@ -83,20 +72,6 @@ void TextureBuffer::setTexture(u8 index, v2f scale_factor, const std::string &na
|
|||||||
definition.format = format;
|
definition.format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBuffer::setDepthTexture(u8 index, core::dimension2du size, const std::string &name, video::ECOLOR_FORMAT format)
|
|
||||||
{
|
|
||||||
assert(index != NO_DEPTH_TEXTURE);
|
|
||||||
setTexture(index, size, name, format);
|
|
||||||
m_depth_texture_index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureBuffer::setDepthTexture(u8 index, v2f scale_factor, const std::string &name, video::ECOLOR_FORMAT format)
|
|
||||||
{
|
|
||||||
assert(index != NO_DEPTH_TEXTURE);
|
|
||||||
setTexture(index, scale_factor, name, format);
|
|
||||||
m_depth_texture_index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureBuffer::reset(PipelineContext &context)
|
void TextureBuffer::reset(PipelineContext &context)
|
||||||
{
|
{
|
||||||
if (!m_driver)
|
if (!m_driver)
|
||||||
@ -116,41 +91,14 @@ void TextureBuffer::reset(PipelineContext &context)
|
|||||||
m_textures.push_back(nullptr);
|
m_textures.push_back(nullptr);
|
||||||
|
|
||||||
// change textures to match definitions
|
// change textures to match definitions
|
||||||
bool modified = false;
|
|
||||||
for (u32 i = 0; i < m_definitions.size(); i++) {
|
for (u32 i = 0; i < m_definitions.size(); i++) {
|
||||||
video::ITexture **ptr = &m_textures[i];
|
video::ITexture **ptr = &m_textures[i];
|
||||||
if (i == m_depth_texture_index) {
|
|
||||||
if (*ptr) {
|
|
||||||
m_driver->removeTexture(*ptr);
|
|
||||||
*ptr = nullptr;
|
|
||||||
}
|
|
||||||
ptr = &m_depth_texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ensureTexture(ptr, m_definitions[i], context))
|
ensureTexture(ptr, m_definitions[i], context);
|
||||||
modified = true;
|
|
||||||
m_definitions[i].dirty = false;
|
m_definitions[i].dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sude depth texture is removed and reset
|
RenderSource::reset(context);
|
||||||
if (m_depth_texture_index == NO_DEPTH_TEXTURE && m_depth_texture) {
|
|
||||||
m_driver->removeTexture(m_depth_texture);
|
|
||||||
m_depth_texture = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_render_target)
|
|
||||||
m_render_target = m_driver->addRenderTarget();
|
|
||||||
|
|
||||||
if (modified)
|
|
||||||
m_render_target->setTexture(m_textures, m_depth_texture);
|
|
||||||
|
|
||||||
RenderTarget::reset(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureBuffer::activate(PipelineContext &context)
|
|
||||||
{
|
|
||||||
m_driver->setRenderTargetEx(m_render_target, m_clear ? video::ECBF_DEPTH | video::ECBF_COLOR : 0, context.clear_color);
|
|
||||||
RenderTarget::activate(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureBuffer::ensureTexture(video::ITexture **texture, const TextureDefinition& definition, PipelineContext &context)
|
bool TextureBuffer::ensureTexture(video::ITexture **texture, const TextureDefinition& definition, PipelineContext &context)
|
||||||
@ -186,15 +134,48 @@ bool TextureBuffer::ensureTexture(video::ITexture **texture, const TextureDefini
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextureBufferOutput::TextureBufferOutput(TextureBuffer *_buffer, u8 _texture_index)
|
TextureBufferOutput::TextureBufferOutput(TextureBuffer *_buffer, u8 _texture_index)
|
||||||
: buffer(_buffer), texture_index(_texture_index)
|
: buffer(_buffer), texture_map({_texture_index})
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
TextureBufferOutput::TextureBufferOutput(TextureBuffer *_buffer, const std::vector<u8> &_texture_map)
|
||||||
|
: buffer(_buffer), texture_map(_texture_map)
|
||||||
|
{}
|
||||||
|
|
||||||
|
TextureBufferOutput::TextureBufferOutput(TextureBuffer *_buffer, const std::vector<u8> &_texture_map, u8 _depth_stencil)
|
||||||
|
: buffer(_buffer), texture_map(_texture_map), depth_stencil(_depth_stencil)
|
||||||
|
{}
|
||||||
|
|
||||||
|
TextureBufferOutput::~TextureBufferOutput()
|
||||||
|
{
|
||||||
|
if (render_target && driver)
|
||||||
|
driver->removeRenderTarget(render_target);
|
||||||
|
}
|
||||||
|
|
||||||
void TextureBufferOutput::activate(PipelineContext &context)
|
void TextureBufferOutput::activate(PipelineContext &context)
|
||||||
{
|
{
|
||||||
auto texture = buffer->getTexture(texture_index);
|
if (!driver)
|
||||||
auto driver = context.device->getVideoDriver();
|
driver = context.device->getVideoDriver();
|
||||||
driver->setRenderTarget(texture, m_clear, m_clear, context.clear_color);
|
|
||||||
driver->OnResize(texture->getSize());
|
if (!render_target)
|
||||||
|
render_target = driver->addRenderTarget();
|
||||||
|
|
||||||
|
core::array<video::ITexture *> textures;
|
||||||
|
core::dimension2du size(0, 0);
|
||||||
|
for (size_t i = 0; i < texture_map.size(); i++) {
|
||||||
|
video::ITexture *texture = buffer->getTexture(texture_map[i]);
|
||||||
|
textures.push_back(texture);
|
||||||
|
if (texture && size.Width == 0)
|
||||||
|
size = texture->getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
video::ITexture *depth_texture = nullptr;
|
||||||
|
if (depth_stencil != NO_DEPTH_TEXTURE)
|
||||||
|
depth_texture = buffer->getTexture(depth_stencil);
|
||||||
|
|
||||||
|
render_target->setTexture(textures, depth_texture);
|
||||||
|
|
||||||
|
driver->setRenderTargetEx(render_target, m_clear ? video::ECBF_ALL : video::ECBF_NONE, context.clear_color);
|
||||||
|
driver->OnResize(size);
|
||||||
|
|
||||||
RenderTarget::activate(context);
|
RenderTarget::activate(context);
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ protected:
|
|||||||
*
|
*
|
||||||
* @note Use of TextureBuffer requires use of gl_FragData[] in the shader
|
* @note Use of TextureBuffer requires use of gl_FragData[] in the shader
|
||||||
*/
|
*/
|
||||||
class TextureBuffer : public RenderSource, public RenderTarget
|
class TextureBuffer : public RenderSource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~TextureBuffer() override;
|
virtual ~TextureBuffer() override;
|
||||||
@ -138,29 +138,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setTexture(u8 index, v2f scale_factor, const std::string& name, video::ECOLOR_FORMAT format);
|
void setTexture(u8 index, v2f scale_factor, const std::string& name, video::ECOLOR_FORMAT format);
|
||||||
|
|
||||||
/**
|
|
||||||
* @Configure depth texture and assign index
|
|
||||||
*
|
|
||||||
* @param index index to use for the depth texture
|
|
||||||
* @param size width and height of the texture in pixels
|
|
||||||
* @param name unique name for the texture
|
|
||||||
* @param format color format
|
|
||||||
*/
|
|
||||||
void setDepthTexture(u8 index, core::dimension2du size, const std::string& name, video::ECOLOR_FORMAT format);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Configure depth texture and assign index
|
|
||||||
*
|
|
||||||
* @param index index to use for the depth texture
|
|
||||||
* @param scale_factor relation of the texture dimensions to the screen dimensions
|
|
||||||
* @param name unique name for the texture
|
|
||||||
* @param format color format
|
|
||||||
*/
|
|
||||||
void setDepthTexture(u8 index, v2f scale_factor, const std::string& name, video::ECOLOR_FORMAT format);
|
|
||||||
|
|
||||||
virtual u8 getTextureCount() override { return m_textures.size(); }
|
virtual u8 getTextureCount() override { return m_textures.size(); }
|
||||||
virtual video::ITexture *getTexture(u8 index) override;
|
virtual video::ITexture *getTexture(u8 index) override;
|
||||||
virtual void activate(PipelineContext &context) override;
|
|
||||||
virtual void reset(PipelineContext &context) override;
|
virtual void reset(PipelineContext &context) override;
|
||||||
private:
|
private:
|
||||||
static const u8 NO_DEPTH_TEXTURE = 255;
|
static const u8 NO_DEPTH_TEXTURE = 255;
|
||||||
@ -189,9 +168,6 @@ private:
|
|||||||
video::IVideoDriver *m_driver { nullptr };
|
video::IVideoDriver *m_driver { nullptr };
|
||||||
std::vector<TextureDefinition> m_definitions;
|
std::vector<TextureDefinition> m_definitions;
|
||||||
core::array<video::ITexture *> m_textures;
|
core::array<video::ITexture *> m_textures;
|
||||||
video::ITexture *m_depth_texture { nullptr };
|
|
||||||
u8 m_depth_texture_index { NO_DEPTH_TEXTURE };
|
|
||||||
video::IRenderTarget *m_render_target { nullptr };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,10 +177,18 @@ class TextureBufferOutput : public RenderTarget
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextureBufferOutput(TextureBuffer *buffer, u8 texture_index);
|
TextureBufferOutput(TextureBuffer *buffer, u8 texture_index);
|
||||||
|
TextureBufferOutput(TextureBuffer *buffer, const std::vector<u8> &texture_map);
|
||||||
|
TextureBufferOutput(TextureBuffer *buffer, const std::vector<u8> &texture_map, u8 depth_stencil);
|
||||||
|
virtual ~TextureBufferOutput() override;
|
||||||
void activate(PipelineContext &context) override;
|
void activate(PipelineContext &context) override;
|
||||||
private:
|
private:
|
||||||
|
static const u8 NO_DEPTH_TEXTURE = 255;
|
||||||
|
|
||||||
TextureBuffer *buffer;
|
TextureBuffer *buffer;
|
||||||
u8 texture_index;
|
std::vector<u8> texture_map;
|
||||||
|
u8 depth_stencil { NO_DEPTH_TEXTURE };
|
||||||
|
video::IRenderTarget* render_target { nullptr };
|
||||||
|
video::IVideoDriver* driver { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,31 +88,77 @@ void PostProcessingStep::run(PipelineContext &context)
|
|||||||
driver->drawVertexPrimitiveList(&vertices, 4, &indices, 2);
|
driver->drawVertexPrimitiveList(&vertices, 4, &indices, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PostProcessingStep::setBilinearFilter(u8 index, bool value)
|
||||||
|
{
|
||||||
|
assert(index < video::MATERIAL_MAX_TEXTURES);
|
||||||
|
material.TextureLayer[index].BilinearFilter = value;
|
||||||
|
}
|
||||||
|
|
||||||
RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep, v2f scale, Client *client)
|
RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep, v2f scale, Client *client)
|
||||||
{
|
{
|
||||||
auto buffer = pipeline->createOwned<TextureBuffer>();
|
auto buffer = pipeline->createOwned<TextureBuffer>();
|
||||||
static const u8 TEXTURE_COLOR = 0;
|
auto driver = client->getSceneManager()->getVideoDriver();
|
||||||
static const u8 TEXTURE_DEPTH = 3;
|
|
||||||
|
|
||||||
// init post-processing buffer
|
// configure texture formats
|
||||||
buffer->setTexture(TEXTURE_COLOR, scale, "3d_render", video::ECF_A8R8G8B8);
|
video::ECOLOR_FORMAT color_format = video::ECF_A8R8G8B8;
|
||||||
|
if (driver->queryTextureFormat(video::ECF_A16B16G16R16F))
|
||||||
|
color_format = video::ECF_A16B16G16R16F;
|
||||||
|
|
||||||
video::ECOLOR_FORMAT depth_format = video::ECF_D16; // fallback depth format
|
video::ECOLOR_FORMAT depth_format = video::ECF_D16; // fallback depth format
|
||||||
auto driver = client->getSceneManager()->getVideoDriver();
|
|
||||||
if (driver->queryTextureFormat(video::ECF_D32))
|
if (driver->queryTextureFormat(video::ECF_D32))
|
||||||
depth_format = video::ECF_D32;
|
depth_format = video::ECF_D32;
|
||||||
else if (driver->queryTextureFormat(video::ECF_D24S8))
|
else if (driver->queryTextureFormat(video::ECF_D24S8))
|
||||||
depth_format = video::ECF_D24S8;
|
depth_format = video::ECF_D24S8;
|
||||||
buffer->setDepthTexture(TEXTURE_DEPTH, scale, "3d_depthmap", depth_format);
|
|
||||||
|
|
||||||
|
// init post-processing buffer
|
||||||
|
static const u8 TEXTURE_COLOR = 0;
|
||||||
|
static const u8 TEXTURE_DEPTH = 1;
|
||||||
|
static const u8 TEXTURE_BLOOM = 2;
|
||||||
|
static const u8 TEXTURE_BLUR = 3;
|
||||||
|
static const u8 TEXTURE_BLUR_SECONDARY = 4;
|
||||||
|
|
||||||
|
buffer->setTexture(TEXTURE_COLOR, scale, "3d_render", color_format);
|
||||||
|
buffer->setTexture(TEXTURE_DEPTH, scale, "3d_depthmap", depth_format);
|
||||||
|
|
||||||
// attach buffer to the previous step
|
// attach buffer to the previous step
|
||||||
previousStep->setRenderTarget(buffer);
|
previousStep->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, std::vector<u8> { TEXTURE_COLOR }, TEXTURE_DEPTH));
|
||||||
|
|
||||||
// post-processing stage
|
// post-processing stage
|
||||||
// set up shader
|
// set up bloom
|
||||||
u32 shader_id = client->getShaderSource()->getShader("second_stage", TILE_MATERIAL_PLAIN, NDT_MESH);
|
if (g_settings->getBool("enable_bloom")) {
|
||||||
|
|
||||||
RenderStep *effect = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_COLOR });
|
buffer->setTexture(TEXTURE_BLUR, scale * 0.5, "blur", color_format);
|
||||||
|
buffer->setTexture(TEXTURE_BLOOM, scale * 0.5, "bloom", color_format);
|
||||||
|
u8 bloom_input_texture = TEXTURE_BLOOM;
|
||||||
|
|
||||||
|
if (g_settings->getBool("enable_bloom_dedicated_texture")) {
|
||||||
|
buffer->setTexture(TEXTURE_BLUR_SECONDARY, scale * 0.5, "blur2", color_format);
|
||||||
|
bloom_input_texture = TEXTURE_BLUR_SECONDARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get bright spots
|
||||||
|
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 });
|
||||||
|
extract_bloom->setRenderSource(buffer);
|
||||||
|
extract_bloom->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, bloom_input_texture));
|
||||||
|
// horizontal blur
|
||||||
|
shader_id = client->getShaderSource()->getShader("blur_h", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||||
|
RenderStep *blur_h = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { bloom_input_texture });
|
||||||
|
blur_h->setRenderSource(buffer);
|
||||||
|
blur_h->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_BLUR));
|
||||||
|
// vertical blur
|
||||||
|
shader_id = client->getShaderSource()->getShader("blur_v", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||||
|
RenderStep *blur_v = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_BLUR });
|
||||||
|
blur_v->setRenderSource(buffer);
|
||||||
|
blur_v->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_BLOOM));
|
||||||
|
}
|
||||||
|
|
||||||
|
// final post-processing
|
||||||
|
u32 shader_id = client->getShaderSource()->getShader("second_stage", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||||
|
PostProcessingStep *effect = pipeline->createOwned<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_COLOR, TEXTURE_BLOOM });
|
||||||
|
pipeline->addStep(effect);
|
||||||
|
effect->setBilinearFilter(1, true); // apply filter to the bloom
|
||||||
effect->setRenderSource(buffer);
|
effect->setRenderSource(buffer);
|
||||||
return effect;
|
return effect;
|
||||||
}
|
}
|
||||||
|
@ -22,17 +22,33 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "stereo.h"
|
#include "stereo.h"
|
||||||
#include "pipeline.h"
|
#include "pipeline.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step to apply post-processing filter to the rendered image
|
||||||
|
*/
|
||||||
class PostProcessingStep : public RenderStep
|
class PostProcessingStep : public RenderStep
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Construct a new PostProcessingStep object
|
||||||
|
*
|
||||||
|
* @param shader_id ID of the shader in IShaderSource
|
||||||
|
* @param texture_map Map of textures to be chosen from the render source
|
||||||
|
*/
|
||||||
PostProcessingStep(u32 shader_id, const std::vector<u8> &texture_map);
|
PostProcessingStep(u32 shader_id, const std::vector<u8> &texture_map);
|
||||||
|
|
||||||
|
|
||||||
void setRenderSource(RenderSource *source) override;
|
void setRenderSource(RenderSource *source) override;
|
||||||
void setRenderTarget(RenderTarget *target) override;
|
void setRenderTarget(RenderTarget *target) override;
|
||||||
void reset(PipelineContext &context) override;
|
void reset(PipelineContext &context) override;
|
||||||
void run(PipelineContext &context) override;
|
void run(PipelineContext &context) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure bilinear filtering for a specific texture layer
|
||||||
|
*
|
||||||
|
* @param index Index of the texture layer
|
||||||
|
* @param value true to enable the bilinear filter, false to disable
|
||||||
|
*/
|
||||||
|
void setBilinearFilter(u8 index, bool value);
|
||||||
private:
|
private:
|
||||||
u32 shader_id;
|
u32 shader_id;
|
||||||
std::vector<u8> texture_map;
|
std::vector<u8> texture_map;
|
||||||
|
@ -46,6 +46,10 @@ class RenderingCore;
|
|||||||
class RenderingEngine
|
class RenderingEngine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// Default color factor before applying effects like bloom or tomemapping
|
||||||
|
/// this is derived from tonemapping code and tuned empirically
|
||||||
|
static constexpr float DEFAULT_EXPOSURE_FACTOR = 2.5f;
|
||||||
|
|
||||||
RenderingEngine(IEventReceiver *eventReceiver);
|
RenderingEngine(IEventReceiver *eventReceiver);
|
||||||
~RenderingEngine();
|
~RenderingEngine();
|
||||||
|
|
||||||
|
@ -682,6 +682,13 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
|
|||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// map legacy semantic texture names to texture identifiers
|
||||||
|
fragment_header += R"(
|
||||||
|
#define baseTexture texture0
|
||||||
|
#define normalTexture texture1
|
||||||
|
#define textureFlags texture2
|
||||||
|
)";
|
||||||
|
|
||||||
// Since this is the first time we're using the GL bindings be extra careful.
|
// Since this is the first time we're using the GL bindings be extra careful.
|
||||||
// This should be removed before 5.6.0 or similar.
|
// This should be removed before 5.6.0 or similar.
|
||||||
if (!GL.GetString) {
|
if (!GL.GetString) {
|
||||||
@ -771,6 +778,12 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
|
|||||||
shaders_header << "#define SOFTSHADOWRADIUS " << shadow_soft_radius << "\n";
|
shaders_header << "#define SOFTSHADOWRADIUS " << shadow_soft_radius << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_settings->getBool("enable_bloom")) {
|
||||||
|
shaders_header << "#define ENABLE_BLOOM 1\n";
|
||||||
|
if (g_settings->getBool("enable_bloom_debug"))
|
||||||
|
shaders_header << "#define ENABLE_BLOOM_DEBUG 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();
|
||||||
|
@ -263,6 +263,12 @@ void set_default_settings()
|
|||||||
settings->setDefault("water_wave_speed", "5.0");
|
settings->setDefault("water_wave_speed", "5.0");
|
||||||
settings->setDefault("enable_waving_leaves", "false");
|
settings->setDefault("enable_waving_leaves", "false");
|
||||||
settings->setDefault("enable_waving_plants", "false");
|
settings->setDefault("enable_waving_plants", "false");
|
||||||
|
settings->setDefault("exposure_factor", "1.0");
|
||||||
|
settings->setDefault("enable_bloom", "false");
|
||||||
|
settings->setDefault("enable_bloom_debug", "false");
|
||||||
|
settings->setDefault("enable_bloom_dedicated_texture", "false");
|
||||||
|
settings->setDefault("bloom_intensity", "0.05");
|
||||||
|
settings->setDefault("bloom_radius", "16");
|
||||||
|
|
||||||
// Effects Shadows
|
// Effects Shadows
|
||||||
settings->setDefault("enable_dynamic_shadows", "false");
|
settings->setDefault("enable_dynamic_shadows", "false");
|
||||||
|
Loading…
Reference in New Issue
Block a user