Skip to content

Commit cafc012

Browse files
allenwpLielay9Calinou
committed
Blend Environment glow before tonemapping and change default blend mode to screen.
Additionally, change the minimum `tonemap_white` parameter to `1.0`; users can increase `tonemap_exposure` for a similar effect to decreasing `tonemap_white` below `1.0`. Co-authored-by: Hei <[email protected]> Co-authored-by: Hugo Locurcio <[email protected]>
1 parent 9a5d6d1 commit cafc012

File tree

11 files changed

+144
-74
lines changed

11 files changed

+144
-74
lines changed

doc/classes/Environment.xml

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
<description>
77
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:
88
- Depth of Field Blur
9+
- Auto Exposure
910
- Glow
10-
- Tonemap (Auto Exposure)
11+
- Tonemap
1112
- Adjustments
1213
</description>
1314
<tutorials>
@@ -124,15 +125,15 @@
124125
<member name="fog_sun_scatter" type="float" setter="set_fog_sun_scatter" getter="get_fog_sun_scatter" default="0.0">
125126
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.
126127
</member>
127-
<member name="glow_blend_mode" type="int" setter="set_glow_blend_mode" getter="get_glow_blend_mode" enum="Environment.GlowBlendMode" default="2">
128+
<member name="glow_blend_mode" type="int" setter="set_glow_blend_mode" getter="get_glow_blend_mode" enum="Environment.GlowBlendMode" default="1">
128129
The glow blending mode.
129-
[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.
130+
[b]Note:[/b] The Compatibility renderer always uses [constant GLOW_BLEND_MODE_SCREEN] and [member glow_blend_mode] will have no effect.
130131
</member>
131132
<member name="glow_bloom" type="float" setter="set_glow_bloom" getter="get_glow_bloom" default="0.0">
132133
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].
133134
</member>
134135
<member name="glow_enabled" type="bool" setter="set_glow_enabled" getter="is_glow_enabled" default="false">
135-
If [code]true[/code], the glow effect is enabled. This simulates real world eye/camera behavior where bright pixels bleed onto surrounding pixels.
136+
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.
136137
[b]Note:[/b] When using the Mobile rendering method, glow looks different due to the lower dynamic range available in the Mobile rendering method.
137138
[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.
138139
</member>
@@ -145,26 +146,26 @@
145146
<member name="glow_hdr_threshold" type="float" setter="set_glow_hdr_bleed_threshold" getter="get_glow_hdr_bleed_threshold" default="1.0">
146147
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.
147148
</member>
148-
<member name="glow_intensity" type="float" setter="set_glow_intensity" getter="get_glow_intensity" default="0.8">
149+
<member name="glow_intensity" type="float" setter="set_glow_intensity" getter="get_glow_intensity" default="0.3">
149150
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.
150151
</member>
151-
<member name="glow_levels/1" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
152+
<member name="glow_levels/1" type="float" setter="set_glow_level" getter="get_glow_level" default="1.0">
152153
The intensity of the 1st level of glow. This is the most "local" level (least blurry).
153154
[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.
154155
</member>
155-
<member name="glow_levels/2" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
156+
<member name="glow_levels/2" type="float" setter="set_glow_level" getter="get_glow_level" default="0.8">
156157
The intensity of the 2nd level of glow.
157158
[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.
158159
</member>
159-
<member name="glow_levels/3" type="float" setter="set_glow_level" getter="get_glow_level" default="1.0">
160+
<member name="glow_levels/3" type="float" setter="set_glow_level" getter="get_glow_level" default="0.4">
160161
The intensity of the 3rd level of glow.
161162
[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.
162163
</member>
163-
<member name="glow_levels/4" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
164+
<member name="glow_levels/4" type="float" setter="set_glow_level" getter="get_glow_level" default="0.1">
164165
The intensity of the 4th level of glow.
165166
[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.
166167
</member>
167-
<member name="glow_levels/5" type="float" setter="set_glow_level" getter="get_glow_level" default="1.0">
168+
<member name="glow_levels/5" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
168169
The intensity of the 5th level of glow.
169170
[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.
170171
</member>
@@ -434,19 +435,19 @@
434435
[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.
435436
</constant>
436437
<constant name="GLOW_BLEND_MODE_ADDITIVE" value="0" enum="GlowBlendMode">
437-
Additive glow blending mode. Mostly used for particles, glows (bloom), lens flare, bright sources.
438+
Adds the glow effect to the scene.
438439
</constant>
439440
<constant name="GLOW_BLEND_MODE_SCREEN" value="1" enum="GlowBlendMode">
440-
Screen glow blending mode. Increases brightness, used frequently with bloom.
441+
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.
441442
</constant>
442443
<constant name="GLOW_BLEND_MODE_SOFTLIGHT" value="2" enum="GlowBlendMode">
443-
Soft light glow blending mode. Modifies contrast, exposes shadows and highlights (vivid bloom).
444+
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].
444445
</constant>
445446
<constant name="GLOW_BLEND_MODE_REPLACE" value="3" enum="GlowBlendMode">
446-
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.
447+
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.
447448
</constant>
448449
<constant name="GLOW_BLEND_MODE_MIX" value="4" enum="GlowBlendMode">
449-
Mixes the glow with the underlying color to avoid increasing brightness as much while still maintaining a glow effect.
450+
Mixes the glow image with the scene image. Best used with [member glow_bloom] to avoid darkening the scene.
450451
</constant>
451452
<constant name="FOG_MODE_EXPONENTIAL" value="0" enum="FogMode">
452453
Use a physically-based fog model defined primarily by fog density.

drivers/gles3/effects/post_effects.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ void PostEffects::_draw_screen_triangle() {
8787
glBindVertexArray(0);
8888
}
8989

90-
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) {
90+
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) {
9191
glDisable(GL_DEPTH_TEST);
9292
glDepthMask(GL_FALSE);
9393
glDisable(GL_BLEND);
@@ -124,6 +124,7 @@ void PostEffects::post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuin
124124

125125
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);
126126
post.shader.version_set_uniform(PostShaderGLES3::GLOW_INTENSITY, p_glow_intensity, post.shader_version, mode, flags);
127+
post.shader.version_set_uniform(PostShaderGLES3::SRGB_WHITE, p_srgb_white, post.shader_version, mode, flags);
127128
}
128129

129130
post.shader.version_set_uniform(PostShaderGLES3::VIEW, float(p_view), post.shader_version, mode, flags);

drivers/gles3/effects/post_effects.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class PostEffects {
5858
PostEffects();
5959
~PostEffects();
6060

61-
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);
61+
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);
6262
};
6363

6464
} //namespace GLES3

drivers/gles3/rasterizer_scene_gles3.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2814,16 +2814,21 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
28142814
float glow_hdr_bleed_threshold = 1.0;
28152815
float glow_hdr_bleed_scale = 2.0;
28162816
float glow_hdr_luminance_cap = 12.0;
2817+
float srgb_white = 1.0;
28172818
if (p_render_data->environment.is_valid()) {
28182819
glow_enabled = environment_get_glow_enabled(p_render_data->environment);
28192820
glow_intensity = environment_get_glow_intensity(p_render_data->environment);
28202821
glow_bloom = environment_get_glow_bloom(p_render_data->environment);
28212822
glow_hdr_bleed_threshold = environment_get_glow_hdr_bleed_threshold(p_render_data->environment);
28222823
glow_hdr_bleed_scale = environment_get_glow_hdr_bleed_scale(p_render_data->environment);
28232824
glow_hdr_luminance_cap = environment_get_glow_hdr_luminance_cap(p_render_data->environment);
2825+
srgb_white = environment_get_white(p_render_data->environment);
28242826
}
28252827

28262828
if (glow_enabled) {
2829+
// Only glow requires srgb_white to be calculated.
2830+
srgb_white = 1.055 * Math::pow(srgb_white, 1.0f / 2.4f) - 0.055;
2831+
28272832
rb->check_glow_buffers();
28282833
}
28292834

@@ -2890,7 +2895,7 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
28902895
}
28912896

