diff --git a/drivers/gles3/effects/copy_effects.cpp b/drivers/gles3/effects/copy_effects.cpp index ba8ad1c44d..9567d76b7a 100644 --- a/drivers/gles3/effects/copy_effects.cpp +++ b/drivers/gles3/effects/copy_effects.cpp @@ -192,6 +192,18 @@ void CopyEffects::copy_screen(float p_multiply) { draw_screen_triangle(); } +void CopyEffects::copy_with_exposure(float p_exposure, float p_multiply) { + bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_APPLY_LINEAR_EXPOSURE_TO_SRGB); + if (!success) { + return; + } + + copy.shader.version_set_uniform(CopyShaderGLES3::EXPOSURE, p_exposure, copy.shader_version, CopyShaderGLES3::MODE_APPLY_LINEAR_EXPOSURE_TO_SRGB); + copy.shader.version_set_uniform(CopyShaderGLES3::MULTIPLY, p_multiply, copy.shader_version, CopyShaderGLES3::MODE_APPLY_LINEAR_EXPOSURE_TO_SRGB); + + draw_screen_triangle(); +} + void CopyEffects::copy_cube_to_rect(const Rect2 &p_rect) { bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_CUBE_TO_OCTAHEDRAL); if (!success) { diff --git a/drivers/gles3/effects/copy_effects.h b/drivers/gles3/effects/copy_effects.h index b50ad9a3e1..5dbaeb4caa 100644 --- a/drivers/gles3/effects/copy_effects.h +++ b/drivers/gles3/effects/copy_effects.h @@ -65,6 +65,7 @@ public: void copy_with_lens_distortion(const Rect2 &p_rect, float p_layer, const Vector2 &p_eye_center, float p_k1, float p_k2, float p_upscale, float p_aspect_ration, bool p_linear_to_srgb = false); void copy_to_and_from_rect(const Rect2 &p_rect); void copy_screen(float p_multiply = 1.0); + void copy_with_exposure(float p_exposure, float p_multiply); void copy_cube_to_rect(const Rect2 &p_rect); void copy_cube_to_panorama(float p_mip_level); void bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 4a4407ef78..5c11b38e8c 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2455,6 +2455,7 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ bool draw_feed = false; float sky_energy_multiplier = 1.0; int camera_feed_id = -1; + bool apply_canvas_bg_exposure = false; if (unlikely(get_debug_draw_mode() == RSE::VIEWPORT_DEBUG_DRAW_OVERDRAW)) { clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black @@ -2494,6 +2495,7 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ } break; case RSE::ENV_BG_CANVAS: { draw_canvas = true; + apply_canvas_bg_exposure = !Math::is_equal_approx(tonemap_ubo.exposure, 1.0f); } break; case RSE::ENV_BG_KEEP: { keep_color = true; @@ -2573,6 +2575,7 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ fbo = GLES3::LightStorage::get_singleton()->reflection_probe_instance_get_framebuffer(render_data.reflection_probe, render_data.reflection_probe_pass); } else { rb->set_apply_environment_effects_in_post(apply_environment_effects_in_post); + rb->set_apply_canvas_bg_exposure(apply_canvas_bg_exposure); fbo = rb->get_render_fbo(); } @@ -2676,7 +2679,11 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ glActiveTexture(GL_TEXTURE0); glBindTexture(rt->view_count > 1 ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D, rt->color); - copy_effects->copy_screen(render_data.luminance_multiplier); + if (apply_canvas_bg_exposure) { + copy_effects->copy_with_exposure(tonemap_ubo.exposure, render_data.luminance_multiplier); + } else { + copy_effects->copy_screen(render_data.luminance_multiplier); + } scene_state.enable_gl_depth_test(true); scene_state.enable_gl_depth_draw(true); diff --git a/drivers/gles3/shaders/effects/copy.glsl b/drivers/gles3/shaders/effects/copy.glsl index 612a05e608..dc6253e780 100644 --- a/drivers/gles3/shaders/effects/copy.glsl +++ b/drivers/gles3/shaders/effects/copy.glsl @@ -13,6 +13,7 @@ mode_mipmap = #define MODE_MIPMAP mode_simple_color = #define MODE_SIMPLE_COLOR \n#define USE_COPY_SECTION mode_cube_to_octahedral = #define CUBE_TO_OCTAHEDRAL \n#define USE_COPY_SECTION mode_cube_to_panorama = #define CUBE_TO_PANORAMA +mode_apply_linear_exposure_to_srgb = #define MODE_SIMPLE_COPY \n#define MODE_MULTIPLY \n#define APPLY_LINEAR_EXPOSURE_TO_SRGB #[specializations] @@ -104,6 +105,10 @@ uniform float upscale; uniform float aspect_ratio; #endif // APPLY_LENS_DISTORTION +#ifdef APPLY_LINEAR_EXPOSURE_TO_SRGB +uniform float exposure; +#endif + layout(location = 0) out vec4 frag_color; // This approximation expects non-negative input; negative input behaves poorly. @@ -165,6 +170,12 @@ void main() { color.rgb = linear_to_srgb(color.rgb); #endif +#ifdef APPLY_LINEAR_EXPOSURE_TO_SRGB + color.rgb = srgb_to_linear(color.rgb); + color.rgb *= exposure; + color.rgb = linear_to_srgb(color.rgb); +#endif + #ifdef MODE_MULTIPLY color *= multiply; #endif // MODE_MULTIPLY diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.cpp b/drivers/gles3/storage/render_scene_buffers_gles3.cpp index 831bad7b86..910952c04e 100644 --- a/drivers/gles3/storage/render_scene_buffers_gles3.cpp +++ b/drivers/gles3/storage/render_scene_buffers_gles3.cpp @@ -189,7 +189,7 @@ void RenderSceneBuffersGLES3::_check_render_buffers() { ERR_FAIL_COND(view_count == 0); - bool use_internal_buffer = scaling_3d_mode != RSE::VIEWPORT_SCALING_3D_MODE_OFF || apply_environment_effects_in_post; + bool use_internal_buffer = scaling_3d_mode != RSE::VIEWPORT_SCALING_3D_MODE_OFF || apply_environment_effects_in_post || apply_canvas_bg_exposure; GLenum depth_format = GL_DEPTH24_STENCIL8; uint32_t depth_format_size = 4; bool use_multiview = view_count > 1; @@ -563,6 +563,10 @@ void RenderSceneBuffersGLES3::set_apply_environment_effects_in_post(bool p_apply apply_environment_effects_in_post = p_apply_in_post; } +void RenderSceneBuffersGLES3::set_apply_canvas_bg_exposure(bool p_apply_canvas_bg_exposure) { + apply_canvas_bg_exposure = p_apply_canvas_bg_exposure; +} + void RenderSceneBuffersGLES3::check_glow_buffers() { if (glow.levels[0].color != 0) { // already have these setup.. diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.h b/drivers/gles3/storage/render_scene_buffers_gles3.h index 65550752e4..4371fdae65 100644 --- a/drivers/gles3/storage/render_scene_buffers_gles3.h +++ b/drivers/gles3/storage/render_scene_buffers_gles3.h @@ -50,6 +50,7 @@ public: //bool use_debanding = false; uint32_t view_count = 1; bool apply_environment_effects_in_post = false; + bool apply_canvas_bg_exposure = false; RID render_target; @@ -107,6 +108,7 @@ public: virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override {} virtual void set_use_debanding(bool p_use_debanding) override {} void set_apply_environment_effects_in_post(bool p_apply_environment_effects_in_post); + void set_apply_canvas_bg_exposure(bool p_apply_canvas_bg_exposure); void free_render_buffer_data();