From 076908bed940adac80ab0a058e8a6d6b2583d84e Mon Sep 17 00:00:00 2001 From: clayjohn Date: Sun, 22 Nov 2020 17:51:31 -0800 Subject: [PATCH] Environment brightness, contrast, saturation restore with color correction. Allow gradients and 2d images. Use shader versions for LUT in tonemap Co-authored-by: alex-poe <3957610+CptPotato@users.noreply.github.com> Co-authored-by: QbieShay Co-authored-by: Clay John --- doc/classes/Environment.xml | 4 +-- doc/classes/RenderingServer.xml | 4 ++- drivers/dummy/rasterizer_dummy.h | 2 +- scene/resources/environment.cpp | 26 +++++++++++++---- scene/resources/environment.h | 7 +++-- servers/rendering/rasterizer.h | 2 +- .../rasterizer_rd/rasterizer_effects_rd.cpp | 9 ++++-- .../rasterizer_rd/rasterizer_effects_rd.h | 5 +++- .../rasterizer_rd/rasterizer_scene_rd.cpp | 29 +++++++++++++++++-- .../rasterizer_rd/rasterizer_scene_rd.h | 11 ++++++- .../rasterizer_rd/shaders/tonemap.glsl | 24 +++++++++++---- servers/rendering/rendering_server_raster.h | 2 +- servers/rendering/rendering_server_wrap_mt.h | 2 +- servers/rendering_server.cpp | 2 +- servers/rendering_server.h | 2 +- 15 files changed, 102 insertions(+), 29 deletions(-) diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index 104c149784..c5b6a54f71 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -43,8 +43,8 @@ The global brightness value of the rendered scene. Effective only if [code]adjustment_enabled[/code] is [code]true[/code]. - - Applies the provided [Texture2D] resource to affect the global color aspect of the rendered scene. Effective only if [code]adjustment_enabled[/code] is [code]true[/code]. + + The [Texture2D] or [Texture3D] lookup table (LUT) to use for the built-in post-process color grading. Can use a [GradientTexture] for a 1-dimensional LUT, or a [Texture3D] for a more complex LUT. Effective only if [code]adjustment_enabled[/code] is [code]true[/code]. The global contrast value of the rendered scene (default value is 1). Effective only if [code]adjustment_enabled[/code] is [code]true[/code]. diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 22a9925d4b..841567ee9f 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -608,7 +608,9 @@ - + + + Sets the values to be used with the "Adjustment" post-process effect. See [Environment] for more details. diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index fd9c26bdb9..faf1921ae9 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -96,7 +96,7 @@ public: void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {} - void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) override {} + void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {} void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {} void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) override {} diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index bacdb6be54..2ed5953b8f 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -31,6 +31,7 @@ #include "environment.h" #include "core/config/project_settings.h" +#include "core/core_string_names.h" #include "servers/rendering_server.h" #include "texture.h" @@ -891,23 +892,38 @@ float Environment::get_adjustment_saturation() const { return adjustment_saturation; } -void Environment::set_adjustment_color_correction(const Ref &p_ramp) { - adjustment_color_correction = p_ramp; +void Environment::set_adjustment_color_correction(Ref p_color_correction) { + adjustment_color_correction = p_color_correction; + Ref grad_tex = p_color_correction; + if (grad_tex.is_valid()) { + if (!grad_tex->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &Environment::_update_adjustment))) { + grad_tex->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Environment::_update_adjustment)); + } + } + Ref adjustment_texture_2d = adjustment_color_correction; + if (adjustment_texture_2d.is_valid()) { + use_1d_color_correction = true; + } else { + use_1d_color_correction = false; + } _update_adjustment(); } -Ref Environment::get_adjustment_color_correction() const { +Ref Environment::get_adjustment_color_correction() const { return adjustment_color_correction; } void Environment::_update_adjustment() { + RID color_correction = adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID(); + RS::get_singleton()->environment_set_adjustment( environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, - adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); + use_1d_color_correction, + color_correction); } // Private methods, constructor and destructor @@ -1319,7 +1335,7 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "adjustment_brightness", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_brightness", "get_adjustment_brightness"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "adjustment_contrast", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_contrast", "get_adjustment_contrast"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "adjustment_saturation", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_saturation", "get_adjustment_saturation"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "adjustment_color_correction", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_adjustment_color_correction", "get_adjustment_color_correction"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "adjustment_color_correction", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D,Texture3D"), "set_adjustment_color_correction", "get_adjustment_color_correction"); // Constants diff --git a/scene/resources/environment.h b/scene/resources/environment.h index 23c7f5180c..106ba92bfe 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -211,7 +211,8 @@ private: float adjustment_brightness = 1.0; float adjustment_contrast = 1.0; float adjustment_saturation = 1.0; - Ref adjustment_color_correction; + bool use_1d_color_correction = true; + Ref adjustment_color_correction; void _update_adjustment(); protected: @@ -402,8 +403,8 @@ public: float get_adjustment_contrast() const; void set_adjustment_saturation(float p_saturation); float get_adjustment_saturation() const; - void set_adjustment_color_correction(const Ref &p_ramp); - Ref get_adjustment_color_correction() const; + void set_adjustment_color_correction(Ref p_color_correction); + Ref get_adjustment_color_correction() const; Environment(); ~Environment(); diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h index 01c957e242..0629136792 100644 --- a/servers/rendering/rasterizer.h +++ b/servers/rendering/rasterizer.h @@ -109,7 +109,7 @@ public: virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; - virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0; + virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0; virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0; diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp index 97c1e7ba70..df94921652 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp @@ -94,7 +94,7 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); u.ids.push_back(p_texture); uniforms.push_back(u); - //any thing with the same configuration (one texture in binding 0 for set 0), is good + //anything with the same configuration (one texture in binding 0 for set 0), is good RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 0); texture_to_uniform_set_cache[p_texture] = uniform_set; @@ -718,7 +718,10 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, tonemap.push_constant.glow_texture_size[1] = p_settings.glow_texture_size.y; tonemap.push_constant.glow_mode = p_settings.glow_mode; - TonemapMode mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL; + int mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL; + if (p_settings.use_1d_color_correction) { + mode += 2; + } tonemap.push_constant.tonemapper = p_settings.tonemap_mode; tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure; @@ -1423,6 +1426,8 @@ RasterizerEffectsRD::RasterizerEffectsRD() { Vector tonemap_modes; tonemap_modes.push_back("\n"); tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n"); + tonemap_modes.push_back("\n#define USE_1D_LUT\n"); + tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n"); tonemap.shader.initialize(tonemap_modes); diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h index a0bdd59fd2..0b8d3a8f27 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h @@ -167,6 +167,8 @@ class RasterizerEffectsRD { enum TonemapMode { TONEMAP_MODE_NORMAL, TONEMAP_MODE_BICUBIC_GLOW_FILTER, + TONEMAP_MODE_1D_LUT, + TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT, TONEMAP_MODE_MAX }; @@ -198,7 +200,7 @@ class RasterizerEffectsRD { /* tonemap actually writes to a framebuffer, which is * better to do using the raster pipeline rather than - * comptute, as that framebuffer might be in different formats + * compute, as that framebuffer might be in different formats */ struct Tonemap { TonemapPushConstant push_constant; @@ -654,6 +656,7 @@ public: float saturation = 1.0; bool use_color_correction = false; + bool use_1d_color_correction = false; RID color_correction_texture; bool use_fxaa = false; diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp index 12fcc6fbb9..2ad13da631 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp @@ -5290,8 +5290,6 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu //tonemap RasterizerEffectsRD::TonemapSettings tonemap; - tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); - if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) { tonemap.use_auto_exposure = true; tonemap.exposure_texture = rb->luminance.current; @@ -5328,6 +5326,21 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu tonemap.exposure = env->exposure; } + if (can_use_effects && env) { + tonemap.use_bcs = env->adjustments_enabled; + tonemap.brightness = env->adjustments_brightness; + tonemap.contrast = env->adjustments_contrast; + tonemap.saturation = env->adjustments_saturation; + tonemap.use_1d_color_correction = env->use_1d_color_correction; + if (env->adjustments_enabled && env->color_correction.is_valid()) { + tonemap.use_color_correction = true; + tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction); + } else { + tonemap.use_color_correction = false; + tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + } + } + storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap); } @@ -5395,6 +5408,18 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s } } +void RasterizerSceneRD::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) { + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->adjustments_enabled = p_enable; + env->adjustments_brightness = p_brightness; + env->adjustments_contrast = p_contrast; + env->adjustments_saturation = p_saturation; + env->use_1d_color_correction = p_use_1d_color_correction; + env->color_correction = p_color_correction; +} + void RasterizerSceneRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h index 3d5310bb7e..6aa79208ea 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h @@ -763,6 +763,15 @@ private: float sdfgi_normal_bias = 1.1; float sdfgi_probe_bias = 1.1; RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_DISABLED; + + /// Adjustments + + bool adjustments_enabled = false; + float adjustments_brightness = 1.0f; + float adjustments_contrast = 1.0f; + float adjustments_saturation = 1.0f; + bool use_1d_color_correction = false; + RID color_correction = RID(); }; RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM; @@ -1571,7 +1580,7 @@ public: RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const; void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); - void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {} + void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction); virtual Ref environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size); diff --git a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl index 4cc4fd3f64..7de91fd541 100644 --- a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl +++ b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl @@ -23,7 +23,11 @@ layout(location = 0) in vec2 uv_interp; layout(set = 0, binding = 0) uniform sampler2D source_color; layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; layout(set = 2, binding = 0) uniform sampler2D source_glow; -layout(set = 3, binding = 0) uniform sampler3D color_correction; +#ifdef USE_1D_LUT +layout(set = 3, binding = 0) uniform sampler2D source_color_correction; +#else +layout(set = 3, binding = 0) uniform sampler3D source_color_correction; +#endif layout(push_constant, binding = 1, std430) uniform Params { vec3 bcs; @@ -35,9 +39,9 @@ layout(push_constant, binding = 1, std430) uniform Params { uint tonemapper; uvec2 glow_texture_size; - float glow_intensity; uint pad3; + uint glow_mode; float glow_levels[7]; @@ -255,10 +259,18 @@ vec3 apply_bcs(vec3 color, vec3 bcs) { return color; } - -vec3 apply_color_correction(vec3 color, sampler3D correction_tex) { - return texture(correction_tex, color).rgb; +#ifdef USE_1D_LUT +vec3 apply_color_correction(vec3 color) { + color.r = texture(source_color_correction, vec2(color.r, 0.0f)).r; + color.g = texture(source_color_correction, vec2(color.g, 0.0f)).g; + color.b = texture(source_color_correction, vec2(color.b, 0.0f)).b; + return color; } +#else +vec3 apply_color_correction(vec3 color) { + return textureLod(source_color_correction, color, 0.0).rgb; +} +#endif vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) { const float FXAA_REDUCE_MIN = (1.0 / 128.0); @@ -367,7 +379,7 @@ void main() { } if (params.use_color_correction) { - color = apply_color_correction(color, color_correction); + color = apply_color_correction(color); } frag_color = vec4(color, 1.0f); diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index 60b25f1b94..3c047939f6 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -592,7 +592,7 @@ public: BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) - BIND6(environment_set_adjustment, RID, bool, float, float, float, RID) + BIND7(environment_set_adjustment, RID, bool, float, float, float, bool, RID) BIND9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float) BIND9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, EnvVolumetricFogShadowFilter) diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index d27b851d1d..50d8d6f5e0 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -504,7 +504,7 @@ public: FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) - FUNC6(environment_set_adjustment, RID, bool, float, float, float, RID) + FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID) FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index bd501f8bc5..18cfc70d22 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1749,7 +1749,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "ambient", "energy", "sky_contibution", "reflection_source", "ao_color"), &RenderingServer::environment_set_ambient_light, DEFVAL(RS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(RS::ENV_REFLECTION_SOURCE_BG), DEFVAL(Color())); ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "levels", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap"), &RenderingServer::environment_set_glow); ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &RenderingServer::environment_set_tonemap); - ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "ramp"), &RenderingServer::environment_set_adjustment); + ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "use_1d_color_correction", "color_correction"), &RenderingServer::environment_set_adjustment); ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance"), &RenderingServer::environment_set_ssr); ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "bias", "light_affect", "ao_channel_affect", "blur", "bilateral_sharpness"), &RenderingServer::environment_set_ssao); ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective"), &RenderingServer::environment_set_fog); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index d676a1ba01..a757289ad7 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -872,7 +872,7 @@ public: }; virtual void environment_set_tonemap(RID p_env, EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_grey) = 0; - virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0; + virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0; virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance) = 0;