28922897
// Copy color buffer
2893-
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);
2898+
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);
28942899

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

29592964
glBindFramebuffer(GL_FRAMEBUFFER, fbos[2]);
29602965
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, write_color, 0, v);
2961-
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);
2966+
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);
29622967
}
29632968

29642969
// Copy depth

drivers/gles3/shaders/effects/post.glsl

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ uniform float luminance_multiplier;
4545
uniform sampler2D glow_color; // texunit:1
4646
uniform vec2 pixel_size;
4747
uniform float glow_intensity;
48+
uniform float srgb_white;
4849

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

62+
#ifdef USE_LUMINANCE_MULTIPLIER
63+
color = color / luminance_multiplier;
64+
#endif
65+
6166
return color / 12.0;
6267
}
6368
#endif // USE_GLOW
@@ -102,17 +107,37 @@ void main() {
102107
vec4 color = texture(source_color, uv_interp);
103108
#endif
104109

110+
#ifdef USE_LUMINANCE_MULTIPLIER
111+
color = color / luminance_multiplier;
112+
#endif
113+
105114
#ifdef USE_GLOW
115+
// Glow blending is performed before srgb_to_linear because
116+
// the glow texture was created from a nonlinear sRGB-encoded
117+
// scene, so it only makes sense to add this glow to an equally
118+
// nonlinear sRGB-encoded scene.
119+
106120
vec4 glow = get_glow_color(uv_interp) * glow_intensity;
107121

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

113-
#ifdef USE_LUMINANCE_MULTIPLIER
114-
color = color / luminance_multiplier;
115-
#endif
124+
// Glow cannot be above 1.0 after normalizing and should be non-negative
125+
// to produce expected results. It is possible that glow can be negative
126+
// if negative lights were used in the scene.
127+
// We clamp to srgb_white because glow will be normalized to this range.
128+
// Note: srgb_white cannot be smaller than the maximum output value (1.0).
129+
glow.rgb = clamp(glow.rgb, 0.0, srgb_white);
130+
131+
// Normalize to srgb_white range.
132+
//glow.rgb /= srgb_white;
133+
//color.rgb /= srgb_white;
134+
//color.rgb = (color.rgb + glow.rgb) - (color.rgb * glow.rgb);
135+
// Expand back to original range.
136+
//color.rgb *= srgb_white;
137+
138+
// The following is a mathematically simplified version of the above.
139+
color.rgb = color.rgb + glow.rgb - (color.rgb * glow.rgb / srgb_white);
140+
#endif // USE_GLOW
116141

117142
color.rgb = srgb_to_linear(color.rgb);
118143
color.rgb = apply_tonemapping(color.rgb, white);

scene/resources/environment.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,7 @@ void Environment::_bind_methods() {
12471247
ADD_GROUP("Tonemap", "tonemap_");
12481248
ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reinhard,Filmic,ACES,AgX"), "set_tonemapper", "get_tonemapper");
12491249
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_exposure", "get_tonemap_exposure");
1250-
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_white", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_white", "get_tonemap_white");
1250+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_white", PROPERTY_HINT_RANGE, "1,16,0.01,or_greater"), "set_tonemap_white", "get_tonemap_white");
12511251

12521252
// SSR
12531253

@@ -1405,7 +1405,7 @@ void Environment::_bind_methods() {
14051405
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_strength", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_glow_strength", "get_glow_strength");
14061406
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_mix", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_glow_mix", "get_glow_mix");
14071407
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_bloom", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_glow_bloom", "get_glow_bloom");
1408-
ADD_PROPERTY(PropertyInfo(Variant::INT, "glow_blend_mode", PROPERTY_HINT_ENUM, "Additive,Screen,Softlight,Replace,Mix"), "set_glow_blend_mode", "get_glow_blend_mode");
1408+
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");
14091409
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");
14101410
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");
14111411
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");
@@ -1572,11 +1572,11 @@ Environment::Environment() {
15721572
set_camera_feed_id(bg_camera_feed_id);
15731573

15741574
glow_levels.resize(7);
1575-
glow_levels.write[0] = 0.0;
1576-
glow_levels.write[1] = 0.0;
1577-
glow_levels.write[2] = 1.0;
1578-
glow_levels.write[3] = 0.0;
1579-
glow_levels.write[4] = 1.0;
1575+
glow_levels.write[0] = 1.0;
1576+
glow_levels.write[1] = 0.8;
1577+
glow_levels.write[2] = 0.4;
1578+
glow_levels.write[3] = 0.1;
1579+
glow_levels.write[4] = 0.0;
15801580
glow_levels.write[5] = 0.0;
15811581
glow_levels.write[6] = 0.0;
15821582

scene/resources/environment.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,11 @@ class Environment : public Resource {
163163
bool glow_enabled = false;
164164
Vector<float> glow_levels;
165165
bool glow_normalize_levels = false;
166-
float glow_intensity = 0.8;
166+
float glow_intensity = 0.3;
167167
float glow_strength = 1.0;
168168
float glow_mix = 0.05;
169169
float glow_bloom = 0.0;
170-
GlowBlendMode glow_blend_mode = GLOW_BLEND_MODE_SOFTLIGHT;
170+
GlowBlendMode glow_blend_mode = GLOW_BLEND_MODE_SCREEN;
171171
float glow_hdr_bleed_threshold = 1.0;
172172
float glow_hdr_bleed_scale = 2.0;
173173
float glow_hdr_luminance_cap = 12.0;

servers/rendering/renderer_rd/effects/tone_mapper.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,10 @@ class ToneMapper {
114114
GLOW_MODE_MIX
115115
};
116116

117-
GlowMode glow_mode = GLOW_MODE_ADD;
118-
float glow_intensity = 1.0;
117+
GlowMode glow_mode = GLOW_MODE_SCREEN;
118+
float glow_intensity = 0.3;
119119
float glow_map_strength = 0.0f;
120-
float glow_levels[7] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0 };
120+
float glow_levels[7] = { 1.0, 0.8, 0.4, 0.1, 0.0, 0.0, 0.0 };
121121
Vector2i glow_texture_size;
122122
bool glow_use_bicubic_upscale = false;
123123
RID glow_texture;

0 commit comments

Comments
 (0)