From b859e699190e45cbf1fda5c32838f1d59c9b1d8e Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Thu, 9 Jan 2020 21:40:26 -0300 Subject: -Refactored post processing, re-added glow and added a mix blend mode. --- scene/resources/environment.cpp | 47 +++- scene/resources/environment.h | 5 + servers/visual/rasterizer.h | 2 +- .../visual/rasterizer_rd/rasterizer_effects_rd.cpp | 62 ++++- .../visual/rasterizer_rd/rasterizer_effects_rd.h | 10 +- .../rasterizer_rd/rasterizer_scene_forward_rd.cpp | 238 +++--------------- .../rasterizer_rd/rasterizer_scene_forward_rd.h | 11 +- .../visual/rasterizer_rd/rasterizer_scene_rd.cpp | 280 +++++++++++++++++---- servers/visual/rasterizer_rd/rasterizer_scene_rd.h | 67 ++++- servers/visual/rasterizer_rd/shaders/SCsub | 3 +- servers/visual/rasterizer_rd/shaders/blur.glsl | 32 ++- .../rasterizer_rd/shaders/luminance_reduce.glsl | 76 ++++++ servers/visual/rasterizer_rd/shaders/tonemap.glsl | 24 +- servers/visual/visual_server_raster.h | 2 +- servers/visual/visual_server_wrap_mt.h | 2 +- servers/visual_server.h | 3 +- 16 files changed, 559 insertions(+), 305 deletions(-) create mode 100644 servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 4ee8962702..1cf291b867 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -312,6 +312,14 @@ void Environment::_validate_property(PropertyInfo &property) const { } } + if (property.name == "glow_intensity" && glow_blend_mode == GLOW_BLEND_MODE_MIX) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + + if (property.name == "glow_mix" && glow_blend_mode != GLOW_BLEND_MODE_MIX) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + if (property.name == "background_color") { if (bg_mode != BG_COLOR && ambient_source != AMBIENT_SOURCE_COLOR) { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; @@ -571,7 +579,7 @@ float Environment::get_ssao_edge_sharpness() const { void Environment::set_glow_enabled(bool p_enabled) { glow_enabled = p_enabled; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); _change_notify(); } @@ -589,7 +597,7 @@ void Environment::set_glow_level(int p_level, bool p_enabled) { else glow_levels &= ~(1 << p_level); - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } bool Environment::is_glow_level_enabled(int p_level) const { @@ -602,7 +610,7 @@ void Environment::set_glow_intensity(float p_intensity) { glow_intensity = p_intensity; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_intensity() const { @@ -612,18 +620,28 @@ float Environment::get_glow_intensity() const { void Environment::set_glow_strength(float p_strength) { glow_strength = p_strength; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_strength() const { return glow_strength; } +void Environment::set_glow_mix(float p_mix) { + + glow_mix = p_mix; + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); +} +float Environment::get_glow_mix() const { + + return glow_mix; +} + void Environment::set_glow_bloom(float p_threshold) { glow_bloom = p_threshold; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_bloom() const { @@ -634,7 +652,8 @@ void Environment::set_glow_blend_mode(GlowBlendMode p_mode) { glow_blend_mode = p_mode; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + _change_notify(); } Environment::GlowBlendMode Environment::get_glow_blend_mode() const { @@ -645,7 +664,7 @@ void Environment::set_glow_hdr_bleed_threshold(float p_threshold) { glow_hdr_bleed_threshold = p_threshold; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_hdr_bleed_threshold() const { @@ -656,7 +675,7 @@ void Environment::set_glow_hdr_luminance_cap(float p_amount) { glow_hdr_luminance_cap = p_amount; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_hdr_luminance_cap() const { @@ -667,7 +686,7 @@ void Environment::set_glow_hdr_bleed_scale(float p_scale) { glow_hdr_bleed_scale = p_scale; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_hdr_bleed_scale() const { @@ -677,7 +696,7 @@ float Environment::get_glow_hdr_bleed_scale() const { void Environment::set_glow_bicubic_upscale(bool p_enable) { glow_bicubic_upscale = p_enable; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } bool Environment::is_glow_bicubic_upscale_enabled() const { @@ -1224,6 +1243,9 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_glow_strength", "strength"), &Environment::set_glow_strength); ClassDB::bind_method(D_METHOD("get_glow_strength"), &Environment::get_glow_strength); + ClassDB::bind_method(D_METHOD("set_glow_mix", "mix"), &Environment::set_glow_mix); + ClassDB::bind_method(D_METHOD("get_glow_mix"), &Environment::get_glow_mix); + ClassDB::bind_method(D_METHOD("set_glow_bloom", "amount"), &Environment::set_glow_bloom); ClassDB::bind_method(D_METHOD("get_glow_bloom"), &Environment::get_glow_bloom); @@ -1253,9 +1275,10 @@ void Environment::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/7"), "set_glow_level", "is_glow_level_enabled", 6); ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_intensity", PROPERTY_HINT_RANGE, "0.0,8.0,0.01"), "set_glow_intensity", "get_glow_intensity"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_mix", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_glow_mix", "get_glow_mix"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_strength", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_glow_strength", "get_glow_strength"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "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"), "set_glow_blend_mode", "get_glow_blend_mode"); + 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::REAL, "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::REAL, "glow_hdr_luminance_cap", PROPERTY_HINT_RANGE, "0.0,256.0,0.01"), "set_glow_hdr_luminance_cap", "get_glow_hdr_luminance_cap"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_scale", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_scale", "get_glow_hdr_bleed_scale"); @@ -1304,6 +1327,7 @@ void Environment::_bind_methods() { BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SCREEN); BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SOFTLIGHT); BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_REPLACE); + BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_MIX); BIND_ENUM_CONSTANT(TONE_MAPPER_LINEAR); BIND_ENUM_CONSTANT(TONE_MAPPER_REINHARDT); @@ -1387,6 +1411,7 @@ Environment::Environment() : glow_levels = (1 << 2) | (1 << 4); glow_intensity = 0.8; glow_strength = 1.0; + glow_mix = 0.05; glow_bloom = 0.0; glow_blend_mode = GLOW_BLEND_MODE_SOFTLIGHT; glow_hdr_bleed_threshold = 1.0; diff --git a/scene/resources/environment.h b/scene/resources/environment.h index 69f18c3424..7926d5d284 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -77,6 +77,7 @@ public: GLOW_BLEND_MODE_SCREEN, GLOW_BLEND_MODE_SOFTLIGHT, GLOW_BLEND_MODE_REPLACE, + GLOW_BLEND_MODE_MIX, }; enum DOFBlurQuality { @@ -154,6 +155,7 @@ private: int glow_levels; float glow_intensity; float glow_strength; + float glow_mix; float glow_bloom; GlowBlendMode glow_blend_mode; float glow_hdr_bleed_threshold; @@ -333,6 +335,9 @@ public: void set_glow_strength(float p_strength); float get_glow_strength() const; + void set_glow_mix(float p_mix); + float get_glow_mix() const; + void set_glow_bloom(float p_threshold); float get_glow_bloom() const; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 23e890e64d..ad515c06b8 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -77,7 +77,7 @@ public: virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) = 0; virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) = 0; - virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0; + virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0; virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0; virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0; diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp index 1763621cc0..65b82da97a 100644 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp @@ -45,7 +45,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar p_array[11] = 0; } -RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture) { +RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { if (texture_to_uniform_set_cache.has(p_texture)) { RID uniform_set = texture_to_uniform_set_cache[p_texture]; @@ -58,7 +58,7 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture) { RD::Uniform u; u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(default_sampler); + 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 @@ -147,6 +147,55 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuff RD::get_singleton()->draw_list_end(); } +void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure) { + + zeromem(&blur.push_constant, sizeof(BlurPushConstant)); + + BlurMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW; + uint32_t base_flags = 0; + + blur.push_constant.pixel_size[0] = p_pixel_size.x; + blur.push_constant.pixel_size[1] = p_pixel_size.y; + + blur.push_constant.glow_strength = p_strength; + blur.push_constant.glow_bloom = p_bloom; + blur.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold; + blur.push_constant.glow_hdr_scale = p_hdr_bleed_scale; + blur.push_constant.glow_exposure = p_exposure; + blur.push_constant.glow_white = 0; //actually unused + blur.push_constant.glow_luminance_cap = p_luminance_cap; + blur.push_constant.glow_auto_exposure_grey = 0; //unused also + + //HORIZONTAL + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); + if (p_auto_exposure.is_valid() && p_first_pass) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1); + } + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + + blur.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + blur_mode = BLUR_MODE_GAUSSIAN_GLOW; + + //VERTICAL + draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + + blur.push_constant.flags = base_flags; + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness) { zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); @@ -241,6 +290,7 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, tonemap.push_constant.glow_level_flags = p_settings.glow_level_flags; tonemap.push_constant.glow_texture_size[0] = p_settings.glow_texture_size.x; 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; @@ -256,7 +306,7 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.glow_texture), 2); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3); RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); @@ -361,6 +411,12 @@ RasterizerEffectsRD::RasterizerEffectsRD() { default_sampler = RD::get_singleton()->sampler_create(sampler); + sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler.mip_filter = RD::SAMPLER_FILTER_LINEAR; + sampler.max_lod = 1e20; + + default_mipmap_sampler = RD::get_singleton()->sampler_create(sampler); + { //create index array for copy shaders PoolVector pv; pv.resize(6 * 4); diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h index 8245f3a67e..74d18683a5 100644 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h @@ -198,17 +198,22 @@ class RasterizerEffectsRD { } copy; RID default_sampler; + RID default_mipmap_sampler; RID index_buffer; RID index_array; Map texture_to_uniform_set_cache; - RID _get_uniform_set_from_texture(RID p_texture); + RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); public: + //TODO must re-do most of the shaders in compute + void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region); void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false); void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region); + void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID()); + void cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness); void render_panorama(RD::DrawListID p_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_panorama, const CameraMatrix &p_camera, const Basis &p_orientation, float p_alpha, float p_multipler); void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size); @@ -221,7 +226,8 @@ public: GLOW_MODE_ADD, GLOW_MODE_SCREEN, GLOW_MODE_SOFTLIGHT, - GLOW_MODE_REPLACE + GLOW_MODE_REPLACE, + GLOW_MODE_MIX }; GlowMode glow_mode = GLOW_MODE_ADD; diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp index 1a426e3df1..0159146bfc 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp @@ -536,34 +536,20 @@ void RasterizerSceneForwardRD::RenderBufferDataForward::clear() { color_fb = RID(); } - if (color.is_valid()) { - RD::get_singleton()->free(color); - color = RID(); - } - if (depth.is_valid()) { RD::get_singleton()->free(depth); depth = RID(); } } -void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) { +void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_color_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) { clear(); width = p_width; height = p_height; - render_target = p_render_target; + color = p_color_buffer; - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = p_width; - tf.height = p_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - - color = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } { RD::TextureFormat tf; tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; @@ -576,7 +562,7 @@ void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_render_t { Vector fb; - fb.push_back(color); + fb.push_back(p_color_buffer); fb.push_back(depth); color_fb = RD::get_singleton()->framebuffer_create(fb); @@ -589,7 +575,7 @@ void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_render_t } { Vector fb; - fb.push_back(color); + fb.push_back(p_color_buffer); color_only_fb = RD::get_singleton()->framebuffer_create(fb); } @@ -951,7 +937,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l } } -void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y) { +void RasterizerSceneForwardRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color) { //CameraMatrix projection = p_cam_projection; //projection.flip_y(); // Vulkan and modern APIs use Y-Down @@ -981,7 +967,7 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env //time global variables scene_state.ubo.time = time; - if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) { + if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) { scene_state.ubo.use_ambient_light = true; scene_state.ubo.ambient_light_color_energy[0] = 1; @@ -1004,7 +990,7 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env //ambient if (ambient_src == VS::ENV_AMBIENT_SOURCE_BG && (env_bg == VS::ENV_BG_CLEAR_COLOR || env_bg == VS::ENV_BG_COLOR)) { - Color color = (p_render_target.is_valid() && env_bg == VS::ENV_BG_CLEAR_COLOR) ? (p_render_target.is_valid() ? storage->render_target_get_clear_request_color(p_render_target) : Color(0, 0, 0)) : environment_get_bg_color(p_environment); + Color color = env_bg == VS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_environment); color = color.to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy; @@ -1039,138 +1025,21 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env } else { - if (p_reflection_probe.is_valid() && !storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { - scene_state.ubo.use_ambient_light = true; - Color clear_color = storage->get_default_clear_color(); - clear_color = clear_color.to_linear(); - scene_state.ubo.ambient_light_color_energy[0] = clear_color.r; - scene_state.ubo.ambient_light_color_energy[1] = clear_color.g; - scene_state.ubo.ambient_light_color_energy[2] = clear_color.b; - scene_state.ubo.ambient_light_color_energy[3] = 1.0; - - } else if (p_render_target.is_valid()) { + if (p_reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { + scene_state.ubo.use_ambient_light = false; + } else { scene_state.ubo.use_ambient_light = true; - Color clear_color = storage->render_target_get_clear_request_color(p_render_target); + Color clear_color = p_default_bg_color; clear_color = clear_color.to_linear(); scene_state.ubo.ambient_light_color_energy[0] = clear_color.r; scene_state.ubo.ambient_light_color_energy[1] = clear_color.g; scene_state.ubo.ambient_light_color_energy[2] = clear_color.b; scene_state.ubo.ambient_light_color_energy[3] = 1.0; - } else { - scene_state.ubo.use_ambient_light = false; } scene_state.ubo.use_ambient_cubemap = false; scene_state.ubo.use_reflection_cubemap = false; } -#if 0 - //bg and ambient - if (p_environment.is_valid()) { - - state.ubo_data.bg_energy = env->bg_energy; - state.ubo_data.ambient_energy = env->ambient_energy; - Color linear_ambient_color = env->ambient_color.to_linear(); - state.ubo_data.ambient_light_color[0] = linear_ambient_color.r; - state.ubo_data.ambient_light_color[1] = linear_ambient_color.g; - state.ubo_data.ambient_light_color[2] = linear_ambient_color.b; - state.ubo_data.ambient_light_color[3] = linear_ambient_color.a; - - Color bg_color; - - switch (env->bg_mode) { - case VS::ENV_BG_CLEAR_COLOR: { - bg_color = storage->frame.clear_request_color.to_linear(); - } break; - case VS::ENV_BG_COLOR: { - bg_color = env->bg_color.to_linear(); - } break; - default: { - bg_color = Color(0, 0, 0, 1); - } break; - } - - state.ubo_data.bg_color[0] = bg_color.r; - state.ubo_data.bg_color[1] = bg_color.g; - state.ubo_data.bg_color[2] = bg_color.b; - state.ubo_data.bg_color[3] = bg_color.a; - - //use the inverse of our sky_orientation, we may need to skip this if we're using a reflection probe? - sky_orientation = Transform(env->sky_orientation, Vector3(0.0, 0.0, 0.0)).affine_inverse(); - - state.env_radiance_data.ambient_contribution = env->ambient_sky_contribution; - state.ubo_data.ambient_occlusion_affect_light = env->ssao_light_affect; - state.ubo_data.ambient_occlusion_affect_ssao = env->ssao_ao_channel_affect; - - //fog - - Color linear_fog = env->fog_color.to_linear(); - state.ubo_data.fog_color_enabled[0] = linear_fog.r; - state.ubo_data.fog_color_enabled[1] = linear_fog.g; - state.ubo_data.fog_color_enabled[2] = linear_fog.b; - state.ubo_data.fog_color_enabled[3] = (!p_no_fog && env->fog_enabled) ? 1.0 : 0.0; - state.ubo_data.fog_density = linear_fog.a; - - Color linear_sun = env->fog_sun_color.to_linear(); - state.ubo_data.fog_sun_color_amount[0] = linear_sun.r; - state.ubo_data.fog_sun_color_amount[1] = linear_sun.g; - state.ubo_data.fog_sun_color_amount[2] = linear_sun.b; - state.ubo_data.fog_sun_color_amount[3] = env->fog_sun_amount; - state.ubo_data.fog_depth_enabled = env->fog_depth_enabled; - state.ubo_data.fog_depth_begin = env->fog_depth_begin; - state.ubo_data.fog_depth_end = env->fog_depth_end; - state.ubo_data.fog_depth_curve = env->fog_depth_curve; - state.ubo_data.fog_transmit_enabled = env->fog_transmit_enabled; - state.ubo_data.fog_transmit_curve = env->fog_transmit_curve; - state.ubo_data.fog_height_enabled = env->fog_height_enabled; - state.ubo_data.fog_height_min = env->fog_height_min; - state.ubo_data.fog_height_max = env->fog_height_max; - state.ubo_data.fog_height_curve = env->fog_height_curve; - - } else { - state.ubo_data.bg_energy = 1.0; - state.ubo_data.ambient_energy = 1.0; - //use from clear color instead, since there is no ambient - Color linear_ambient_color = storage->frame.clear_request_color.to_linear(); - state.ubo_data.ambient_light_color[0] = linear_ambient_color.r; - state.ubo_data.ambient_light_color[1] = linear_ambient_color.g; - state.ubo_data.ambient_light_color[2] = linear_ambient_color.b; - state.ubo_data.ambient_light_color[3] = linear_ambient_color.a; - - state.ubo_data.bg_color[0] = linear_ambient_color.r; - state.ubo_data.bg_color[1] = linear_ambient_color.g; - state.ubo_data.bg_color[2] = linear_ambient_color.b; - state.ubo_data.bg_color[3] = linear_ambient_color.a; - - state.env_radiance_data.ambient_contribution = 0; - state.ubo_data.ambient_occlusion_affect_light = 0; - - state.ubo_data.fog_color_enabled[3] = 0.0; - } - - { - //directional shadow - - state.ubo_data.shadow_directional_pixel_size[0] = 1.0 / directional_shadow.size; - state.ubo_data.shadow_directional_pixel_size[1] = 1.0 / directional_shadow.size; - - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); - glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); - } - - glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(State::SceneDataUBO), &state.ubo_data); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - //fill up environment - - store_transform(sky_orientation * p_cam_transform, state.env_radiance_data.transform); - - glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_data); - glBindBuffer(GL_UNIFORM_BUFFER, 0); -#endif RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true); } @@ -1181,12 +1050,12 @@ void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material; - if (unlikely(debug_draw != VS::VIEWPORT_DEBUG_DRAW_DISABLED)) { - if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { + if (unlikely(get_debug_draw_mode() != VS::VIEWPORT_DEBUG_DRAW_DISABLED)) { + if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { m_src = overdraw_material; - } else if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME) { + } else if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME) { m_src = wireframe_material; - } else if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_LIGHTING) { + } else if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_LIGHTING) { m_src = default_material; } } @@ -1756,9 +1625,12 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig } } -void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { +void RasterizerSceneForwardRD::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) { - RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)p_buffer_data; + RenderBufferDataForward *render_buffer = NULL; + if (p_render_buffer.is_valid()) { + render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer); + } //first of all, make a new render pass render_pass++; @@ -1788,7 +1660,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co RENDER_TIMESTAMP("Setup 3D Scene"); - if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) { + if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) { p_light_cull_count = 0; p_reflection_probe_cull_count = 0; p_gi_probe_cull_count = 0; @@ -1816,7 +1688,6 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co scene_state.ubo.viewport_size[0] = vp_he.x; scene_state.ubo.viewport_size[1] = vp_he.y; - RID render_target; Size2 screen_pixel_size; RID opaque_framebuffer; RID depth_framebuffer; @@ -1825,7 +1696,6 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co if (render_buffer) { screen_pixel_size.width = 1.0 / render_buffer->width; screen_pixel_size.height = 1.0 / render_buffer->height; - render_target = render_buffer->render_target; opaque_framebuffer = render_buffer->color_fb; depth_framebuffer = render_buffer->depth_fb; @@ -1851,7 +1721,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows); _setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment); _setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform); - _setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid()); + _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color); render_list.clear(); _fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr); @@ -1862,14 +1732,14 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co Color clear_color; bool keep_color = false; - if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { + if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black } else if (is_environment(p_environment)) { VS::EnvironmentBG bg_mode = environment_get_background(p_environment); float bg_energy = environment_get_bg_energy(p_environment); switch (bg_mode) { case VS::ENV_BG_CLEAR_COLOR: { - clear_color = render_target.is_valid() ? storage->render_target_get_clear_request_color(render_target) : environment_get_bg_color(p_environment); + clear_color = p_default_bg_color; clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; @@ -1896,14 +1766,12 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co case VS::ENV_BG_CAMERA_FEED: { } break; + default: { + } } } else { - if (p_reflection_probe.is_valid() && !storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { - clear_color = storage->get_default_clear_color(); - } else if (render_target.is_valid()) { - clear_color = storage->render_target_get_clear_request_color(render_target); - } + clear_color = p_default_bg_color; } _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap, p_shadow_atlas, p_reflection_atlas); @@ -1913,7 +1781,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co _fill_instances(render_list.elements, render_list.element_count, false); bool can_continue = true; //unless the middle buffers are needed - bool debug_giprobes = debug_draw == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || debug_draw == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || debug_draw == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION; + bool debug_giprobes = get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION; bool using_separate_specular = false; bool depth_pre_pass = depth_framebuffer.is_valid(); @@ -1944,7 +1812,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse()); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); for (int i = 0; i < p_gi_probe_cull_count; i++) { - _debug_giprobe(p_gi_probe_cull_result[i], draw_list, opaque_framebuffer, cm, debug_draw == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, debug_draw == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0); + _debug_giprobe(p_gi_probe_cull_result[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0); } RD::get_singleton()->draw_list_end(); } @@ -1992,44 +1860,10 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co return; } - RasterizerEffectsRD *effects = storage->get_effects(); + RENDER_TIMESTAMP("Tonemap"); - { - RENDER_TIMESTAMP("Tonemap"); - //tonemap - RasterizerEffectsRD::TonemapSettings tonemap; - - tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); - tonemap.exposure_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); - tonemap.glow_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); - - if (is_environment(p_environment)) { - tonemap.tonemap_mode = environment_get_tonemapper(p_environment); - tonemap.white = environment_get_white(p_environment); - tonemap.exposure = environment_get_exposure(p_environment); - } - effects->tonemapper(render_buffer->color, storage->render_target_get_rd_framebuffer(render_buffer->render_target), tonemap); - } - - storage->render_target_disable_clear_request(render_buffer->render_target); - - if (render_buffer && debug_draw == VS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) { - if (p_shadow_atlas.is_valid()) { - RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); - Size2 rtsize = storage->render_target_get_size(render_buffer->render_target); - - effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(render_buffer->render_target), Rect2(Vector2(), rtsize / 2)); - } - } - - if (render_buffer && debug_draw == VS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) { - if (directional_shadow_get_texture().is_valid()) { - RID shadow_atlas_texture = directional_shadow_get_texture(); - Size2 rtsize = storage->render_target_get_size(render_buffer->render_target); - - effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(render_buffer->render_target), Rect2(Vector2(), rtsize / 2)); - } - } + render_buffers_post_process_and_tonemap(p_render_buffer, p_environment); + render_buffers_debug_draw(p_render_buffer, p_shadow_atlas); #if 0 _post_process(env, p_cam_projection); @@ -2101,7 +1935,7 @@ void RasterizerSceneForwardRD::_render_shadow(RID p_framebuffer, InstanceBase ** scene_state.ubo.z_far = p_zfar; scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; - _setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true); + _setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color()); render_list.clear(); @@ -2137,7 +1971,7 @@ void RasterizerSceneForwardRD::_render_material(const Transform &p_cam_transform scene_state.ubo.z_far = 0; scene_state.ubo.dual_paraboloid_side = 0; - _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false); + _setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color()); render_list.clear(); @@ -2395,10 +2229,6 @@ void RasterizerSceneForwardRD::set_time(double p_time) { time = p_time; } -void RasterizerSceneForwardRD::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) { - debug_draw = p_debug_draw; -} - RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storage) : RasterizerSceneRD(p_storage) { singleton = this; diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h index 676db253e9..0494a8f1b4 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h @@ -194,10 +194,8 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { RID color_only_fb; int width, height; - RID render_target; - void clear(); - virtual void configure(RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa); + virtual void configure(RID p_color_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa); ~RenderBufferDataForward(); }; @@ -525,7 +523,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { PASS_MODE_DEPTH_MATERIAL, }; - void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y); + void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color); void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows); void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment); void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform); @@ -539,16 +537,13 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { void _draw_sky(RD::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha); - VS::ViewportDebugDraw debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED; - protected: - virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); + virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color); virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip); virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); public: virtual void set_time(double p_time); - virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw); virtual bool free(RID p_rid); diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp index 77ab4624b1..0b24cb2888 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp @@ -468,46 +468,21 @@ void RasterizerSceneRD::environment_set_tonemap(RID p_env, VS::EnvironmentToneMa env->auto_exp_scale = p_auto_exp_scale; } -VS::EnvironmentToneMapper RasterizerSceneRD::environment_get_tonemapper(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, VS::ENV_TONE_MAPPER_LINEAR); - return env->tone_mapper; -} -float RasterizerSceneRD::environment_get_exposure(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->exposure; -} -float RasterizerSceneRD::environment_get_white(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->white; -} -bool RasterizerSceneRD::environment_get_auto_exposure(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, false); - return env->auto_exposure; -} -float RasterizerSceneRD::environment_get_min_luminance(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->min_luminance; -} -float RasterizerSceneRD::environment_get_max_luminance(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->max_luminance; -} -float RasterizerSceneRD::environment_get_auto_exposure_scale(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->auto_exp_scale; -} +void RasterizerSceneRD::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) { -float RasterizerSceneRD::environment_get_auto_exposure_speed(RID p_env) const { Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->auto_exp_speed; + ERR_FAIL_COND(!env); + env->glow_enabled = p_enable; + env->glow_levels = p_level_flags; + env->glow_intensity = p_intensity; + env->glow_strength = p_strength; + env->glow_mix = p_mix; + env->glow_bloom = p_bloom_threshold; + env->glow_blend_mode = p_blend_mode; + env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold; + env->glow_hdr_bleed_scale = p_hdr_bleed_scale; + env->glow_hdr_luminance_cap = p_hdr_luminance_cap; + env->glow_bicubic_upscale = p_bicubic_upscale; } bool RasterizerSceneRD::is_environment(RID p_env) const { @@ -2181,6 +2156,198 @@ RID RasterizerSceneRD::render_buffers_create() { return render_buffers_owner.make_rid(rb); } +void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) { + ERR_FAIL_COND(!rb->blur[0].texture.is_null()); + + uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH); + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = rb->width; + tf.height = rb->height; + tf.type = RD::TEXTURE_TYPE_2D; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + tf.mipmaps = mipmaps_required; + + rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + //the second one is smaller (only used for separatable part of blur) + tf.width >>= 1; + tf.height >>= 1; + tf.mipmaps--; + rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + int base_width = rb->width; + int base_height = rb->height; + + for (uint32_t i = 0; i < mipmaps_required; i++) { + + RenderBuffers::Blur::Mipmap mm; + mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, 0, i); + { + Vector fbs; + fbs.push_back(mm.texture); + mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs); + } + + mm.width = base_width; + mm.height = base_height; + + rb->blur[0].mipmaps.push_back(mm); + + if (i > 0) { + + mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1); + { + Vector fbs; + fbs.push_back(mm.texture); + mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs); + } + + rb->blur[1].mipmaps.push_back(mm); + } + + base_width = MAX(1, base_width >> 1); + base_height = MAX(1, base_height >> 1); + } +} + +void RasterizerSceneRD::_free_render_buffer_data(RenderBuffers *rb) { + + if (rb->texture.is_valid()) { + RD::get_singleton()->free(rb->texture); + } + + for (int i = 0; i < 2; i++) { + if (rb->blur[i].texture.is_valid()) { + RD::get_singleton()->free(rb->blur[i].texture); + rb->blur[i].texture = RID(); + rb->blur[i].mipmaps.clear(); + } + } + + for (int i = 0; i < rb->luminance.reduce.size(); i++) { + RD::get_singleton()->free(rb->luminance.reduce[i]); + } + + rb->luminance.reduce.clear(); + + if (rb->luminance.current.is_valid()) { + RD::get_singleton()->free(rb->luminance.current); + rb->luminance.current = RID(); + } +} + +void RasterizerSceneRD::render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment) { + + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + + Environent *env = environment_owner.getornull(p_environment); + //glow (if enabled) + + int max_glow_level = -1; + int glow_mask = 0; + + if (env && env->glow_enabled) { + + /* see that blur textures are allocated */ + + if (rb->blur[0].texture.is_null()) { + _allocate_blur_textures(rb); + } + + for (int i = 0; i < VS::MAX_GLOW_LEVELS; i++) { + if (env->glow_levels & (1 << i)) { + + if (i >= rb->blur[1].mipmaps.size()) { + max_glow_level = rb->blur[1].mipmaps.size() - 1; + glow_mask |= 1 << max_glow_level; + + } else { + max_glow_level = i; + glow_mask |= (1 << i); + } + } + } + + for (int i = 0; i < (max_glow_level + 1); i++) { + + int vp_w = rb->blur[1].mipmaps[i].width; + int vp_h = rb->blur[1].mipmaps[i].height; + + if (i == 0) { + storage->get_effects()->gaussian_glow(rb->texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, RID()); + } else { + storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength); + } + } + } + + { + //tonemap + RasterizerEffectsRD::TonemapSettings tonemap; + + tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + tonemap.exposure_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + + if (env && env->glow_enabled) { + tonemap.use_glow = true; + tonemap.glow_mode = RasterizerEffectsRD::TonemapSettings::GlowMode(env->glow_blend_mode); + tonemap.glow_intensity = env->glow_blend_mode == VS::GLOW_BLEND_MODE_MIX ? env->glow_mix : env->glow_intensity; + tonemap.glow_level_flags = glow_mask; + tonemap.glow_texture_size.x = rb->blur[1].mipmaps[0].width; + tonemap.glow_texture_size.y = rb->blur[1].mipmaps[0].height; + tonemap.glow_use_bicubic_upscale = env->glow_bicubic_upscale; + tonemap.glow_texture = rb->blur[1].texture; + } else { + tonemap.glow_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + } + + if (env) { + tonemap.tonemap_mode = env->tone_mapper; + tonemap.white = env->white; + tonemap.exposure = env->exposure; + } + + storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap); + } + + storage->render_target_disable_clear_request(rb->render_target); +} + +void RasterizerSceneRD::render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas) { + RasterizerEffectsRD *effects = storage->get_effects(); + + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + + if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) { + if (p_shadow_atlas.is_valid()) { + RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); + Size2 rtsize = storage->render_target_get_size(rb->render_target); + + effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2)); + } + } + + if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) { + if (directional_shadow_get_texture().is_valid()) { + RID shadow_atlas_texture = directional_shadow_get_texture(); + Size2 rtsize = storage->render_target_get_size(rb->render_target); + + effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2)); + } + } +} + +RID RasterizerSceneRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) { + + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, RID()); + ERR_FAIL_COND_V(!rb->blur[0].texture.is_valid(), RID()); //should have been created for some reason? + return rb->blur[0].texture; +} + void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); @@ -2188,7 +2355,19 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren rb->height = p_height; rb->render_target = p_render_target; rb->msaa = p_msaa; - rb->data->configure(p_render_target, p_width, p_height, p_msaa); + _free_render_buffer_data(rb); + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = rb->width; + tf.height = rb->height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + + rb->data->configure(rb->texture, p_width, p_height, p_msaa); } int RasterizerSceneRD::get_roughness_layers() const { @@ -2199,12 +2378,24 @@ bool RasterizerSceneRD::is_using_radiance_cubemap_array() const { return sky_use_cubemap_array; } +RasterizerSceneRD::RenderBufferData *RasterizerSceneRD::render_buffers_get_data(RID p_render_buffers) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, NULL); + return rb->data; +} + void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { - RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); - ERR_FAIL_COND(!rb && p_render_buffers.is_valid()); + Color clear_color; + if (p_render_buffers.is_valid()) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + clear_color = storage->render_target_get_clear_request_color(rb->render_target); + } else { + clear_color = storage->get_default_clear_color(); + } - _render_scene(rb ? rb->data : (RenderBufferData *)NULL, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_environment, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass); + _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_environment, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color); } void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) { @@ -2392,6 +2583,7 @@ bool RasterizerSceneRD::free(RID p_rid) { if (render_buffers_owner.owns(p_rid)) { RenderBuffers *rb = render_buffers_owner.getornull(p_rid); + _free_render_buffer_data(rb); memdelete(rb->data); render_buffers_owner.free(p_rid); } else if (environment_owner.owns(p_rid)) { @@ -2463,6 +2655,10 @@ bool RasterizerSceneRD::free(RID p_rid) { return true; } +void RasterizerSceneRD::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) { + debug_draw = p_debug_draw; +} + void RasterizerSceneRD::update() { _update_dirty_skys(); } diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h index 91e53b66cc..3be67d8a92 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h @@ -49,18 +49,22 @@ public: protected: struct RenderBufferData { - virtual void configure(RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) = 0; + virtual void configure(RID p_color_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) = 0; virtual ~RenderBufferData() {} }; virtual RenderBufferData *_create_render_buffer_data() = 0; - virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0; + virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0; virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip) = 0; virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); + RenderBufferData *render_buffers_get_data(RID p_render_buffers); + private: + VS::ViewportDebugDraw debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED; + int roughness_layers; RasterizerStorageRD *storage; @@ -461,6 +465,20 @@ private: float max_luminance = 8.0; float auto_exp_speed = 0.2; float auto_exp_scale = 0.5; + + /// Glow + + bool glow_enabled = false; + int glow_levels = (1 << 2) | (1 << 4); + float glow_intensity = 0.8; + float glow_strength = 1.0; + float glow_bloom = 0.0; + float glow_mix = 0.01; + VS::EnvironmentGlowBlendMode glow_blend_mode = VS::GLOW_BLEND_MODE_SOFTLIGHT; + float glow_hdr_bleed_threshold = 1.0; + float glow_hdr_luminance_cap = 12.0; + float glow_hdr_bleed_scale = 2.0; + bool glow_bicubic_upscale = false; }; mutable RID_Owner environment_owner; @@ -473,10 +491,37 @@ private: int width = 0, height = 0; VS::ViewportMSAA msaa = VS::VIEWPORT_MSAA_DISABLED; RID render_target; + + RID texture; //main texture for rendering to, must be filled after done rendering + + //built-in textures used for ping pong image processing and blurring + struct Blur { + RID texture; + + struct Mipmap { + RID texture; + RID framebuffer; + int width; + int height; + }; + + Vector mipmaps; + }; + + Blur blur[2]; //the second one starts from the first mipmap + + struct Luminance { + + Vector reduce; + RID current; + } luminance; }; mutable RID_Owner render_buffers_owner; + void _free_render_buffer_data(RenderBuffers *rb); + void _allocate_blur_textures(RenderBuffers *rb); + uint64_t scene_pass = 0; uint64_t shadow_atlas_realloc_tolerance_msec = 500; @@ -557,7 +602,7 @@ public: void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {} void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {} - void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) {} + void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale); void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {} @@ -565,15 +610,6 @@ public: void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {} void environment_set_tonemap(RID p_env, VS::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); - VS::EnvironmentToneMapper environment_get_tonemapper(RID p_env) const; - float environment_get_exposure(RID p_env) const; - float environment_get_white(RID p_env) const; - bool environment_get_auto_exposure(RID p_env) const; - float environment_get_min_luminance(RID p_env) const; - float environment_get_max_luminance(RID p_env) const; - float environment_get_auto_exposure_scale(RID p_env) const; - float environment_get_auto_exposure_speed(RID p_env) const; - 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_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) {} @@ -802,6 +838,10 @@ public: RID render_buffers_create(); void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa); + RID render_buffers_get_back_buffer_texture(RID p_render_buffers); + void render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas); + void render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment); + void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count); @@ -818,6 +858,9 @@ public: virtual void update(); + virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw); + _FORCE_INLINE_ VS::ViewportDebugDraw get_debug_draw_mode() const { return debug_draw; } + RasterizerSceneRD(RasterizerStorageRD *p_storage); ~RasterizerSceneRD(); }; diff --git a/servers/visual/rasterizer_rd/shaders/SCsub b/servers/visual/rasterizer_rd/shaders/SCsub index ff83b46a9b..7d5e88b0ab 100644 --- a/servers/visual/rasterizer_rd/shaders/SCsub +++ b/servers/visual/rasterizer_rd/shaders/SCsub @@ -14,5 +14,6 @@ if 'RD_GLSL' in env['BUILDERS']: env.RD_GLSL('giprobe.glsl'); env.RD_GLSL('giprobe_debug.glsl'); env.RD_GLSL('giprobe_sdf.glsl'); - + env.RD_GLSL('luminance_reduce.glsl'); + diff --git a/servers/visual/rasterizer_rd/shaders/blur.glsl b/servers/visual/rasterizer_rd/shaders/blur.glsl index 3f67638a45..ae4cedec67 100644 --- a/servers/visual/rasterizer_rd/shaders/blur.glsl +++ b/servers/visual/rasterizer_rd/shaders/blur.glsl @@ -125,31 +125,43 @@ void main() { //Glow uses larger sigma 1 for a more rounded blur effect +#define GLOW_ADD( m_ofs, m_mult )\ + {\ + vec2 ofs = uv_interp + m_ofs * pix_size;\ + vec4 c = texture(source_color, ofs ) * m_mult; \ + if (any(lessThan(ofs,vec2(0.0))) || any(greaterThan(ofs,vec2(1.0)))) {\ + c*=0.0;\ + }\ + color+=c;\ + } + if (bool(blur.flags & FLAG_HORIZONTAL)) { vec2 pix_size = blur.pixel_size; pix_size *= 0.5; //reading from larger buffer, so use more samples vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938; - color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.165569; - color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.140367; - color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.106595; - color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.165569; - color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.140367; - color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.106595; + GLOW_ADD(vec2(1.0, 0.0),0.165569); + GLOW_ADD(vec2(2.0, 0.0),0.140367); + GLOW_ADD(vec2(3.0, 0.0), 0.106595); + GLOW_ADD(vec2(-1.0, 0.0),0.165569); + GLOW_ADD(vec2(-2.0, 0.0),0.140367); + GLOW_ADD(vec2(-3.0, 0.0),0.106595); color *= blur.glow_strength; frag_color = color; } else { vec2 pix_size = blur.pixel_size; vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713; - color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.233062; - color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.122581; - color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.233062; - color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.122581; + GLOW_ADD(vec2(0.0, 1.0),0.233062); + GLOW_ADD(vec2(0.0, 2.0),0.122581); + GLOW_ADD(vec2(0.0, -1.0),0.233062); + GLOW_ADD(vec2(0.0, -2.0),0.122581); color *= blur.glow_strength; frag_color = color; } +#undef GLOW_ADD + if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) { #ifdef GLOW_USE_AUTO_EXPOSURE diff --git a/servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl b/servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl new file mode 100644 index 0000000000..157ea91a36 --- /dev/null +++ b/servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl @@ -0,0 +1,76 @@ +/* clang-format off */ +[compute] +/* clang-format on */ +#version 450 + +VERSION_DEFINES + +#define BLOCK_SIZE 8 + +layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in; + +shared float tmp_data[BLOCK_SIZE*BLOCK_SIZE]; + + +#ifdef READ_TEXTURE + +//use for main texture +layout(set = 0, binding = 1) uniform texture2D source_texture; +layout(set = 0, binding = 2) uniform sampler source_sampler; + +#else + +//use for intermediate textures +layout(r32f, set = 0, binding = 1) uniform restrict readonly image2D source_luminance; + +#endif + +layout(r32f, set = 0, binding = 3) uniform restrict writeonly image2D dest_luminance; + +layout(push_constant, binding = 0, std430) uniform Params { + ivec2 source_size; +} params; + +void main() { + + + uint t = gl_LocalInvocationID.y * BLOCK_SIZE + gl_LocalInvocationID.x; + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + + if (any(lessThan(pos,params.source_size))) { + +#ifdef READ_TEXTURE + vec3 v = texelFetch(sampler2D(source_texture,source_sampler),pos).rgb; + avg += max(v.r,max(v.g,v.b)); + tmp_data[t] = 0.0; +#else + tmp_data[t] = imageLoad(source_luminance, pos); +#endif + } else { + tmp_data[t] = 0.0; + } + + groupMemoryBarrier(); + barrier(); + + uint size = (BLOCK_SIZE * BLOCK_SIZE)>>1; + + do { + if (t>=1; + + } while(size>1); + + if (t==0) { + //compute rect size + ivec2 rect_size = max(params.source_size - pos,ivec2(BLOCK_SIZE)); + float avg = tmp_data[0] / float(rect_size.x*rect_size.y); + pos/=ivec2(BLOCK_SIZE); + imageStore(dest_luminance, pos, vec4(avg)); + } +} diff --git a/servers/visual/rasterizer_rd/shaders/tonemap.glsl b/servers/visual/rasterizer_rd/shaders/tonemap.glsl index 477e0d1055..ee6ced0a55 100644 --- a/servers/visual/rasterizer_rd/shaders/tonemap.glsl +++ b/servers/visual/rasterizer_rd/shaders/tonemap.glsl @@ -187,31 +187,31 @@ vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels vec3 glow = vec3(0.0f); if (bool(params.glow_level_flags & (1 << 0))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb; + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 0).rgb; } if (bool(params.glow_level_flags & (1 << 1))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb; + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb; } if (bool(params.glow_level_flags & (1 << 2))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb; + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb; } if (bool(params.glow_level_flags & (1 << 3))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb; + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb; } if (bool(params.glow_level_flags & (1 << 4))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb; + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb; } if (bool(params.glow_level_flags & (1 << 5))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb; + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb; } if (bool(params.glow_level_flags & (1 << 6))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 7).rgb; + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb; } return glow; @@ -221,6 +221,7 @@ vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels #define GLOW_MODE_SCREEN 1 #define GLOW_MODE_SOFTLIGHT 2 #define GLOW_MODE_REPLACE 3 +#define GLOW_MODE_MIX 4 vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blending mode if (params.glow_mode == GLOW_MODE_ADD) { @@ -266,13 +267,20 @@ void main() { // Early Tonemap & SRGB Conversion + if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) { + + vec3 glow = gather_glow(source_glow, uv_interp); + color.rgb = mix(color.rgb,glow,params.glow_intensity); + + } + color = apply_tonemapping(color, params.white); color = linear_to_srgb(color); // regular linear -> SRGB conversion // Glow - if (params.use_glow) { + if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) { vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity; diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index e791a9897f..cc80a96efc 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -528,7 +528,7 @@ public: BIND6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality) BIND6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality) - BIND11(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool) + BIND12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool) BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 5dc75c0f15..201d60cb40 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -442,7 +442,7 @@ public: FUNC6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality) FUNC6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality) - FUNC11(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool) + FUNC12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool) FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) diff --git a/servers/visual_server.h b/servers/visual_server.h index 8e83464a87..f79933e31c 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -740,8 +740,9 @@ public: GLOW_BLEND_MODE_SCREEN, GLOW_BLEND_MODE_SOFTLIGHT, GLOW_BLEND_MODE_REPLACE, + GLOW_BLEND_MODE_MIX, }; - virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0; + virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0; enum EnvironmentToneMapper { ENV_TONE_MAPPER_LINEAR, -- cgit v1.2.3