From 8da3c739bff12a2c16ec2f7ff07336bd5d1c9035 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Mon, 31 Aug 2020 23:04:45 -0700 Subject: [PATCH] Add high quality glow mode --- doc/classes/ProjectSettings.xml | 3 ++ drivers/dummy/rasterizer_dummy.h | 1 + editor/editor_node.cpp | 2 + servers/rendering/rasterizer.h | 1 + .../rasterizer_rd/rasterizer_effects_rd.cpp | 4 +- .../rasterizer_rd/rasterizer_effects_rd.h | 5 ++- .../rasterizer_rd/rasterizer_scene_rd.cpp | 9 ++++- .../rasterizer_rd/rasterizer_scene_rd.h | 2 + .../rendering/rasterizer_rd/shaders/copy.glsl | 40 +++++++++++++++---- servers/rendering/rendering_server_raster.h | 1 + servers/rendering/rendering_server_wrap_mt.h | 1 + servers/rendering_server.cpp | 1 + servers/rendering_server.h | 1 + 13 files changed, 58 insertions(+), 13 deletions(-) diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index f1feade59d..a28dc06937 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -1038,6 +1038,9 @@ Lower-end override for [member rendering/quality/glow/upscale_mode] on mobile devices, due to performance concerns or driver support. + + Takes more samples during downsample pass of glow. This ensures that single pixels are captured by glow which makes the glow look smoother and more stable during movement. However, it is very expensive and makes the glow post process take twice as long. + Strategy used for framebuffer allocation. The simpler it is, the less resources it uses (but the less features it supports). If set to "2D Without Sampling" or "3D Without Effects", sample buffers will not be allocated. This means [code]SCREEN_TEXTURE[/code] and [code]DEPTH_TEXTURE[/code] will not be available in shaders and post-processing effects will not be available in the [Environment]. diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index 0d2d6b38a7..5947d7a5e5 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -88,6 +88,7 @@ public: 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, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) {} virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) {} + virtual void environment_glow_set_use_high_quality(bool p_enable) {} void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {} 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) {} diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 26281a232b..16b8c6e0ac 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -478,6 +478,8 @@ void EditorNode::_notification(int p_what) { RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_enabled"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_amount"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_limit")); bool glow_bicubic = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0; RS::get_singleton()->environment_glow_set_use_bicubic_upscale(glow_bicubic); + bool glow_high_quality = GLOBAL_GET("rendering/quality/glow/use_high_quality"); + RS::get_singleton()->environment_glow_set_use_high_quality(glow_high_quality); RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality"))); RS::get_singleton()->environment_set_ssr_roughness_quality(ssr_roughness_quality); RS::SubSurfaceScatteringQuality sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_quality"))); diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h index e1282fdf71..78eb369672 100644 --- a/servers/rendering/rasterizer.h +++ b/servers/rendering/rasterizer.h @@ -86,6 +86,7 @@ public: 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, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0; virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; + virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_lenght, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) = 0; diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp index 323d39190e..93ddcb1cff 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp @@ -389,7 +389,7 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_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, float p_auto_exposure_grey) { +void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, 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, float p_auto_exposure_grey) { zeromem(©.push_constant, sizeof(CopyPushConstant)); CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW; @@ -420,7 +420,7 @@ void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_texture, RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_auto_exposure), 1); } - copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0); + copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h index b0964f23e7..6dff835e21 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h @@ -81,7 +81,8 @@ class RasterizerEffectsRD { COPY_FLAG_GLOW_FIRST_PASS = (1 << 4), COPY_FLAG_FLIP_Y = (1 << 5), COPY_FLAG_FORCE_LUMINANCE = (1 << 6), - COPY_FLAG_ALL_SOURCE = (1 << 7) + COPY_FLAG_ALL_SOURCE = (1 << 7), + COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8) }; struct CopyPushConstant { @@ -586,7 +587,7 @@ public: void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far); void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false); void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false); - void gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_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(), float p_auto_exposure_grey = 1.0); + void gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, 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(), float p_auto_exposure_grey = 1.0); void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp index 34818d2683..958d8eac1f 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp @@ -2951,6 +2951,10 @@ void RasterizerSceneRD::environment_glow_set_use_bicubic_upscale(bool p_enable) glow_bicubic_upscale = p_enable; } +void RasterizerSceneRD::environment_glow_set_use_high_quality(bool p_enable) { + glow_high_quality = p_enable; +} + void RasterizerSceneRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -5265,9 +5269,9 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu if (env->auto_exposure && rb->luminance.current.is_valid()) { luminance_texture = rb->luminance.current; } - storage->get_effects()->gaussian_glow(rb->texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, 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, luminance_texture, env->auto_exp_scale); + storage->get_effects()->gaussian_glow(rb->texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); } else { - storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength); + storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); } } } @@ -8310,6 +8314,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { screen_space_roughness_limiter_amount = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_amount"); screen_space_roughness_limiter_limit = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_limit"); glow_bicubic_upscale = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0; + glow_high_quality = GLOBAL_GET("rendering/quality/glow/use_high_quality"); ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality"))); sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_quality"))); sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale"); diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h index f504240f50..7fe74a97f5 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h @@ -765,6 +765,7 @@ private: RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM; bool ssao_half_size = false; bool glow_bicubic_upscale = false; + bool glow_high_quality = false; RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGNESS_QUALITY_LOW; static uint64_t auto_exposure_counter; @@ -1530,6 +1531,7 @@ public: 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, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap); void environment_glow_set_use_bicubic_upscale(bool p_enable); + void environment_glow_set_use_high_quality(bool p_enable); 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); bool environment_is_fog_enabled(RID p_env) const; diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/rasterizer_rd/shaders/copy.glsl index 86c15e9efa..e565bd8e3d 100644 --- a/servers/rendering/rasterizer_rd/shaders/copy.glsl +++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl @@ -14,6 +14,7 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #define FLAG_FLIP_Y (1 << 5) #define FLAG_FORCE_LUMINANCE (1 << 6) #define FLAG_COPY_ALL_SOURCE (1 << 7) +#define FLAG_HIGH_QUALITY_GLOW (1 << 8) layout(push_constant, binding = 1, std430) uniform Params { ivec4 section; @@ -120,13 +121,38 @@ void main() { ivec2 section_begin = params.section.xy << 1; ivec2 section_end = section_begin + (params.section.zw << 1); - GLOW_ADD(ivec2(0, 0), 0.174938); - GLOW_ADD(ivec2(1, 0), 0.165569); - GLOW_ADD(ivec2(2, 0), 0.140367); - GLOW_ADD(ivec2(3, 0), 0.106595); - GLOW_ADD(ivec2(-1, 0), 0.165569); - GLOW_ADD(ivec2(-2, 0), 0.140367); - GLOW_ADD(ivec2(-3, 0), 0.106595); + if (bool(params.flags & FLAG_HIGH_QUALITY_GLOW)) { + //Sample from two lines to capture single pixel features + GLOW_ADD(ivec2(0, 0), 0.152781); + GLOW_ADD(ivec2(1, 0), 0.144599); + GLOW_ADD(ivec2(2, 0), 0.122589); + GLOW_ADD(ivec2(3, 0), 0.093095); + GLOW_ADD(ivec2(4, 0), 0.063327); + GLOW_ADD(ivec2(-1, 0), 0.144599); + GLOW_ADD(ivec2(-2, 0), 0.122589); + GLOW_ADD(ivec2(-3, 0), 0.093095); + GLOW_ADD(ivec2(-4, 0), 0.063327); + + GLOW_ADD(ivec2(0, 1), 0.152781); + GLOW_ADD(ivec2(1, 1), 0.144599); + GLOW_ADD(ivec2(2, 1), 0.122589); + GLOW_ADD(ivec2(3, 1), 0.093095); + GLOW_ADD(ivec2(4, 1), 0.063327); + GLOW_ADD(ivec2(-1, 1), 0.144599); + GLOW_ADD(ivec2(-2, 1), 0.122589); + GLOW_ADD(ivec2(-3, 1), 0.093095); + GLOW_ADD(ivec2(-4, 1), 0.063327); + color *= 0.5; + } else { + GLOW_ADD(ivec2(0, 0), 0.174938); + GLOW_ADD(ivec2(1, 0), 0.165569); + GLOW_ADD(ivec2(2, 0), 0.140367); + GLOW_ADD(ivec2(3, 0), 0.106595); + GLOW_ADD(ivec2(-1, 0), 0.165569); + GLOW_ADD(ivec2(-2, 0), 0.140367); + GLOW_ADD(ivec2(-3, 0), 0.106595); + } + color *= params.glow_strength; } else { ivec2 base_pos = pos + params.section.xy; diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index b4eac8cd76..547595f9b0 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -557,6 +557,7 @@ public: BIND11(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float) BIND1(environment_glow_set_use_bicubic_upscale, bool) + BIND1(environment_glow_set_use_high_quality, bool) BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index fb5c161c8a..40aff46a3c 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -474,6 +474,7 @@ public: FUNC11(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float) FUNC1(environment_glow_set_use_bicubic_upscale, bool) + FUNC1(environment_glow_set_use_high_quality, bool) FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 3b034da3aa..8f863a6fc8 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2387,6 +2387,7 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/quality/glow/upscale_mode", 1); ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/glow/upscale_mode", PropertyInfo(Variant::INT, "rendering/quality/glow/upscale_mode", PROPERTY_HINT_ENUM, "Linear (Fast),Bicubic (Slow)")); GLOBAL_DEF("rendering/quality/glow/upscale_mode.mobile", 0); + GLOBAL_DEF("rendering/quality/glow/use_high_quality", false); GLOBAL_DEF("rendering/quality/screen_space_reflection/roughness_quality", 1); ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_space_reflection/roughness_quality", PropertyInfo(Variant::INT, "rendering/quality/screen_space_reflection/roughness_quality", PROPERTY_HINT_ENUM, "Disabled (Fastest),Low (Fast),Medium (Average),High (Slow)")); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index a13fd4954b..38b4dec658 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -784,6 +784,7 @@ public: 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) = 0; virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; + virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; enum EnvironmentToneMapper { ENV_TONE_MAPPER_LINEAR,