Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions doc/classes/Environment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
<description>
Resource for environment nodes (like [WorldEnvironment]) that define multiple environment operations (such as background [Sky] or [Color], ambient light, fog, depth-of-field...). These parameters affect the final render of the scene. The order of these operations is:
- Depth of Field Blur
- Auto Exposure
- Glow
- Tonemap (Auto Exposure)
- Tonemap
- Adjustments
</description>
<tutorials>
Expand Down Expand Up @@ -124,15 +125,15 @@
<member name="fog_sun_scatter" type="float" setter="set_fog_sun_scatter" getter="get_fog_sun_scatter" default="0.0">
If set above [code]0.0[/code], renders the scene's directional light(s) in the fog color depending on the view angle. This can be used to give the impression that the sun is "piercing" through the fog.
</member>
<member name="glow_blend_mode" type="int" setter="set_glow_blend_mode" getter="get_glow_blend_mode" enum="Environment.GlowBlendMode" default="2">
<member name="glow_blend_mode" type="int" setter="set_glow_blend_mode" getter="get_glow_blend_mode" enum="Environment.GlowBlendMode" default="1">
The glow blending mode.
[b]Note:[/b] [member glow_blend_mode] has no effect when using the Compatibility rendering method, due to this rendering method using a simpler glow implementation optimized for low-end devices.
[b]Note:[/b] The Compatibility renderer always uses [constant GLOW_BLEND_MODE_SCREEN] and [member glow_blend_mode] will have no effect.
</member>
<member name="glow_bloom" type="float" setter="set_glow_bloom" getter="get_glow_bloom" default="0.0">
The bloom's intensity. If set to a value higher than [code]0[/code], this will make glow visible in areas darker than the [member glow_hdr_threshold].
</member>
<member name="glow_enabled" type="bool" setter="set_glow_enabled" getter="is_glow_enabled" default="false">
If [code]true[/code], the glow effect is enabled. This simulates real world eye/camera behavior where bright pixels bleed onto surrounding pixels.
If [code]true[/code], the glow effect is enabled. This simulates real world atmosphere and eye/camera behavior by causing bright pixels to bleed onto surrounding pixels.
[b]Note:[/b] When using the Mobile rendering method, glow looks different due to the lower dynamic range available in the Mobile rendering method.
[b]Note:[/b] When using the Compatibility rendering method, glow uses a different implementation with some properties being unavailable and hidden from the inspector: [code]glow_levels/*[/code], [member glow_normalized], [member glow_strength], [member glow_blend_mode], [member glow_mix], [member glow_map], and [member glow_map_strength]. This implementation is optimized to run on low-end devices and is less flexible as a result.
</member>
Expand All @@ -145,26 +146,26 @@
<member name="glow_hdr_threshold" type="float" setter="set_glow_hdr_bleed_threshold" getter="get_glow_hdr_bleed_threshold" default="1.0">
The lower threshold of the HDR glow. When using the Mobile rendering method (which only supports a lower dynamic range up to [code]2.0[/code]), this may need to be below [code]1.0[/code] for glow to be visible. A value of [code]0.9[/code] works well in this case. This value also needs to be decreased below [code]1.0[/code] when using glow in 2D, as 2D rendering is performed in SDR.
</member>
<member name="glow_intensity" type="float" setter="set_glow_intensity" getter="get_glow_intensity" default="0.8">
<member name="glow_intensity" type="float" setter="set_glow_intensity" getter="get_glow_intensity" default="0.3">
The overall brightness multiplier of the glow effect. When using the Mobile rendering method (which only supports a lower dynamic range up to [code]2.0[/code]), this should be increased to [code]1.5[/code] to compensate.
</member>
<member name="glow_levels/1" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
<member name="glow_levels/1" type="float" setter="set_glow_level" getter="get_glow_level" default="1.0">
The intensity of the 1st level of glow. This is the most "local" level (least blurry).
[b]Note:[/b] [member glow_levels/1] has no effect when using the Compatibility rendering method, due to this rendering method using a simpler glow implementation optimized for low-end devices.
</member>
<member name="glow_levels/2" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
<member name="glow_levels/2" type="float" setter="set_glow_level" getter="get_glow_level" default="0.8">
The intensity of the 2nd level of glow.
[b]Note:[/b] [member glow_levels/2] has no effect when using the Compatibility rendering method, due to this rendering method using a simpler glow implementation optimized for low-end devices.
</member>
<member name="glow_levels/3" type="float" setter="set_glow_level" getter="get_glow_level" default="1.0">
<member name="glow_levels/3" type="float" setter="set_glow_level" getter="get_glow_level" default="0.4">
The intensity of the 3rd level of glow.
[b]Note:[/b] [member glow_levels/3] has no effect when using the Compatibility rendering method, due to this rendering method using a simpler glow implementation optimized for low-end devices.
</member>
<member name="glow_levels/4" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
<member name="glow_levels/4" type="float" setter="set_glow_level" getter="get_glow_level" default="0.1">
The intensity of the 4th level of glow.
[b]Note:[/b] [member glow_levels/4] has no effect when using the Compatibility rendering method, due to this rendering method using a simpler glow implementation optimized for low-end devices.
</member>
<member name="glow_levels/5" type="float" setter="set_glow_level" getter="get_glow_level" default="1.0">
<member name="glow_levels/5" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
The intensity of the 5th level of glow.
[b]Note:[/b] [member glow_levels/5] has no effect when using the Compatibility rendering method, due to this rendering method using a simpler glow implementation optimized for low-end devices.
</member>
Expand Down Expand Up @@ -434,19 +435,19 @@
[b]Note:[/b] [member tonemap_white] is fixed at a value of [code]16.29[/code], which makes [constant TONE_MAPPER_AGX] unsuitable for use with the Mobile rendering method.
</constant>
<constant name="GLOW_BLEND_MODE_ADDITIVE" value="0" enum="GlowBlendMode">
Additive glow blending mode. Mostly used for particles, glows (bloom), lens flare, bright sources.
Adds the glow effect to the scene.
</constant>
<constant name="GLOW_BLEND_MODE_SCREEN" value="1" enum="GlowBlendMode">
Screen glow blending mode. Increases brightness, used frequently with bloom.
Adds the glow effect to the scene after modifying the glow influence based on the scene value; dark values will be highly influenced by glow and bright values will not be influenced by glow. This approach avoids bright values becoming overly bright from the glow effect. [member tonemap_white] is used to determine the maximum scene value where the glow should have no influence. When [member tonemap_mode] is set to [constant TONE_MAPPER_LINEAR], a value of [code]1.0[/code] will be used as the maximum scene value.
</constant>
<constant name="GLOW_BLEND_MODE_SOFTLIGHT" value="2" enum="GlowBlendMode">
Soft light glow blending mode. Modifies contrast, exposes shadows and highlights (vivid bloom).
Adds the glow effect to the tonemapped image after modifying the glow influence based on the image value; dark values and bright values will not be influenced by glow and mid-range values will be highly influenced by glow. This approach avoids bright values becoming overly bright from the glow effect. The glow will have the largest influence on image values of [code]0.25[/code] and will have no influence when applied to image values greater than [code]1.0[/code].
</constant>
<constant name="GLOW_BLEND_MODE_REPLACE" value="3" enum="GlowBlendMode">
Replace glow blending mode. Replaces all pixels' color by the glow value. This can be used to simulate a full-screen blur effect by tweaking the glow parameters to match the original image's brightness.
Replaces all pixels' color by the glow effect. This can be used to simulate a full-screen blur effect by tweaking the glow parameters to match the original image's brightness or to preview glow configuration in the editor.
</constant>
<constant name="GLOW_BLEND_MODE_MIX" value="4" enum="GlowBlendMode">
Mixes the glow with the underlying color to avoid increasing brightness as much while still maintaining a glow effect.
Mixes the glow image with the scene image. Best used with [member glow_bloom] to avoid darkening the scene.
</constant>
<constant name="FOG_MODE_EXPONENTIAL" value="0" enum="FogMode">
Use a physically-based fog model defined primarily by fog density.
Expand Down
3 changes: 2 additions & 1 deletion drivers/gles3/effects/post_effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ void PostEffects::_draw_screen_triangle() {
glBindVertexArray(0);
}

void PostEffects::post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuint p_source_color, Size2i p_source_size, float p_luminance_multiplier, const Glow::GLOWLEVEL *p_glow_buffers, float p_glow_intensity, uint32_t p_view, bool p_use_multiview, uint64_t p_spec_constants) {
void PostEffects::post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuint p_source_color, Size2i p_source_size, float p_luminance_multiplier, const Glow::GLOWLEVEL *p_glow_buffers, float p_glow_intensity, float p_srgb_white, uint32_t p_view, bool p_use_multiview, uint64_t p_spec_constants) {
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_BLEND);
Expand Down Expand Up @@ -124,6 +124,7 @@ void PostEffects::post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuin

post.shader.version_set_uniform(PostShaderGLES3::PIXEL_SIZE, 1.0 / p_source_size.x, 1.0 / p_source_size.y, post.shader_version, mode, flags);
post.shader.version_set_uniform(PostShaderGLES3::GLOW_INTENSITY, p_glow_intensity, post.shader_version, mode, flags);
post.shader.version_set_uniform(PostShaderGLES3::SRGB_WHITE, p_srgb_white, post.shader_version, mode, flags);
}

post.shader.version_set_uniform(PostShaderGLES3::VIEW, float(p_view), post.shader_version, mode, flags);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gles3/effects/post_effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class PostEffects {
PostEffects();
~PostEffects();

void post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuint p_source_color, Size2i p_source_size, float p_luminance_multiplier, const Glow::GLOWLEVEL *p_glow_buffers, float p_glow_intensity, uint32_t p_view = 0, bool p_use_multiview = false, uint64_t p_spec_constants = 0);
void post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuint p_source_color, Size2i p_source_size, float p_luminance_multiplier, const Glow::GLOWLEVEL *p_glow_buffers, float p_glow_intensity, float p_srgb_white, uint32_t p_view = 0, bool p_use_multiview = false, uint64_t p_spec_constants = 0);
};

} //namespace GLES3
Expand Down
9 changes: 7 additions & 2 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2814,16 +2814,21 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
float glow_hdr_bleed_threshold = 1.0;
float glow_hdr_bleed_scale = 2.0;
float glow_hdr_luminance_cap = 12.0;
float srgb_white = 1.0;
if (p_render_data->environment.is_valid()) {
glow_enabled = environment_get_glow_enabled(p_render_data->environment);
glow_intensity = environment_get_glow_intensity(p_render_data->environment);
glow_bloom = environment_get_glow_bloom(p_render_data->environment);
glow_hdr_bleed_threshold = environment_get_glow_hdr_bleed_threshold(p_render_data->environment);
glow_hdr_bleed_scale = environment_get_glow_hdr_bleed_scale(p_render_data->environment);
glow_hdr_luminance_cap = environment_get_glow_hdr_luminance_cap(p_render_data->environment);
srgb_white = environment_get_white(p_render_data->environment);
}

if (glow_enabled) {
// Only glow requires srgb_white to be calculated.
srgb_white = 1.055 * Math::pow(srgb_white, 1.0f / 2.4f) - 0.055;

rb->check_glow_buffers();
}

Expand Down Expand Up @@ -2890,7 +2895,7 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
}

// Copy color buffer
post_effects->post_copy(fbo_rt, target_size, color, internal_size, p_render_data->luminance_multiplier, glow_buffers, glow_intensity, 0, false, bcs_spec_constants);
post_effects->post_copy(fbo_rt, target_size, color, internal_size, p_render_data->luminance_multiplier, glow_buffers, glow_intensity, srgb_white, 0, false, bcs_spec_constants);

// Copy depth buffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_int);
Expand Down Expand Up @@ -2958,7 +2963,7 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend

glBindFramebuffer(GL_FRAMEBUFFER, fbos[2]);
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, write_color, 0, v);
post_effects->post_copy(fbos[2], target_size, source_color, internal_size, p_render_data->luminance_multiplier, glow_buffers, glow_intensity, v, true, bcs_spec_constants);
post_effects->post_copy(fbos[2], target_size, source_color, internal_size, p_render_data->luminance_multiplier, glow_buffers, glow_intensity, srgb_white, v, true, bcs_spec_constants);
}

// Copy depth
Expand Down
39 changes: 32 additions & 7 deletions drivers/gles3/shaders/effects/post.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ uniform float luminance_multiplier;
uniform sampler2D glow_color; // texunit:1
uniform vec2 pixel_size;
uniform float glow_intensity;
uniform float srgb_white;

vec4 get_glow_color(vec2 uv) {
vec2 half_pixel = pixel_size * 0.5;
Expand All @@ -58,6 +59,10 @@ vec4 get_glow_color(vec2 uv) {
color += textureLod(glow_color, uv + vec2(0.0, -half_pixel.y * 2.0), 0.0);
color += textureLod(glow_color, uv + vec2(-half_pixel.x, -half_pixel.y), 0.0) * 2.0;

#ifdef USE_LUMINANCE_MULTIPLIER
color = color / luminance_multiplier;
#endif

return color / 12.0;
}
#endif // USE_GLOW
Expand Down Expand Up @@ -102,17 +107,37 @@ void main() {
vec4 color = texture(source_color, uv_interp);
#endif

#ifdef USE_LUMINANCE_MULTIPLIER
color = color / luminance_multiplier;
#endif

#ifdef USE_GLOW
// Glow blending is performed before srgb_to_linear because
// the glow texture was created from a nonlinear sRGB-encoded
// scene, so it only makes sense to add this glow to an equally
// nonlinear sRGB-encoded scene.

vec4 glow = get_glow_color(uv_interp) * glow_intensity;

// Just use softlight...
glow.rgb = clamp(glow.rgb, vec3(0.0f), vec3(1.0f));
color.rgb = max((color.rgb + glow.rgb) - (color.rgb * glow.rgb), vec3(0.0));
#endif // USE_GLOW
// Glow always uses the screen blend mode in the Compatibility renderer:

#ifdef USE_LUMINANCE_MULTIPLIER
color = color / luminance_multiplier;
#endif
// Glow cannot be above 1.0 after normalizing and should be non-negative
// to produce expected results. It is possible that glow can be negative
// if negative lights were used in the scene.
// We clamp to srgb_white because glow will be normalized to this range.
// Note: srgb_white cannot be smaller than the maximum output value (1.0).
glow.rgb = clamp(glow.rgb, 0.0, srgb_white);

// Normalize to srgb_white range.
//glow.rgb /= srgb_white;
//color.rgb /= srgb_white;
//color.rgb = (color.rgb + glow.rgb) - (color.rgb * glow.rgb);
// Expand back to original range.
//color.rgb *= srgb_white;

// The following is a mathematically simplified version of the above.
color.rgb = color.rgb + glow.rgb - (color.rgb * glow.rgb / srgb_white);
#endif // USE_GLOW

color.rgb = srgb_to_linear(color.rgb);
color.rgb = apply_tonemapping(color.rgb, white);
Expand Down
14 changes: 7 additions & 7 deletions scene/resources/environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1247,7 +1247,7 @@ void Environment::_bind_methods() {
ADD_GROUP("Tonemap", "tonemap_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reinhard,Filmic,ACES,AgX"), "set_tonemapper", "get_tonemapper");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_exposure", "get_tonemap_exposure");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_white", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_white", "get_tonemap_white");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_white", PROPERTY_HINT_RANGE, "1,16,0.01,or_greater"), "set_tonemap_white", "get_tonemap_white");

// SSR

Expand Down Expand Up @@ -1405,7 +1405,7 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_strength", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_glow_strength", "get_glow_strength");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_mix", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_glow_mix", "get_glow_mix");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_bloom", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_glow_bloom", "get_glow_bloom");
ADD_PROPERTY(PropertyInfo(Variant::INT, "glow_blend_mode", PROPERTY_HINT_ENUM, "Additive,Screen,Softlight,Replace,Mix"), "set_glow_blend_mode", "get_glow_blend_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "glow_blend_mode", PROPERTY_HINT_ENUM, "Additive,Screen,Soft Light,Replace,Mix"), "set_glow_blend_mode", "get_glow_blend_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_threshold", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_threshold", "get_glow_hdr_bleed_threshold");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_scale", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_scale", "get_glow_hdr_bleed_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_luminance_cap", PROPERTY_HINT_RANGE, "0.0,256.0,0.01"), "set_glow_hdr_luminance_cap", "get_glow_hdr_luminance_cap");
Expand Down Expand Up @@ -1572,11 +1572,11 @@ Environment::Environment() {
set_camera_feed_id(bg_camera_feed_id);

glow_levels.resize(7);
glow_levels.write[0] = 0.0;
glow_levels.write[1] = 0.0;
glow_levels.write[2] = 1.0;
glow_levels.write[3] = 0.0;
glow_levels.write[4] = 1.0;
glow_levels.write[0] = 1.0;
glow_levels.write[1] = 0.8;
glow_levels.write[2] = 0.4;
glow_levels.write[3] = 0.1;
glow_levels.write[4] = 0.0;
glow_levels.write[5] = 0.0;
glow_levels.write[6] = 0.0;

Expand Down
4 changes: 2 additions & 2 deletions scene/resources/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,11 @@ class Environment : public Resource {
bool glow_enabled = false;
Vector<float> glow_levels;
bool glow_normalize_levels = false;
float glow_intensity = 0.8;
float glow_intensity = 0.3;
float glow_strength = 1.0;
float glow_mix = 0.05;
float glow_bloom = 0.0;
GlowBlendMode glow_blend_mode = GLOW_BLEND_MODE_SOFTLIGHT;
GlowBlendMode glow_blend_mode = GLOW_BLEND_MODE_SCREEN;
float glow_hdr_bleed_threshold = 1.0;
float glow_hdr_bleed_scale = 2.0;
float glow_hdr_luminance_cap = 12.0;
Expand Down
6 changes: 3 additions & 3 deletions servers/rendering/renderer_rd/effects/tone_mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ class ToneMapper {
GLOW_MODE_MIX
};

GlowMode glow_mode = GLOW_MODE_ADD;
float glow_intensity = 1.0;
GlowMode glow_mode = GLOW_MODE_SCREEN;
float glow_intensity = 0.3;
float glow_map_strength = 0.0f;
float glow_levels[7] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0 };
float glow_levels[7] = { 1.0, 0.8, 0.4, 0.1, 0.0, 0.0, 0.0 };
Vector2i glow_texture_size;
bool glow_use_bicubic_upscale = false;
RID glow_texture;
Expand Down
Loading