From bed8980ca50cb6a197f37e3decaff963d5cedce1 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 25 Jan 2020 07:18:55 -0300 Subject: [PATCH] Re-implemented screen space ambient occlusion --- editor/editor_node.cpp | 1 + editor/plugins/spatial_editor_plugin.cpp | 9 +- editor/plugins/spatial_editor_plugin.h | 1 + scene/main/viewport.cpp | 1 + scene/main/viewport.h | 1 + scene/resources/environment.cpp | 94 +--- scene/resources/environment.h | 25 +- servers/visual/rasterizer.h | 6 +- .../rasterizer_rd/rasterizer_effects_rd.cpp | 214 +++++++++- .../rasterizer_rd/rasterizer_effects_rd.h | 80 +++- .../rasterizer_scene_high_end_rd.cpp | 401 +++++++++++++----- .../rasterizer_scene_high_end_rd.h | 46 +- .../rasterizer_rd/rasterizer_scene_rd.cpp | 203 ++++++++- .../rasterizer_rd/rasterizer_scene_rd.h | 43 +- .../rasterizer_rd/rasterizer_storage_rd.cpp | 2 +- servers/visual/rasterizer_rd/shaders/SCsub | 3 + .../visual/rasterizer_rd/shaders/blur.glsl | 4 + .../rasterizer_rd/shaders/blur_inc.glsl | 1 + .../rasterizer_rd/shaders/scene_high_end.glsl | 48 ++- .../shaders/scene_high_end_inc.glsl | 41 +- .../visual/rasterizer_rd/shaders/ssao.glsl | 257 +++++++++++ .../rasterizer_rd/shaders/ssao_blur.glsl | 163 +++++++ .../rasterizer_rd/shaders/ssao_minify.glsl | 49 +++ servers/visual/visual_server_raster.h | 5 +- servers/visual/visual_server_viewport.cpp | 3 + servers/visual/visual_server_wrap_mt.h | 6 +- servers/visual_server.cpp | 6 +- servers/visual_server.h | 20 +- 28 files changed, 1469 insertions(+), 264 deletions(-) create mode 100644 servers/visual/rasterizer_rd/shaders/ssao.glsl create mode 100644 servers/visual/rasterizer_rd/shaders/ssao_blur.glsl create mode 100644 servers/visual/rasterizer_rd/shaders/ssao_minify.glsl diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 2fb417ad499..a3d9b180f03 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -360,6 +360,7 @@ void EditorNode::_notification(int p_what) { VS::DOFBlurQuality dof_quality = VS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_quality"))); bool dof_jitter = GLOBAL_GET("rendering/quality/filters/depth_of_field_use_jitter"); VS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter); + VS::get_singleton()->environment_set_ssao_quality(VS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size")); } ResourceImporterTexture::get_singleton()->update_imports(); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 7711231be84..815b3be6984 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -2769,7 +2769,8 @@ void SpatialEditorViewport::_menu_option(int p_option) { case VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO: case VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING: case VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION: - case VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE: { + case VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE: + case VIEW_DISPLAY_DEBUG_SSAO: { static const int display_options[] = { VIEW_DISPLAY_NORMAL, @@ -2784,6 +2785,7 @@ void SpatialEditorViewport::_menu_option(int p_option) { VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING, VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION, VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, + VIEW_DISPLAY_DEBUG_SSAO, VIEW_MAX }; static const Viewport::DebugDraw debug_draw_modes[] = { @@ -2798,7 +2800,8 @@ void SpatialEditorViewport::_menu_option(int p_option) { Viewport::DEBUG_DRAW_GI_PROBE_ALBEDO, Viewport::DEBUG_DRAW_GI_PROBE_LIGHTING, Viewport::DEBUG_DRAW_GI_PROBE_EMISSION, - Viewport::DEBUG_DRAW_SCENE_LUMINANCE + Viewport::DEBUG_DRAW_SCENE_LUMINANCE, + Viewport::DEBUG_DRAW_SSAO }; int idx = 0; @@ -3644,6 +3647,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed display_submenu->add_radio_check_item(TTR("GIProbe Emission"), VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION); display_submenu->add_separator(); display_submenu->add_radio_check_item(TTR("Scene Luminance"), VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE); + display_submenu->add_separator(); + display_submenu->add_radio_check_item(TTR("SSAO"), VIEW_DISPLAY_DEBUG_SSAO); display_submenu->set_name("display_advanced"); view_menu->get_popup()->add_submenu_item(TTR("Display Advanced..."), "display_advanced"); view_menu->get_popup()->add_separator(); diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 0eb56989e08..065a0396a86 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -174,6 +174,7 @@ class SpatialEditorViewport : public Control { VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING, VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION, VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, + VIEW_DISPLAY_DEBUG_SSAO, VIEW_LOCK_ROTATION, VIEW_CINEMATIC_PREVIEW, VIEW_MAX diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 9e9b77bab4f..dad2ec40107 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -3269,6 +3269,7 @@ void Viewport::_bind_methods() { BIND_ENUM_CONSTANT(DEBUG_DRAW_SHADOW_ATLAS); BIND_ENUM_CONSTANT(DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS); BIND_ENUM_CONSTANT(DEBUG_DRAW_SCENE_LUMINANCE); + BIND_ENUM_CONSTANT(DEBUG_DRAW_SSAO); BIND_ENUM_CONSTANT(MSAA_DISABLED); BIND_ENUM_CONSTANT(MSAA_2X); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 53a024f5554..6e77467f232 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -137,6 +137,7 @@ public: DEBUG_DRAW_SHADOW_ATLAS, DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS, DEBUG_DRAW_SCENE_LUMINANCE, + DEBUG_DRAW_SSAO, }; diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 30ba8762ddd..d72036462e9 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -79,17 +79,17 @@ void Environment::set_canvas_max_layer(int p_max_layer) { void Environment::set_ambient_light_color(const Color &p_color) { ambient_color = p_color; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source)); + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); } void Environment::set_ambient_light_energy(float p_energy) { ambient_energy = p_energy; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source)); + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); } void Environment::set_ambient_light_sky_contribution(float p_energy) { ambient_sky_contribution = p_energy; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source)); + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); } void Environment::set_camera_feed_id(int p_camera_feed_id) { @@ -102,7 +102,7 @@ void Environment::set_camera_feed_id(int p_camera_feed_id) { void Environment::set_ambient_source(AmbientSource p_source) { ambient_source = p_source; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source)); + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); } Environment::AmbientSource Environment::get_ambient_source() const { @@ -110,7 +110,7 @@ Environment::AmbientSource Environment::get_ambient_source() const { } void Environment::set_reflection_source(ReflectionSource p_source) { reflection_source = p_source; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source)); + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); } Environment::ReflectionSource Environment::get_reflection_source() const { return reflection_source; @@ -451,7 +451,7 @@ bool Environment::is_ssr_rough() const { void Environment::set_ssao_enabled(bool p_enable) { ssao_enabled = p_enable; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); _change_notify(); } @@ -463,7 +463,7 @@ bool Environment::is_ssao_enabled() const { void Environment::set_ssao_radius(float p_radius) { ssao_radius = p_radius; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_radius() const { @@ -473,7 +473,7 @@ float Environment::get_ssao_radius() const { void Environment::set_ssao_intensity(float p_intensity) { ssao_intensity = p_intensity; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_intensity() const { @@ -481,30 +481,10 @@ float Environment::get_ssao_intensity() const { return ssao_intensity; } -void Environment::set_ssao_radius2(float p_radius) { - - ssao_radius2 = p_radius; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); -} -float Environment::get_ssao_radius2() const { - - return ssao_radius2; -} - -void Environment::set_ssao_intensity2(float p_intensity) { - - ssao_intensity2 = p_intensity; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); -} -float Environment::get_ssao_intensity2() const { - - return ssao_intensity2; -} - void Environment::set_ssao_bias(float p_bias) { ssao_bias = p_bias; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_bias() const { @@ -514,7 +494,7 @@ float Environment::get_ssao_bias() const { void Environment::set_ssao_direct_light_affect(float p_direct_light_affect) { ssao_direct_light_affect = p_direct_light_affect; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_direct_light_affect() const { @@ -524,49 +504,38 @@ float Environment::get_ssao_direct_light_affect() const { void Environment::set_ssao_ao_channel_affect(float p_ao_channel_affect) { ssao_ao_channel_affect = p_ao_channel_affect; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_ao_channel_affect() const { return ssao_ao_channel_affect; } -void Environment::set_ssao_color(const Color &p_color) { +void Environment::set_ao_color(const Color &p_color) { - ssao_color = p_color; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + ao_color = p_color; + VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); } -Color Environment::get_ssao_color() const { +Color Environment::get_ao_color() const { - return ssao_color; + return ao_color; } void Environment::set_ssao_blur(SSAOBlur p_blur) { ssao_blur = p_blur; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } Environment::SSAOBlur Environment::get_ssao_blur() const { return ssao_blur; } -void Environment::set_ssao_quality(SSAOQuality p_quality) { - - ssao_quality = p_quality; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); -} - -Environment::SSAOQuality Environment::get_ssao_quality() const { - - return ssao_quality; -} - void Environment::set_ssao_edge_sharpness(float p_edge_sharpness) { ssao_edge_sharpness = p_edge_sharpness; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_edge_sharpness() const { @@ -888,6 +857,8 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("get_camera_feed_id"), &Environment::get_camera_feed_id); ClassDB::bind_method(D_METHOD("get_ambient_source"), &Environment::get_ambient_source); ClassDB::bind_method(D_METHOD("get_reflection_source"), &Environment::get_reflection_source); + ClassDB::bind_method(D_METHOD("set_ao_color", "color"), &Environment::set_ao_color); + ClassDB::bind_method(D_METHOD("get_ao_color"), &Environment::get_ao_color); ADD_GROUP("Background", "background_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "background_mode", PROPERTY_HINT_ENUM, "Clear Color,Custom Color,Sky,Canvas,Keep,Camera Feed"), "set_background", "get_background"); @@ -904,6 +875,7 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_light_color"), "set_ambient_light_color", "get_ambient_light_color"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_sky_contribution", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ambient_light_sky_contribution", "get_ambient_light_sky_contribution"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_light_energy", "get_ambient_light_energy"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_light_occlusion_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ao_color", "get_ao_color"); ADD_GROUP("Reflected Light", "reflected_light_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "reflected_light_source", PROPERTY_HINT_ENUM, "Background,Disabled,Sky"), "set_reflection_source", "get_reflection_source"); @@ -1035,12 +1007,6 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_ssao_intensity", "intensity"), &Environment::set_ssao_intensity); ClassDB::bind_method(D_METHOD("get_ssao_intensity"), &Environment::get_ssao_intensity); - ClassDB::bind_method(D_METHOD("set_ssao_radius2", "radius"), &Environment::set_ssao_radius2); - ClassDB::bind_method(D_METHOD("get_ssao_radius2"), &Environment::get_ssao_radius2); - - ClassDB::bind_method(D_METHOD("set_ssao_intensity2", "intensity"), &Environment::set_ssao_intensity2); - ClassDB::bind_method(D_METHOD("get_ssao_intensity2"), &Environment::get_ssao_intensity2); - ClassDB::bind_method(D_METHOD("set_ssao_bias", "bias"), &Environment::set_ssao_bias); ClassDB::bind_method(D_METHOD("get_ssao_bias"), &Environment::get_ssao_bias); @@ -1050,15 +1016,9 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_ssao_ao_channel_affect", "amount"), &Environment::set_ssao_ao_channel_affect); ClassDB::bind_method(D_METHOD("get_ssao_ao_channel_affect"), &Environment::get_ssao_ao_channel_affect); - ClassDB::bind_method(D_METHOD("set_ssao_color", "color"), &Environment::set_ssao_color); - ClassDB::bind_method(D_METHOD("get_ssao_color"), &Environment::get_ssao_color); - ClassDB::bind_method(D_METHOD("set_ssao_blur", "mode"), &Environment::set_ssao_blur); ClassDB::bind_method(D_METHOD("get_ssao_blur"), &Environment::get_ssao_blur); - ClassDB::bind_method(D_METHOD("set_ssao_quality", "quality"), &Environment::set_ssao_quality); - ClassDB::bind_method(D_METHOD("get_ssao_quality"), &Environment::get_ssao_quality); - ClassDB::bind_method(D_METHOD("set_ssao_edge_sharpness", "edge_sharpness"), &Environment::set_ssao_edge_sharpness); ClassDB::bind_method(D_METHOD("get_ssao_edge_sharpness"), &Environment::get_ssao_edge_sharpness); @@ -1066,13 +1026,9 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ssao_enabled"), "set_ssao_enabled", "is_ssao_enabled"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_radius", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_ssao_radius", "get_ssao_radius"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_intensity", PROPERTY_HINT_RANGE, "0.0,128,0.1"), "set_ssao_intensity", "get_ssao_intensity"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_radius2", PROPERTY_HINT_RANGE, "0.0,128,0.1"), "set_ssao_radius2", "get_ssao_radius2"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_intensity2", PROPERTY_HINT_RANGE, "0.0,128,0.1"), "set_ssao_intensity2", "get_ssao_intensity2"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_bias", PROPERTY_HINT_RANGE, "0.001,8,0.001"), "set_ssao_bias", "get_ssao_bias"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_light_affect", PROPERTY_HINT_RANGE, "0.00,1,0.01"), "set_ssao_direct_light_affect", "get_ssao_direct_light_affect"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_ao_channel_affect", PROPERTY_HINT_RANGE, "0.00,1,0.01"), "set_ssao_ao_channel_affect", "get_ssao_ao_channel_affect"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ssao_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ssao_color", "get_ssao_color"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "ssao_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_ssao_quality", "get_ssao_quality"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ssao_blur", PROPERTY_HINT_ENUM, "Disabled,1x1,2x2,3x3"), "set_ssao_blur", "get_ssao_blur"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_edge_sharpness", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_ssao_edge_sharpness", "get_ssao_edge_sharpness"); @@ -1183,17 +1139,12 @@ void Environment::_bind_methods() { BIND_ENUM_CONSTANT(SSAO_BLUR_1x1); BIND_ENUM_CONSTANT(SSAO_BLUR_2x2); BIND_ENUM_CONSTANT(SSAO_BLUR_3x3); - - BIND_ENUM_CONSTANT(SSAO_QUALITY_LOW); - BIND_ENUM_CONSTANT(SSAO_QUALITY_MEDIUM); - BIND_ENUM_CONSTANT(SSAO_QUALITY_HIGH); } Environment::Environment() : bg_mode(BG_CLEAR_COLOR), tone_mapper(TONE_MAPPER_LINEAR), ssao_blur(SSAO_BLUR_3x3), - ssao_quality(SSAO_QUALITY_MEDIUM), glow_blend_mode(GLOW_BLEND_MODE_ADDITIVE) { environment = VS::get_singleton()->environment_create(); @@ -1237,14 +1188,11 @@ Environment::Environment() : ssao_enabled = false; ssao_radius = 1; ssao_intensity = 1; - ssao_radius2 = 0; - ssao_intensity2 = 1; ssao_bias = 0.01; ssao_direct_light_affect = 0.0; ssao_ao_channel_affect = 0.0; ssao_blur = SSAO_BLUR_3x3; set_ssao_edge_sharpness(4); - set_ssao_quality(SSAO_QUALITY_MEDIUM); glow_enabled = false; glow_levels = (1 << 2) | (1 << 4); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index 2e799d8a864..4360ceeca35 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -87,12 +87,6 @@ public: SSAO_BLUR_3x3 }; - enum SSAOQuality { - SSAO_QUALITY_LOW, - SSAO_QUALITY_MEDIUM, - SSAO_QUALITY_HIGH - }; - private: RID environment; @@ -105,6 +99,7 @@ private: int bg_canvas_max_layer; Color ambient_color; float ambient_energy; + Color ao_color; float ambient_sky_contribution; int camera_feed_id; AmbientSource ambient_source; @@ -135,15 +130,11 @@ private: bool ssao_enabled; float ssao_radius; float ssao_intensity; - float ssao_radius2; - float ssao_intensity2; float ssao_bias; float ssao_direct_light_affect; float ssao_ao_channel_affect; - Color ssao_color; SSAOBlur ssao_blur; float ssao_edge_sharpness; - SSAOQuality ssao_quality; bool glow_enabled; int glow_levels; @@ -278,12 +269,6 @@ public: void set_ssao_intensity(float p_intensity); float get_ssao_intensity() const; - void set_ssao_radius2(float p_radius); - float get_ssao_radius2() const; - - void set_ssao_intensity2(float p_intensity); - float get_ssao_intensity2() const; - void set_ssao_bias(float p_bias); float get_ssao_bias() const; @@ -293,15 +278,12 @@ public: void set_ssao_ao_channel_affect(float p_ao_channel_affect); float get_ssao_ao_channel_affect() const; - void set_ssao_color(const Color &p_color); - Color get_ssao_color() const; + void set_ao_color(const Color &p_color); + Color get_ao_color() const; void set_ssao_blur(SSAOBlur p_blur); SSAOBlur get_ssao_blur() const; - void set_ssao_quality(SSAOQuality p_quality); - SSAOQuality get_ssao_quality() const; - void set_ssao_edge_sharpness(float p_edge_sharpness); float get_ssao_edge_sharpness() const; @@ -391,7 +373,6 @@ VARIANT_ENUM_CAST(Environment::AmbientSource) VARIANT_ENUM_CAST(Environment::ReflectionSource) VARIANT_ENUM_CAST(Environment::ToneMapper) VARIANT_ENUM_CAST(Environment::GlowBlendMode) -VARIANT_ENUM_CAST(Environment::SSAOQuality) VARIANT_ENUM_CAST(Environment::SSAOBlur) class CameraEffects : public Resource { diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 0bfd323ec00..913bebd0f54 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -69,7 +69,7 @@ public: virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; - virtual void environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient = VS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, VS::EnvironmentReflectionSource p_reflection_source = VS::ENV_REFLECTION_SOURCE_BG) = 0; + virtual void environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient = VS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, VS::EnvironmentReflectionSource p_reflection_source = VS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0; // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; @@ -79,7 +79,9 @@ public: 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; - virtual 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) = 0; + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; + + virtual void environment_set_ssao_quality(VS::EnvironmentSSAOQuality p_quality, bool p_half_size) = 0; virtual 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) = 0; diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp index 111ad06f5b6..4f8e8c6944d 100644 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp @@ -116,12 +116,15 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bo return uniform_set; } -void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y) { +void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, bool p_force_luminance) { zeromem(&blur.push_constant, sizeof(BlurPushConstant)); if (p_flip_y) { blur.push_constant.flags |= BLUR_FLAG_FLIP_Y; } + if (p_force_luminance) { + blur.push_constant.flags |= BLUR_COPY_FORCE_LUMINANCE; + } RD::DrawListID 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, Vector(), 1.0, 0, p_rect); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); @@ -570,6 +573,160 @@ void RasterizerEffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, con RD::get_singleton()->compute_list_end(); } +void RasterizerEffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness) { + + //minify first + ssao.minify_push_constant.orthogonal = p_projection.is_orthogonal(); + ssao.minify_push_constant.z_near = p_projection.get_z_near(); + ssao.minify_push_constant.z_far = p_projection.get_z_far(); + ssao.minify_push_constant.pixel_size[0] = 1.0 / p_depth_buffer_size.x; + ssao.minify_push_constant.pixel_size[1] = 1.0 / p_depth_buffer_size.y; + ssao.minify_push_constant.source_size[0] = p_depth_buffer_size.x; + ssao.minify_push_constant.source_size[1] = p_depth_buffer_size.y; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + /* FIRST PASS */ + // Minify the depth buffer. + + for (int i = 0; i < depth_mipmaps.size(); i++) { + + if (i == 0) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_MINIFY_FIRST]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0); + } else { + if (i == 1) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_MINIFY_MIPMAP]); + } + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(depth_mipmaps[i - 1]), 0); + } + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(depth_mipmaps[i]), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.minify_push_constant, sizeof(SSAOMinifyPushConstant)); + // shrink after set + ssao.minify_push_constant.source_size[0] = MAX(1, ssao.minify_push_constant.source_size[0] >> 1); + ssao.minify_push_constant.source_size[1] = MAX(1, ssao.minify_push_constant.source_size[1] >> 1); + + int x_groups = (ssao.minify_push_constant.source_size[0] - 1) / 8 + 1; + int y_groups = (ssao.minify_push_constant.source_size[1] - 1) / 8 + 1; + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + + /* SECOND PASS */ + // Gather samples + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[(SSAO_GATHER_LOW + p_quality) + (p_half_size ? 4 : 0)]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao1), 1); + if (!p_half_size) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 2); + } + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_normal_buffer), 3); + + ssao.gather_push_constant.screen_size[0] = p_depth_buffer_size.x; + ssao.gather_push_constant.screen_size[1] = p_depth_buffer_size.y; + if (p_half_size) { + ssao.gather_push_constant.screen_size[0] >>= 1; + ssao.gather_push_constant.screen_size[1] >>= 1; + } + ssao.gather_push_constant.z_far = p_projection.get_z_far(); + ssao.gather_push_constant.z_near = p_projection.get_z_near(); + ssao.gather_push_constant.orthogonal = p_projection.is_orthogonal(); + + ssao.gather_push_constant.proj_info[0] = -2.0f / (ssao.gather_push_constant.screen_size[0] * p_projection.matrix[0][0]); + ssao.gather_push_constant.proj_info[1] = -2.0f / (ssao.gather_push_constant.screen_size[1] * p_projection.matrix[1][1]); + ssao.gather_push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; + ssao.gather_push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; + //ssao.gather_push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; + //ssao.gather_push_constant.proj_info[3] = -(1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; + + ssao.gather_push_constant.radius = p_radius; + + ssao.gather_push_constant.proj_scale = float(p_projection.get_pixels_per_meter(ssao.gather_push_constant.screen_size[0])); + ssao.gather_push_constant.bias = p_bias; + ssao.gather_push_constant.intensity_div_r6 = p_intensity / pow(p_radius, 6.0f); + + ssao.gather_push_constant.pixel_size[0] = 1.0 / p_depth_buffer_size.x; + ssao.gather_push_constant.pixel_size[1] = 1.0 / p_depth_buffer_size.y; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant)); + + int x_groups = (ssao.gather_push_constant.screen_size[0] - 1) / 8 + 1; + int y_groups = (ssao.gather_push_constant.screen_size[1] - 1) / 8 + 1; + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + /* THIRD PASS */ + // Blur horizontal + + ssao.blur_push_constant.edge_sharpness = p_edge_sharpness; + ssao.blur_push_constant.filter_scale = p_blur + 1; + ssao.blur_push_constant.screen_size[0] = ssao.gather_push_constant.screen_size[0]; + ssao.blur_push_constant.screen_size[1] = ssao.gather_push_constant.screen_size[1]; + ssao.blur_push_constant.z_far = p_projection.get_z_far(); + ssao.blur_push_constant.z_near = p_projection.get_z_near(); + ssao.blur_push_constant.orthogonal = p_projection.is_orthogonal(); + ssao.blur_push_constant.axis[0] = 1; + ssao.blur_push_constant.axis[1] = 0; + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[p_half_size ? SSAO_BLUR_PASS_HALF : SSAO_BLUR_PASS]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao1), 0); + if (p_half_size) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 1); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 1); + } + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao2), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + /* THIRD PASS */ + // Blur vertical + + ssao.blur_push_constant.axis[0] = 0; + ssao.blur_push_constant.axis[1] = 1; + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao2), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao1), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + + if (p_half_size) { //must upscale + + /* FOURTH PASS */ + // upscale if half size + //back to full size + ssao.blur_push_constant.screen_size[0] = p_depth_buffer_size.x; + ssao.blur_push_constant.screen_size[1] = p_depth_buffer_size.y; + + RD::get_singleton()->compute_list_add_barrier(compute_list); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_BLUR_UPSCALE]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao1), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_upscale_buffer), 3); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 2); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); //not used but set anyway + + x_groups = (p_depth_buffer_size.x - 1) / 8 + 1; + y_groups = (p_depth_buffer_size.y - 1) / 8 + 1; + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + } + + RD::get_singleton()->compute_list_end(); +} + RasterizerEffectsRD::RasterizerEffectsRD() { { @@ -693,6 +850,61 @@ RasterizerEffectsRD::RasterizerEffectsRD() { } } + { + // Initialize ssao + uint32_t pipeline = 0; + { + Vector ssao_modes; + ssao_modes.push_back("\n#define MINIFY_START\n"); + ssao_modes.push_back("\n"); + + ssao.minify_shader.initialize(ssao_modes); + + ssao.minify_shader_version = ssao.minify_shader.version_create(); + + for (int i = 0; i <= SSAO_MINIFY_MIPMAP; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.minify_shader.version_get_shader(ssao.minify_shader_version, i)); + pipeline++; + } + } + { + Vector ssao_modes; + ssao_modes.push_back("\n#define SSAO_QUALITY_LOW\n"); + ssao_modes.push_back("\n"); + ssao_modes.push_back("\n#define SSAO_QUALITY_HIGH\n"); + ssao_modes.push_back("\n#define SSAO_QUALITY_ULTRA\n"); + ssao_modes.push_back("\n#define SSAO_QUALITY_LOW\n#define USE_HALF_SIZE\n"); + ssao_modes.push_back("\n#define USE_HALF_SIZE\n"); + ssao_modes.push_back("\n#define SSAO_QUALITY_HIGH\n#define USE_HALF_SIZE\n"); + ssao_modes.push_back("\n#define SSAO_QUALITY_ULTRA\n#define USE_HALF_SIZE\n"); + + ssao.gather_shader.initialize(ssao_modes); + + ssao.gather_shader_version = ssao.gather_shader.version_create(); + + for (int i = SSAO_GATHER_LOW; i <= SSAO_GATHER_ULTRA_HALF; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i - SSAO_GATHER_LOW)); + pipeline++; + } + } + { + Vector ssao_modes; + ssao_modes.push_back("\n#define MODE_FULL_SIZE\n"); + ssao_modes.push_back("\n"); + ssao_modes.push_back("\n#define MODE_UPSCALE\n"); + + ssao.blur_shader.initialize(ssao_modes); + + ssao.blur_shader_version = ssao.blur_shader.version_create(); + + for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_UPSCALE; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS)); + pipeline++; + } + } + + ERR_FAIL_COND(pipeline != SSAO_MAX); + } RD::SamplerState sampler; sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR; sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h index 77779f2c84f..7a7d127e383 100644 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h @@ -39,6 +39,9 @@ #include "servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h" #include "servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl.gen.h" #include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h" +#include "servers/visual/rasterizer_rd/shaders/ssao.glsl.gen.h" +#include "servers/visual/rasterizer_rd/shaders/ssao_blur.glsl.gen.h" +#include "servers/visual/rasterizer_rd/shaders/ssao_minify.glsl.gen.h" #include "servers/visual/rasterizer_rd/shaders/tonemap.glsl.gen.h" #include "servers/visual_server.h" @@ -71,7 +74,8 @@ class RasterizerEffectsRD { BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2), BLUR_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3), BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4), - BLUR_FLAG_FLIP_Y = (1 << 5) + BLUR_FLAG_FLIP_Y = (1 << 5), + BLUR_COPY_FORCE_LUMINANCE = (1 << 6) }; struct BlurPushConstant { @@ -265,6 +269,76 @@ class RasterizerEffectsRD { RID pipelines[BOKEH_MAX]; } bokeh; + enum SSAOMode { + SSAO_MINIFY_FIRST, + SSAO_MINIFY_MIPMAP, + SSAO_GATHER_LOW, + SSAO_GATHER_MEDIUM, + SSAO_GATHER_HIGH, + SSAO_GATHER_ULTRA, + SSAO_GATHER_LOW_HALF, + SSAO_GATHER_MEDIUM_HALF, + SSAO_GATHER_HIGH_HALF, + SSAO_GATHER_ULTRA_HALF, + SSAO_BLUR_PASS, + SSAO_BLUR_PASS_HALF, + SSAO_BLUR_UPSCALE, + SSAO_MAX + }; + + struct SSAOMinifyPushConstant { + float pixel_size[2]; + float z_far; + float z_near; + int32_t source_size[2]; + uint32_t orthogonal; + uint32_t pad; + }; + + struct SSAOGatherPushConstant { + int32_t screen_size[2]; + float z_far; + float z_near; + + uint32_t orthogonal; + float intensity_div_r6; + float radius; + float bias; + + float proj_info[4]; + float pixel_size[2]; + float proj_scale; + uint32_t pad; + }; + + struct SSAOBlurPushConstant { + float edge_sharpness; + int32_t filter_scale; + float z_far; + float z_near; + uint32_t orthogonal; + uint32_t pad[3]; + int32_t axis[2]; + int32_t screen_size[2]; + }; + + struct SSAO { + + SSAOMinifyPushConstant minify_push_constant; + SsaoMinifyShaderRD minify_shader; + RID minify_shader_version; + + SSAOGatherPushConstant gather_push_constant; + SsaoShaderRD gather_shader; + RID gather_shader_version; + + SSAOBlurPushConstant blur_push_constant; + SsaoBlurShaderRD blur_shader; + RID blur_shader_version; + + RID pipelines[SSAO_MAX]; + } ssao; + RID default_sampler; RID default_mipmap_sampler; RID index_buffer; @@ -283,7 +357,7 @@ 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 copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false, bool p_force_luminance = 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(), float p_auto_exposure_grey = 1.0); @@ -331,6 +405,8 @@ public: void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings); + void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness); + RasterizerEffectsRD(); ~RasterizerEffectsRD(); }; diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp index e7dafda072d..29aef6916e4 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -505,7 +505,7 @@ void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Mapuniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), 3); + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); } RasterizerSceneHighEndRD::MaterialData::~MaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { @@ -525,19 +525,54 @@ RasterizerStorageRD::MaterialData *RasterizerSceneHighEndRD::_create_material_fu return material_data; } -RasterizerSceneHighEndRD::RenderBufferDataForward::~RenderBufferDataForward() { +RasterizerSceneHighEndRD::RenderBufferDataHighEnd::~RenderBufferDataHighEnd() { clear(); } -void RasterizerSceneHighEndRD::RenderBufferDataForward::clear() { +void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_specular() { - if (color_fb.is_valid()) { - RD::get_singleton()->free(color_fb); - color_fb = RID(); + if (!specular.is_valid()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = width; + tf.height = height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + specular = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Vector fb; + fb.push_back(color); + fb.push_back(specular); + fb.push_back(depth); + + color_specular_fb = RD::get_singleton()->framebuffer_create(fb); } } -void RasterizerSceneHighEndRD::RenderBufferDataForward::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) { +void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() { + + if (specular.is_valid()) { + RD::get_singleton()->free(specular); + specular = RID(); + } + + color_specular_fb = RID(); + color_fb = RID(); + + if (normal_buffer.is_valid()) { + RD::get_singleton()->free(normal_buffer); + normal_buffer = RID(); + depth_normal_fb = RID(); + } + + if (roughness_buffer.is_valid()) { + RD::get_singleton()->free(roughness_buffer); + roughness_buffer = RID(); + depth_normal_roughness_fb = RID(); + } +} + +void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) { clear(); width = p_width; @@ -559,16 +594,54 @@ void RasterizerSceneHighEndRD::RenderBufferDataForward::configure(RID p_color_bu depth_fb = RD::get_singleton()->framebuffer_create(fb); } - { - Vector fb; - fb.push_back(p_color_buffer); +} - color_only_fb = RD::get_singleton()->framebuffer_create(fb); +void RasterizerSceneHighEndRD::_allocate_normal_texture(RenderBufferDataHighEnd *rb) { + if (rb->normal_buffer.is_valid()) { + return; } + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; + tf.width = rb->width; + tf.height = rb->height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + rb->normal_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + Vector fb; + fb.push_back(rb->depth); + fb.push_back(rb->normal_buffer); + rb->depth_normal_fb = RD::get_singleton()->framebuffer_create(fb); + + _render_buffers_clear_uniform_set(rb); +} + +void RasterizerSceneHighEndRD::_allocate_roughness_texture(RenderBufferDataHighEnd *rb) { + + if (rb->roughness_buffer.is_valid()) { + return; + } + + ERR_FAIL_COND(rb->normal_buffer.is_null()); + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = rb->width; + tf.height = rb->height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + rb->roughness_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + Vector fb; + fb.push_back(rb->depth); + fb.push_back(rb->normal_buffer); + fb.push_back(rb->roughness_buffer); + rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb); + + _render_buffers_clear_uniform_set(rb); } RasterizerSceneRD::RenderBufferData *RasterizerSceneHighEndRD::_create_render_buffer_data() { - return memnew(RenderBufferDataForward); + return memnew(RenderBufferDataHighEnd); } bool RasterizerSceneHighEndRD::free(RID p_rid) { @@ -658,15 +731,25 @@ void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, /// RENDERING /// -void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi) { +void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set) { RD::DrawListID draw_list = p_draw_list; RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; //global scope bindings - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_pass_uniform_set, 1); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_vec4_xform_uniform_set, 2); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, SCENE_UNIFORM_SET); + if (p_radiance_uniform_set.is_valid()) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_radiance_uniform_set, RADIANCE_UNIFORM_SET); + } else { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_radiance_uniform_set, RADIANCE_UNIFORM_SET); + } + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, view_dependant_uniform_set, VIEW_DEPENDANT_UNIFORM_SET); + if (p_render_buffers_uniform_set.is_valid()) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_render_buffers_uniform_set, RENDER_BUFFERS_UNIFORM_SET); + } else { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_render_buffers_uniform_set, RENDER_BUFFERS_UNIFORM_SET); + } + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_vec4_xform_uniform_set, TRANSFORMS_UNIFORM_SET); MaterialData *prev_material = nullptr; // ShaderData *prev_shader = nullptr; @@ -707,7 +790,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l case VS::INSTANCE_MESH: { primitive = storage->mesh_surface_get_primitive(e->instance->base, e->surface_index); if (e->instance->skeleton.is_valid()) { - xforms_uniform_set = storage->skeleton_get_3d_uniform_set(e->instance->skeleton, default_shader_rd, 2); + xforms_uniform_set = storage->skeleton_get_3d_uniform_set(e->instance->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET); } } break; case VS::INSTANCE_MULTIMESH: { @@ -715,7 +798,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l ERR_CONTINUE(!mesh.is_valid()); //should be a bug primitive = storage->mesh_surface_get_primitive(mesh, e->surface_index); - xforms_uniform_set = storage->multimesh_get_3d_uniform_set(e->instance->base, default_shader_rd, 2); + xforms_uniform_set = storage->multimesh_get_3d_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); } break; case VS::INSTANCE_IMMEDIATE: { @@ -821,14 +904,14 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l } if (xforms_uniform_set.is_valid() && prev_xforms_uniform_set != xforms_uniform_set) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, xforms_uniform_set, 2); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, xforms_uniform_set, TRANSFORMS_UNIFORM_SET); prev_xforms_uniform_set = xforms_uniform_set; } if (material != prev_material) { //update uniform set if (material->uniform_set.is_valid()) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material->uniform_set, 3); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material->uniform_set, MATERIAL_UNIFORM_SET); } prev_material = material; @@ -900,6 +983,7 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer scene_state.ubo.ambient_light_color_energy[3] = 1.0; scene_state.ubo.use_ambient_cubemap = false; scene_state.ubo.use_reflection_cubemap = false; + scene_state.ubo.ssao_enabled = false; } else if (is_environment(p_environment)) { @@ -947,6 +1031,16 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer scene_state.ubo.use_reflection_cubemap = false; } + scene_state.ubo.ssao_enabled = environment_is_ssao_enabled(p_environment); + scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_environment); + scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_environment); + + Color ao_color = environment_get_ao_color(p_environment); + scene_state.ubo.ao_color[0] = ao_color.r; + scene_state.ubo.ao_color[1] = ao_color.g; + scene_state.ubo.ao_color[2] = ao_color.b; + scene_state.ubo.ao_color[3] = ao_color.a; + } else { if (p_reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { @@ -1557,9 +1651,9 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig void RasterizerSceneHighEndRD::_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_camera_effects, 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 = NULL; + RenderBufferDataHighEnd *render_buffer = NULL; if (p_render_buffer.is_valid()) { - render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer); + render_buffer = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffer); } //first of all, make a new render pass @@ -1621,12 +1715,40 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor RID depth_framebuffer; RID alpha_framebuffer; + PassMode depth_pass_mode = PASS_MODE_DEPTH; + Vector depth_pass_clear; + if (render_buffer) { screen_pixel_size.width = 1.0 / render_buffer->width; screen_pixel_size.height = 1.0 / render_buffer->height; opaque_framebuffer = render_buffer->color_fb; - depth_framebuffer = render_buffer->depth_fb; + if (p_environment.is_valid() && environment_is_ssr_enabled(p_environment)) { + depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; + } else if (p_environment.is_valid() && environment_is_ssao_enabled(p_environment)) { + depth_pass_mode = PASS_MODE_DEPTH_NORMAL; + } + + switch (depth_pass_mode) { + case PASS_MODE_DEPTH: { + depth_framebuffer = render_buffer->depth_fb; + } break; + case PASS_MODE_DEPTH_NORMAL: { + _allocate_normal_texture(render_buffer); + depth_framebuffer = render_buffer->depth_normal_fb; + depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); + } break; + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { + _allocate_normal_texture(render_buffer); + _allocate_roughness_texture(render_buffer); + depth_framebuffer = render_buffer->depth_normal_roughness_fb; + depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); + depth_pass_clear.push_back(Color()); + } break; + default: { + }; + } + alpha_framebuffer = opaque_framebuffer; } else if (p_reflection_probe.is_valid()) { @@ -1660,7 +1782,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor render_list.clear(); _fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr); - RID radiance_cubemap; + RID radiance_uniform_set; bool draw_sky = false; Color clear_color; @@ -1687,7 +1809,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor case VS::ENV_BG_SKY: { RID sky = environment_get_sky(p_environment); if (sky.is_valid()) { - radiance_cubemap = sky_get_radiance_texture_rd(sky); + radiance_uniform_set = sky_get_radiance_uniform_set_rd(sky, radiance_uniform_set, RADIANCE_UNIFORM_SET); draw_sky = true; } } break; @@ -1708,7 +1830,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor clear_color = p_default_bg_color; } - _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap, p_shadow_atlas, p_reflection_atlas); + _setup_view_dependant_uniform_set(p_shadow_atlas, p_reflection_atlas); render_list.sort_by_key(false); @@ -1719,13 +1841,26 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor bool using_separate_specular = false; bool depth_pre_pass = depth_framebuffer.is_valid(); + RID render_buffers_uniform_set; + if (depth_pre_pass) { //depth pre pass RENDER_TIMESTAMP("Render Depth Pre-Pass"); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, PASS_MODE_DEPTH, render_buffer == nullptr); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, depth_pass_clear); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, radiance_uniform_set, RID()); RD::get_singleton()->draw_list_end(); } + + if (p_render_buffer.is_valid() && p_environment.is_valid() && environment_is_ssao_enabled(p_environment)) { + _process_ssao(p_render_buffer, p_environment, render_buffer->normal_buffer, p_cam_projection); + } + + if (p_render_buffer.is_valid()) { + //update the render buffers uniform set in case it changed + _update_render_buffers_uniform_set(p_render_buffer); + render_buffers_uniform_set = render_buffer->uniform_set; + } + RENDER_TIMESTAMP("Render Opaque Pass"); { @@ -1734,7 +1869,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor Vector c; c.push_back(clear_color.to_linear()); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set); RD::get_singleton()->draw_list_end(); } @@ -1772,7 +1907,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor { RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set); RD::get_singleton()->draw_list_end(); } @@ -1867,7 +2002,7 @@ void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase ** _fill_render_list(p_cull_result, p_cull_count, pass_mode, true); - _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), RID(), RID()); + _setup_view_dependant_uniform_set(RID(), RID()); RENDER_TIMESTAMP("Render Shadow"); @@ -1878,7 +2013,7 @@ void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase ** { //regular forward for now RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true, RID(), RID()); RD::get_singleton()->draw_list_end(); } } @@ -1901,7 +2036,7 @@ void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; _fill_render_list(p_cull_result, p_cull_count, pass_mode, true); - _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), RID(), RID()); + _setup_view_dependant_uniform_set(RID(), RID()); RENDER_TIMESTAMP("Render Material"); @@ -1918,14 +2053,22 @@ void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform clear.push_back(Color(0, 0, 0, 0)); clear.push_back(Color(0, 0, 0, 0)); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), RID()); RD::get_singleton()->draw_list_end(); } } +void RasterizerSceneHighEndRD::_base_uniforms_changed() { + + if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { + RD::get_singleton()->free(render_base_uniform_set); + } + render_base_uniform_set = RID(); +} + void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { - if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || gi_probe_slots_are_dirty()) { + if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); @@ -2059,69 +2202,37 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { uniforms.push_back(u); } - render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 0); + { + RD::Uniform u; + u.binding = 12; + u.type = RD::UNIFORM_TYPE_TEXTURE; + if (directional_shadow_get_texture().is_valid()) { + u.ids.push_back(directional_shadow_get_texture()); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + } + uniforms.push_back(u); + } - gi_probe_slots_make_not_dirty(); + render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, SCENE_UNIFORM_SET); } } -void RasterizerSceneHighEndRD::_setup_render_pass_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap, RID p_shadow_atlas, RID p_reflection_atlas) { +void RasterizerSceneHighEndRD::_setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas) { - if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) { - RD::get_singleton()->free(render_pass_uniform_set); + if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) { + RD::get_singleton()->free(view_dependant_uniform_set); } //default render buffer and scene state uniform set Vector uniforms; - { - RD::Uniform u; - u.binding = 0; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = p_depth_buffer.is_valid() ? p_depth_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); - u.ids.push_back(texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 1; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = p_color_buffer.is_valid() ? p_color_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); - u.ids.push_back(texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 2; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = p_normal_buffer.is_valid() ? p_normal_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL); - u.ids.push_back(texture); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.binding = 3; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = p_roughness_limit_buffer.is_valid() ? p_roughness_limit_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); - u.ids.push_back(texture); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.binding = 4; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = p_radiance_cubemap.is_valid() ? p_radiance_cubemap : storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); - u.ids.push_back(texture); - uniforms.push_back(u); - } { RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID(); RD::Uniform u; - u.binding = 5; + u.binding = 0; u.type = RD::UNIFORM_TYPE_TEXTURE; if (ref_texture.is_valid()) { u.ids.push_back(ref_texture); @@ -2133,7 +2244,7 @@ void RasterizerSceneHighEndRD::_setup_render_pass_uniform_set(RID p_depth_buffer { RD::Uniform u; - u.binding = 6; + u.binding = 1; u.type = RD::UNIFORM_TYPE_TEXTURE; RID texture; if (p_shadow_atlas.is_valid()) { @@ -2146,19 +2257,78 @@ void RasterizerSceneHighEndRD::_setup_render_pass_uniform_set(RID p_depth_buffer uniforms.push_back(u); } - { - RD::Uniform u; - u.binding = 7; - u.type = RD::UNIFORM_TYPE_TEXTURE; - if (directional_shadow_get_texture().is_valid()) { - u.ids.push_back(directional_shadow_get_texture()); - } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); - } - uniforms.push_back(u); - } + view_dependant_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, VIEW_DEPENDANT_UNIFORM_SET); +} - render_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 1); +void RasterizerSceneHighEndRD::_render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb) { + + if (!rb->uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) { + RD::get_singleton()->free(rb->uniform_set); + } + rb->uniform_set = RID(); +} + +void RasterizerSceneHighEndRD::_render_buffers_uniform_set_changed(RID p_render_buffers) { + + RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); + + _render_buffers_clear_uniform_set(rb); +} + +void RasterizerSceneHighEndRD::_update_render_buffers_uniform_set(RID p_render_buffers) { + + RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); + + if (rb->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) { + + Vector uniforms; + { + RD::Uniform u; + u.binding = 0; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = false && rb->depth.is_valid() ? rb->depth : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + u.ids.push_back(texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 1; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID bbt = render_buffers_get_back_buffer_texture(p_render_buffers); + RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = rb->normal_buffer.is_valid() ? rb->normal_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 3; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = rb->roughness_buffer.is_valid() ? rb->roughness_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 4; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID aot = render_buffers_get_ao_texture(p_render_buffers); + RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + rb->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET); + } } RasterizerSceneHighEndRD *RasterizerSceneHighEndRD::singleton = NULL; @@ -2246,8 +2416,8 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag Vector shader_versions; shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define ENABLE_WRITE_NORMAL_BUFFER\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define ENABLE_WRITE_NORMAL_ROUGHNESS_BUFFER\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL\n#define MODE_RENDER_ROUGHNESS\n"); shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); shader_versions.push_back(""); shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); @@ -2388,7 +2558,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.sampler_array_name = "material_samplers"; actions.base_texture_binding_index = 1; - actions.texture_layout_set = 3; + actions.texture_layout_set = MATERIAL_UNIFORM_SET; actions.base_uniform_string = "material."; actions.base_varying_index = 10; @@ -2445,7 +2615,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag u.binding = 0; uniforms.push_back(u); - default_vec4_xform_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 2); + default_vec4_xform_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, TRANSFORMS_UNIFORM_SET); } { @@ -2457,13 +2627,40 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag shadow_sampler = RD::get_singleton()->sampler_create(sampler); } + { + Vector uniforms; + + RD::Uniform u; + u.binding = 0; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + + default_radiance_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RADIANCE_UNIFORM_SET); + } + + { //render buffers + Vector uniforms; + for (int i = 0; i < 5; i++) { + RD::Uniform u; + u.binding = i; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = storage->texture_rd_get_default(i == 0 ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE : (i == 2 ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL : RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + default_render_buffers_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET); + } + cluster_builder.setup(16, 8, 24); } RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() { //clear base uniform set if still valid - if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) { - RD::get_singleton()->free(render_pass_uniform_set); + if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) { + RD::get_singleton()->free(view_dependant_uniform_set); } { diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h index ddc38fb4ca2..e4349919f68 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h @@ -39,6 +39,15 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { + enum { + SCENE_UNIFORM_SET = 0, + RADIANCE_UNIFORM_SET = 1, + VIEW_DEPENDANT_UNIFORM_SET = 2, + RENDER_BUFFERS_UNIFORM_SET = 3, + TRANSFORMS_UNIFORM_SET = 4, + MATERIAL_UNIFORM_SET = 5 + }; + /* Shader */ enum ShaderVersion { @@ -186,28 +195,44 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { /* Framebuffer */ - struct RenderBufferDataForward : public RenderBufferData { + struct RenderBufferDataHighEnd : public RenderBufferData { //for rendering, may be MSAAd RID color; RID depth; + RID specular; + RID normal_buffer; + RID roughness_buffer; RID depth_fb; + RID depth_normal_fb; + RID depth_normal_roughness_fb; RID color_fb; - RID color_only_fb; + RID color_specular_fb; int width, height; + void ensure_specular(); void clear(); virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa); - ~RenderBufferDataForward(); + RID uniform_set; + + ~RenderBufferDataHighEnd(); }; virtual RenderBufferData *_create_render_buffer_data(); + void _allocate_normal_texture(RenderBufferDataHighEnd *rb); + void _allocate_roughness_texture(RenderBufferDataHighEnd *rb); RID shadow_sampler; RID render_base_uniform_set; - RID render_pass_uniform_set; + RID view_dependant_uniform_set; + + virtual void _base_uniforms_changed(); + void _render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb); + virtual void _render_buffers_uniform_set_changed(RID p_render_buffers); + void _update_render_base_uniform_set(); - void _setup_render_pass_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap, RID p_shadow_atlas, RID p_reflection_atlas); + void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas); + void _update_render_buffers_uniform_set(RID p_render_buffers); /* Scene State UBO */ @@ -318,6 +343,13 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { float dual_paraboloid_side; float z_far; float z_near; + + uint32_t ssao_enabled; + float ssao_light_affect; + float ssao_ao_affect; + uint32_t pad_ssao; + + float ao_color[4]; }; UBO ubo; @@ -503,6 +535,8 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { RID wireframe_material_shader; RID wireframe_material; RID default_shader_rd; + RID default_radiance_uniform_set; + RID default_render_buffers_uniform_set; RID default_vec4_xform_buffer; RID default_vec4_xform_uniform_set; @@ -527,7 +561,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform); void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth); - void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi); + void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set); _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index); _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index); diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp index c9f3f696ebd..41acd05a305 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp @@ -347,6 +347,30 @@ RID RasterizerSceneRD::sky_get_radiance_texture_rd(RID p_sky) const { return sky->radiance; } +RID RasterizerSceneRD::sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const { + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND_V(!sky, RID()); + + if (sky->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(sky->uniform_set)) { + + sky->uniform_set = RID(); + if (sky->radiance.is_valid()) { + Vector uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + u.ids.push_back(sky->radiance); + uniforms.push_back(u); + } + + sky->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + } + + return sky->uniform_set; +} + RID RasterizerSceneRD::environment_create() { return environment_owner.make_rid(Environent()); @@ -387,7 +411,7 @@ void RasterizerSceneRD::environment_set_canvas_max_layer(RID p_env, int p_max_la ERR_FAIL_COND(!env); env->canvas_max_layer = p_max_layer; } -void RasterizerSceneRD::environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, VS::EnvironmentReflectionSource p_reflection_source) { +void RasterizerSceneRD::environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, VS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color) { Environent *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->ambient_light = p_color; @@ -395,6 +419,7 @@ void RasterizerSceneRD::environment_set_ambient_light(RID p_env, const Color &p_ env->ambient_light_energy = p_energy; env->ambient_sky_contribution = p_sky_contribution; env->reflection_source = p_reflection_source; + env->ao_color = p_ao_color; } VS::EnvironmentBG RasterizerSceneRD::environment_get_background(RID p_env) const { @@ -458,6 +483,12 @@ VS::EnvironmentReflectionSource RasterizerSceneRD::environment_get_reflection_so return env->reflection_source; } +Color RasterizerSceneRD::environment_get_ao_color(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, Color()); + return env->ao_color; +} + void RasterizerSceneRD::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) { Environent *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -491,6 +522,50 @@ void RasterizerSceneRD::environment_set_glow(RID p_env, bool p_enable, int p_lev env->glow_bicubic_upscale = p_bicubic_upscale; } +void RasterizerSceneRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) { + + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->ssao_enabled = p_enable; + env->ssao_radius = p_radius; + env->ssao_intensity = p_intensity; + env->ssao_bias = p_bias; + env->ssao_direct_light_affect = p_light_affect; + env->ssao_ao_channel_affect = p_ao_channel_affect; + env->ssao_blur = p_blur; +} + +void RasterizerSceneRD::environment_set_ssao_quality(VS::EnvironmentSSAOQuality p_quality, bool p_half_size) { + ssao_quality = p_quality; + ssao_half_size = p_half_size; +} + +bool RasterizerSceneRD::environment_is_ssao_enabled(RID p_env) const { + + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, false); + return env->ssao_enabled; +} + +float RasterizerSceneRD::environment_get_ssao_ao_affect(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, false); + return env->ssao_ao_channel_affect; +} +float RasterizerSceneRD::environment_get_ssao_light_affect(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, false); + return env->ssao_direct_light_affect; +} + +bool RasterizerSceneRD::environment_is_ssr_enabled(RID p_env) const { + + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, false); + return false; +} + bool RasterizerSceneRD::is_environment(RID p_env) const { return environment_owner.owns(p_env); } @@ -1065,6 +1140,8 @@ void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) { fb.push_back(directional_shadow.depth); directional_shadow.fb = RD::get_singleton()->framebuffer_create(fb); } + + _base_uniforms_changed(); } void RasterizerSceneRD::set_directional_shadow_count(int p_count) { @@ -1725,8 +1802,9 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc } gi_probe->last_probe_data_version = data_version; - gi_probe_slots_dirty = true; p_update_light_instances = true; //just in case + + _base_uniforms_changed(); } // UDPDATE TIME @@ -2183,14 +2261,6 @@ const Vector &RasterizerSceneRD::gi_probe_get_slots() const { return gi_probe_slots; } -bool RasterizerSceneRD::gi_probe_slots_are_dirty() const { - return gi_probe_slots_dirty; -} - -void RasterizerSceneRD::gi_probe_slots_make_not_dirty() { - gi_probe_slots_dirty = false; -} - RasterizerSceneRD::GIProbeQuality RasterizerSceneRD::gi_probe_get_quality() const { return gi_probe_quality; } @@ -2323,6 +2393,91 @@ void RasterizerSceneRD::_free_render_buffer_data(RenderBuffers *rb) { RD::get_singleton()->free(rb->luminance.current); rb->luminance.current = RID(); } + + if (rb->ssao.ao[0].is_valid()) { + RD::get_singleton()->free(rb->ssao.depth); + RD::get_singleton()->free(rb->ssao.ao[0]); + if (rb->ssao.ao[1].is_valid()) { + RD::get_singleton()->free(rb->ssao.ao[1]); + } + if (rb->ssao.ao_full.is_valid()) { + RD::get_singleton()->free(rb->ssao.ao_full); + } + + rb->ssao.depth = RID(); + rb->ssao.ao[0] = RID(); + rb->ssao.ao[1] = RID(); + rb->ssao.ao_full = RID(); + rb->ssao.depth_slices.clear(); + } +} + +void RasterizerSceneRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) { + + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + + Environent *env = environment_owner.getornull(p_environment); + ERR_FAIL_COND(!env); + + if (rb->ssao.ao[0].is_valid() && rb->ssao.ao_full.is_valid() != ssao_half_size) { + RD::get_singleton()->free(rb->ssao.depth); + RD::get_singleton()->free(rb->ssao.ao[0]); + if (rb->ssao.ao[1].is_valid()) { + RD::get_singleton()->free(rb->ssao.ao[1]); + } + if (rb->ssao.ao_full.is_valid()) { + RD::get_singleton()->free(rb->ssao.ao_full); + } + + rb->ssao.depth = RID(); + rb->ssao.ao[0] = RID(); + rb->ssao.ao[1] = RID(); + rb->ssao.ao_full = RID(); + rb->ssao.depth_slices.clear(); + } + + if (!rb->ssao.ao[0].is_valid()) { + //allocate depth slices + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + tf.width = rb->width / 2; + tf.height = rb->height / 2; + tf.mipmaps = Image::get_image_required_mipmaps(tf.width, tf.height, Image::FORMAT_RF) + 1; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + rb->ssao.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); + for (uint32_t i = 0; i < tf.mipmaps; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.depth, 0, i); + rb->ssao.depth_slices.push_back(slice); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = ssao_half_size ? rb->width / 2 : rb->width; + tf.height = ssao_half_size ? rb->height / 2 : rb->height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + rb->ssao.ao[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + rb->ssao.ao[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + + if (ssao_half_size) { + //upsample texture + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = rb->width; + tf.height = rb->height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + rb->ssao.ao_full = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + + _render_buffers_uniform_set_changed(p_render_buffers); + } + + storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, Size2i(rb->width, rb->height), rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao[0], rb->ssao.ao_full.is_valid(), rb->ssao.ao[1], rb->ssao.ao_full, env->ssao_intensity, env->ssao_radius, env->ssao_bias, p_projection, ssao_quality, env->ssao_blur, env->ssao_blur_edge_sharpness); } void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection) { @@ -2340,6 +2495,7 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu if (rb->blur[0].texture.is_null()) { _allocate_blur_textures(rb); + _render_buffers_uniform_set_changed(p_render_buffers); } float bokeh_size = camfx->dof_blur_amount * 64.0; @@ -2350,6 +2506,7 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu if (rb->luminance.current.is_null()) { _allocate_luminance_textures(rb); + _render_buffers_uniform_set_changed(p_render_buffers); } bool set_immediate = env->auto_exposure_version != rb->auto_exposure_version; @@ -2372,6 +2529,7 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu if (rb->blur[0].texture.is_null()) { _allocate_blur_textures(rb); + _render_buffers_uniform_set_changed(p_render_buffers); } for (int i = 0; i < VS::MAX_GLOW_LEVELS; i++) { @@ -2456,7 +2614,7 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s 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)); + effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2), false, true); } } @@ -2465,7 +2623,7 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s 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)); + effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2), false, true); } } @@ -2473,19 +2631,34 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s if (rb->luminance.current.is_valid()) { Size2 rtsize = storage->render_target_get_size(rb->render_target); - effects->copy_to_rect(rb->luminance.current, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8)); + effects->copy_to_rect(rb->luminance.current, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true); } } + + if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ssao.ao[0].is_valid()) { + Size2 rtsize = storage->render_target_get_size(rb->render_target); + RID ao_buf = rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0]; + effects->copy_to_rect(ao_buf, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); + } } 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? + if (!rb->blur[0].texture.is_valid()) { + return RID(); //not valid at the moment + } return rb->blur[0].texture; } +RID RasterizerSceneRD::render_buffers_get_ao_texture(RID p_render_buffers) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, RID()); + + return rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0]; +} + 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); @@ -2516,6 +2689,7 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren } rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa); + _render_buffers_uniform_set_changed(p_render_buffers); } int RasterizerSceneRD::get_roughness_layers() const { @@ -2921,6 +3095,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { camera_effects_set_dof_blur_bokeh_shape(VS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_shape")))); camera_effects_set_dof_blur_quality(VS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/filters/depth_of_field_use_jitter")); + environment_set_ssao_quality(VS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size")); } RasterizerSceneRD::~RasterizerSceneRD() { diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h index c6d13e4d34c..cb917482ccf 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h @@ -62,6 +62,11 @@ protected: RenderBufferData *render_buffers_get_data(RID p_render_buffers); + virtual void _base_uniforms_changed() = 0; + virtual void _render_buffers_uniform_set_changed(RID p_render_buffers) = 0; + + void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection); + private: VS::ViewportDebugDraw debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED; double time_step = 0; @@ -94,6 +99,7 @@ private: /* SKY */ struct Sky { RID radiance; + RID uniform_set; int radiance_size = 256; VS::SkyMode mode = VS::SKY_MODE_QUALITY; RID panorama; @@ -266,7 +272,6 @@ private: bool gi_probe_use_anisotropy = false; GIProbeQuality gi_probe_quality = GIPROBE_QUALITY_MEDIUM; - bool gi_probe_slots_dirty = true; Vector gi_probe_slots; @@ -455,6 +460,7 @@ private: float ambient_light_energy = 1.0; float ambient_sky_contribution = 1.0; VS::EnvironmentReflectionSource reflection_source = VS::ENV_REFLECTION_SOURCE_BG; + Color ao_color; /// Tonemap @@ -481,8 +487,22 @@ private: float glow_hdr_luminance_cap = 12.0; float glow_hdr_bleed_scale = 2.0; bool glow_bicubic_upscale = false; + + /// SSAO + + bool ssao_enabled = false; + float ssao_radius = 1; + float ssao_intensity = 1; + float ssao_bias = 0.01; + float ssao_direct_light_affect = 0.0; + float ssao_ao_channel_affect = 0.0; + float ssao_blur_edge_sharpness = 4.0; + VS::EnvironmentSSAOBlur ssao_blur = VS::ENV_SSAO_BLUR_3x3; }; + VS::EnvironmentSSAOQuality ssao_quality = VS::ENV_SSAO_QUALITY_MEDIUM; + bool ssao_half_size = false; + static uint64_t auto_exposure_counter; mutable RID_Owner environment_owner; @@ -546,6 +566,13 @@ private: Vector reduce; RID current; } luminance; + + struct SSAO { + RID depth; + Vector depth_slices; + RID ao[2]; + RID ao_full; //when using half-size + } ssao; }; mutable RID_Owner render_buffers_owner; @@ -606,6 +633,7 @@ public: RID sky_get_panorama_texture_rd(RID p_sky) const; RID sky_get_radiance_texture_rd(RID p_sky) const; + RID sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const; /* ENVIRONMENT API */ @@ -618,7 +646,7 @@ public: void environment_set_bg_color(RID p_env, const Color &p_color); void environment_set_bg_energy(RID p_env, float p_energy); void environment_set_canvas_max_layer(RID p_env, int p_max_layer); - void environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient = VS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, VS::EnvironmentReflectionSource p_reflection_source = VS::ENV_REFLECTION_SOURCE_BG); + void environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient = VS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, VS::EnvironmentReflectionSource p_reflection_source = VS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()); VS::EnvironmentBG environment_get_background(RID p_env) const; RID environment_get_sky(RID p_env) const; @@ -632,6 +660,7 @@ public: float environment_get_ambient_light_ambient_energy(RID p_env) const; float environment_get_ambient_sky_contribution(RID p_env) const; VS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const; + Color environment_get_ao_color(RID p_env) const; bool is_environment(RID p_env) const; @@ -640,7 +669,12 @@ public: 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, bool p_roughness) {} - 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_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness); + void environment_set_ssao_quality(VS::EnvironmentSSAOQuality p_quality, bool p_half_size); + bool environment_is_ssao_enabled(RID p_env) const; + float environment_get_ssao_ao_affect(RID p_env) const; + float environment_get_ssao_light_affect(RID p_env) const; + bool environment_is_ssr_enabled(RID p_env) const; 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); void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {} @@ -869,8 +903,6 @@ public: } const Vector &gi_probe_get_slots() const; - bool gi_probe_slots_are_dirty() const; - void gi_probe_slots_make_not_dirty(); _FORCE_INLINE_ bool gi_probe_is_anisotropic() const { return gi_probe_use_anisotropy; } @@ -879,6 +911,7 @@ 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_ao_texture(RID p_render_buffers); RID render_buffers_get_back_buffer_texture(RID p_render_buffers); 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_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp index 2d4675cfb32..cab501acb88 100644 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp @@ -2052,7 +2052,7 @@ AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) { AABB aabb; - for (int i = 0; i < mesh->surface_count; i++) { + for (uint32_t i = 0; i < mesh->surface_count; i++) { AABB laabb; if ((mesh->surfaces[i]->format & VS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) { diff --git a/servers/visual/rasterizer_rd/shaders/SCsub b/servers/visual/rasterizer_rd/shaders/SCsub index 6151d9bd9ff..98c14144e91 100644 --- a/servers/visual/rasterizer_rd/shaders/SCsub +++ b/servers/visual/rasterizer_rd/shaders/SCsub @@ -16,3 +16,6 @@ if 'RD_GLSL' in env['BUILDERS']: env.RD_GLSL('giprobe_sdf.glsl'); env.RD_GLSL('luminance_reduce.glsl'); env.RD_GLSL('bokeh_dof.glsl'); + env.RD_GLSL('ssao.glsl'); + env.RD_GLSL('ssao_minify.glsl'); + env.RD_GLSL('ssao_blur.glsl'); diff --git a/servers/visual/rasterizer_rd/shaders/blur.glsl b/servers/visual/rasterizer_rd/shaders/blur.glsl index ae4cedec673..03456dc97e5 100644 --- a/servers/visual/rasterizer_rd/shaders/blur.glsl +++ b/servers/visual/rasterizer_rd/shaders/blur.glsl @@ -279,6 +279,9 @@ void main() { #ifdef MODE_SIMPLE_COPY vec4 color = texture(source_color, uv_interp, 0.0); + if (bool(blur.flags & FLAG_COPY_FORCE_LUMINANCE)) { + color.rgb = vec3(max(max(color.r,color.g),color.b)); + } frag_color = color; #endif @@ -286,5 +289,6 @@ void main() { vec4 color = texture(source_color, uv_interp, 0.0); float ssao = texture(source_ssao, uv_interp, 0.0).r; frag_color = vec4(mix(color.rgb, color.rgb * mix(blur.ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0); + #endif } diff --git a/servers/visual/rasterizer_rd/shaders/blur_inc.glsl b/servers/visual/rasterizer_rd/shaders/blur_inc.glsl index b6bfe13b956..a008e001028 100644 --- a/servers/visual/rasterizer_rd/shaders/blur_inc.glsl +++ b/servers/visual/rasterizer_rd/shaders/blur_inc.glsl @@ -4,6 +4,7 @@ #define FLAG_DOF_NEAR_FIRST_TAP (1 << 3) #define FLAG_GLOW_FIRST_PASS (1 << 4) #define FLAG_FLIP_Y (1 << 5) +#define FLAG_COPY_FORCE_LUMINANCE (1 << 6) layout(push_constant, binding = 1, std430) uniform Blur { vec4 section; diff --git a/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl b/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl index 7b36f240103..66ce4b466fa 100644 --- a/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl +++ b/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl @@ -53,7 +53,7 @@ layout(location = 6) out vec3 binormal_interp; #endif #ifdef USE_MATERIAL_UNIFORMS -layout(set = 3, binding = 0, std140) uniform MaterialUniforms{ +layout(set = 5, binding = 0, std140) uniform MaterialUniforms{ /* clang-format off */ MATERIAL_UNIFORMS /* clang-format on */ @@ -316,7 +316,7 @@ layout(location = 8) in float dp_clip; #define projection_matrix scene_data.projection_matrix #ifdef USE_MATERIAL_UNIFORMS -layout(set = 3, binding = 0, std140) uniform MaterialUniforms{ +layout(set = 5, binding = 0, std140) uniform MaterialUniforms{ /* clang-format off */ MATERIAL_UNIFORMS /* clang-format on */ @@ -341,6 +341,12 @@ layout(location = 4) out float depth_output_buffer; #endif +#ifdef MODE_RENDER_NORMAL +layout(location = 0) out vec4 normal_output_buffer; +#ifdef MODE_RENDER_ROUGHNESS +layout(location = 1) out float roughness_output_buffer; +#endif //MODE_RENDER_ROUGHNESS +#endif //MODE_RENDER_NORMAL #else // RENDER DEPTH #ifdef MODE_MULTIPLE_RENDER_TARGETS @@ -1145,7 +1151,7 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 ao = 1.0 - min(1.0, ao); - light *= mix(1.0, ao, gi_probes.data[index].ambient_occlusion); + light = mix(scene_data.ao_color.rgb,light,mix(1.0, ao, gi_probes.data[index].ambient_occlusion)); } out_diff += vec4(light * blend, blend); @@ -1236,7 +1242,7 @@ void main() { float normaldepth = 1.0; - vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size; + vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center float sss_strength = 0.0; @@ -1633,18 +1639,44 @@ FRAGMENT_SHADER_CODE emission_output_buffer.a = 0.0; #endif +#ifdef MODE_RENDER_NORMAL + normal_output_buffer = vec4(normal * 0.5 + 0.5,0.0); +#ifdef MODE_RENDER_ROUGHNESS + roughness_output_buffer = roughness; +#endif //MODE_RENDER_ROUGHNESS +#endif //MODE_RENDER_NORMAL + //nothing happens, so a tree-ssa optimizer will result in no fragment shader :) #else specular_light *= scene_data.reflection_multiplier; ambient_light *= albedo; //ambient must be multiplied by albedo at the end +//ambient occlusion #if defined(AO_USED) - ambient_light *= ao; + + if (scene_data.ssao_enabled && scene_data.ssao_ao_affect > 0.0) { + float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]),screen_uv).r; + ao = mix(ao,min(ao,ssao),scene_data.ssao_ao_affect); + ao_light_affect = mix(ao_light_affect,max(ao_light_affect,scene_data.ssao_light_affect),scene_data.ssao_ao_affect); + } + + ambient_light = mix(scene_data.ao_color.rgb,ambient_light,ao); ao_light_affect = mix(1.0, ao, ao_light_affect); - specular_light *= ao_light_affect; - diffuse_light *= ao_light_affect; -#endif + specular_light = mix(scene_data.ao_color.rgb,specular_light,ao_light_affect); + diffuse_light = mix(scene_data.ao_color.rgb,diffuse_light,ao_light_affect); + +#else + + if (scene_data.ssao_enabled) { + float ao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]),screen_uv).r; + ambient_light = mix(scene_data.ao_color.rgb,ambient_light,ao); + float ao_light_affect = mix(1.0, ao,scene_data.ssao_light_affect); + specular_light = mix(scene_data.ao_color.rgb,specular_light,ao_light_affect); + diffuse_light = mix(scene_data.ao_color.rgb,diffuse_light,ao_light_affect); + } + +#endif // AO_USED // base color remapping diffuse_light *= 1.0 - metallic; // TODO: avoid all diffuse and ambient light calculations when metallic == 1 up to this point diff --git a/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl index 6ad5559b082..5504d0fc2f9 100644 --- a/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl +++ b/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl @@ -60,6 +60,13 @@ layout(set = 0, binding = 3, std140) uniform SceneData { float z_far; float z_near; + bool ssao_enabled; + float ssao_light_affect; + float ssao_ao_affect; + uint pad_ssao; + + vec4 ao_color; + #if 0 vec4 ambient_light_color; vec4 bg_color; @@ -211,33 +218,41 @@ layout(set = 0, binding = 11, std430) buffer ClusterData { uint indices[]; } cluster_data; -/* Set 1, Scene data that changes per render pass */ +layout(set = 0, binding = 12) uniform texture2D directional_shadow_atlas; -layout(set = 1, binding = 0) uniform texture2D depth_buffer; -layout(set = 1, binding = 1) uniform texture2D color_buffer; -layout(set = 1, binding = 2) uniform texture2D normal_buffer; -layout(set = 1, binding = 3) uniform texture2D roughness_limit; +// decal atlas + +/* Set 1, Radiance */ #ifdef USE_RADIANCE_CUBEMAP_ARRAY -layout(set = 1, binding = 4) uniform textureCubeArray radiance_cubemap; +layout(set = 1, binding = 0) uniform textureCubeArray radiance_cubemap; #else -layout(set = 1, binding = 4) uniform textureCube radiance_cubemap; +layout(set = 1, binding = 0) uniform textureCube radiance_cubemap; #endif -layout(set = 1, binding = 5) uniform textureCubeArray reflection_atlas; -layout(set = 1, binding = 6) uniform texture2D shadow_atlas; +/* Set 2, Reflection and Shadow Atlases (view dependant) */ -layout(set = 1, binding = 7) uniform texture2D directional_shadow_atlas; +layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas; -/* Set 2 Skeleton & Instancing (Multimesh) */ +layout(set = 2, binding = 1) uniform texture2D shadow_atlas; -layout(set = 2, binding = 0, std430) buffer Transforms { +/* Set 1, Render Buffers */ + +layout(set = 3, binding = 0) uniform texture2D depth_buffer; +layout(set = 3, binding = 1) uniform texture2D color_buffer; +layout(set = 3, binding = 2) uniform texture2D normal_buffer; +layout(set = 3, binding = 3) uniform texture2D roughness_buffer; +layout(set = 3, binding = 4) uniform texture2D ao_buffer; + +/* Set 4 Skeleton & Instancing (Multimesh) */ + +layout(set = 4, binding = 0, std430) buffer Transforms { vec4 data[]; } transforms; -/* Set 3 User Material */ +/* Set 5 User Material */ diff --git a/servers/visual/rasterizer_rd/shaders/ssao.glsl b/servers/visual/rasterizer_rd/shaders/ssao.glsl new file mode 100644 index 00000000000..95a5c41d399 --- /dev/null +++ b/servers/visual/rasterizer_rd/shaders/ssao.glsl @@ -0,0 +1,257 @@ +/* clang-format off */ +[compute] +/* clang-format on */ +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#define TWO_PI 6.283185307179586476925286766559 + +#ifdef SSAO_QUALITY_HIGH +#define NUM_SAMPLES (20) +#endif + +#ifdef SSAO_QUALITY_ULTRA +#define NUM_SAMPLES (48) +#endif + +#ifdef SSAO_QUALITY_LOW +#define NUM_SAMPLES (8) +#endif + +#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH) && !defined(SSAO_QUALITY_ULTRA) +#define NUM_SAMPLES (12) +#endif + +// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower +// miplevel to maintain reasonable spatial locality in the cache +// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing. +// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively +#define LOG_MAX_OFFSET (3) + +// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp +#define MAX_MIP_LEVEL (4) + +// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent +// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9 + +const int ROTATIONS[] = int[]( + 1, 1, 2, 3, 2, 5, 2, 3, 2, + 3, 3, 5, 5, 3, 4, 7, 5, 5, 7, + 9, 8, 5, 5, 7, 7, 7, 8, 5, 8, + 11, 12, 7, 10, 13, 8, 11, 8, 7, 14, + 11, 11, 13, 12, 13, 19, 17, 13, 11, 18, + 19, 11, 11, 14, 17, 21, 15, 16, 17, 18, + 13, 17, 11, 17, 19, 18, 25, 18, 19, 19, + 29, 21, 19, 27, 31, 29, 21, 18, 17, 29, + 31, 31, 23, 18, 25, 26, 25, 23, 19, 34, + 19, 27, 21, 25, 39, 29, 17, 21, 27); +/* clang-format on */ + +//#define NUM_SPIRAL_TURNS (7) +const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1]; + +layout(set = 0, binding = 0) uniform sampler2D source_depth_mipmaps; +layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_image; + +#ifndef USE_HALF_SIZE +layout(set = 2, binding = 0) uniform sampler2D source_depth; +#endif + +layout(set = 3, binding = 0) uniform sampler2D source_normal; + +layout(push_constant, binding = 1, std430) uniform Params { + ivec2 screen_size; + float z_far; + float z_near; + + bool orthogonal; + float intensity_div_r6; + float radius; + float bias; + + vec4 proj_info; + vec2 pixel_size; + float proj_scale; + uint pad; + +} params; + + +vec3 reconstructCSPosition(vec2 S, float z) { + if (params.orthogonal) { + return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z); + } else { + return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z); + } +} + +vec3 getPosition(ivec2 ssP) { + vec3 P; +#ifdef USE_HALF_SIZE + P.z = texelFetch(source_depth_mipmaps, ssP, 0).r; + P.z = -P.z; +#else + P.z = texelFetch(source_depth, ssP, 0).r; + + P.z = P.z * 2.0 - 1.0; + if (params.orthogonal) { + P.z = ((P.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + P.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - P.z * (params.z_far - params.z_near)); + } + P.z = -P.z; +#endif + // Offset to pixel center + P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); + return P; +} + +/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */ +vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR) { + // Radius relative to ssR + float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES)); + float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle; + + ssR = alpha; + return vec2(cos(angle), sin(angle)); +} + +/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */ +vec3 getOffsetPosition(ivec2 ssP, float ssR) { + // Derivation: + // mipLevel = floor(log(ssR / MAX_OFFSET)); + + int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL); + + vec3 P; + + // We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map. + // Manually clamp to the texture size because texelFetch bypasses the texture unit + ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (params.screen_size >> mipLevel) - ivec2(1)); + +#ifdef USE_HALF_SIZE + P.z = texelFetch(source_depth_mipmaps, mipP, mipLevel).r; + P.z = -P.z; +#else + if (mipLevel < 1) { + //read from depth buffer + P.z = texelFetch(source_depth, mipP, 0).r; + P.z = P.z * 2.0 - 1.0; + if (params.orthogonal) { + P.z = ((P.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + P.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - P.z * (params.z_far - params.z_near)); + } + P.z = -P.z; + + } else { + //read from mipmaps + P.z = texelFetch(source_depth_mipmaps, mipP, mipLevel - 1).r; + P.z = -P.z; + } +#endif + + // Offset to pixel center + P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); + + + return P; +} + +/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds + to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius + + Note that units of H() in the HPG12 paper are meters, not + unitless. The whole falloff/sampling function is therefore + unitless. In this implementation, we factor out (9 / radius). + + Four versions of the falloff function are implemented below +*/ +float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in float p_radius, in int tapIndex, in float randomPatternRotationAngle) { + // Offset on the unit disk, spun for this pixel + float ssR; + vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR); + ssR *= ssDiskRadius; + + ivec2 ssP = ivec2(ssR * unitOffset) + ssC; + + if (any(lessThan(ssP,ivec2(0))) || any(greaterThanEqual(ssP,params.screen_size))) { + return 0.0; + } + + // The occluding point in camera space + vec3 Q = getOffsetPosition(ssP, ssR); + + vec3 v = Q - C; + + float vv = dot(v, v); + float vn = dot(v, n_C); + + const float epsilon = 0.01; + float radius2 = p_radius * p_radius; + + // A: From the HPG12 paper + // Note large epsilon to avoid overdarkening within cracks + //return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6; + + // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] + float f = max(radius2 - vv, 0.0); + return f * f * f * max((vn - params.bias) / (epsilon + vv), 0.0); + + // C: Medium contrast (which looks better at high radii), no division. Note that the + // contribution still falls off with radius^2, but we've adjusted the rate in a way that is + // more computationally efficient and happens to be aesthetically pleasing. + // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0); + + // D: Low contrast, no division operation + // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0); +} + +void main() { + // Pixel being shaded + ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThan(ssC,params.screen_size))) { //too large, do nothing + return; + } + + // World space point being shaded + vec3 C = getPosition(ssC); + + + +#ifdef USE_HALF_SIZE + vec3 n_C = texelFetch(source_normal,ssC<<1,0).xyz * 2.0 - 1.0; +#else + vec3 n_C = texelFetch(source_normal,ssC,0).xyz * 2.0 - 1.0; +#endif + n_C = normalize(n_C); + n_C.y = -n_C.y; //because this code reads flipped + + + + // Hash function used in the HPG12 AlchemyAO paper + float randomPatternRotationAngle = mod(float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10), TWO_PI); + + // Reconstruct normals from positions. These will lead to 1-pixel black lines + // at depth discontinuities, however the blur will wipe those out so they are not visible + // in the final image. + + // Choose the screen-space sample radius + // proportional to the projected area of the sphere + + float ssDiskRadius = -params.proj_scale * params.radius; + if (!params.orthogonal) { + ssDiskRadius = -params.proj_scale * params.radius / C.z; + } + float sum = 0.0; + for (int i = 0; i < NUM_SAMPLES; ++i) { + sum += sampleAO(ssC, C, n_C, ssDiskRadius, params.radius, i, randomPatternRotationAngle); + } + + float A = max(0.0, 1.0 - sum * params.intensity_div_r6 * (5.0 / float(NUM_SAMPLES))); + + imageStore(dest_image,ssC,vec4(A)); +} diff --git a/servers/visual/rasterizer_rd/shaders/ssao_blur.glsl b/servers/visual/rasterizer_rd/shaders/ssao_blur.glsl new file mode 100644 index 00000000000..51ecef9bd99 --- /dev/null +++ b/servers/visual/rasterizer_rd/shaders/ssao_blur.glsl @@ -0,0 +1,163 @@ +/* clang-format off */ +[compute] +/* clang-format on */ + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + + +layout(set = 0, binding = 0) uniform sampler2D source_ssao; +layout(set = 1, binding = 0) uniform sampler2D source_depth; +#ifdef MODE_UPSCALE +layout(set = 2, binding = 0) uniform sampler2D source_depth_mipmaps; +#endif + +layout(r8, set = 3, binding = 0) uniform restrict writeonly image2D dest_image; + +////////////////////////////////////////////////////////////////////////////////////////////// +// Tunable Parameters: + +layout(push_constant, binding = 1, std430) uniform Params { + float edge_sharpness; /** Increase to make depth edges crisper. Decrease to reduce flicker. */ + int filter_scale; + float z_far; + float z_near; + bool orthogonal; + uint pad0; + uint pad1; + uint pad2; + ivec2 axis; /** (1, 0) or (0, 1) */ + ivec2 screen_size; +} params; + + + +/** Filter radius in pixels. This will be multiplied by SCALE. */ +#define R (4) + +////////////////////////////////////////////////////////////////////////////////////////////// + +// Gaussian coefficients +const float gaussian[R + 1] = + //float[](0.356642, 0.239400, 0.072410, 0.009869); + //float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0 + float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0 +//float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0 + + + + +void main() { + + // Pixel being shaded + ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThan(ssC,params.screen_size))) { //too large, do nothing + return; + } + +#ifdef MODE_UPSCALE + + //closest one should be the same pixel, but check nearby just in case + float depth = texelFetch(source_depth, ssC, 0).r; + + depth = depth * 2.0 - 1.0; + if (params.orthogonal) { + depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); + } + + vec2 pixel_size = 1.0 / vec2(params.screen_size); + vec2 closest_uv = vec2(ssC) * pixel_size + pixel_size * 0.5; + vec2 from_uv = closest_uv; + vec2 ps2 = pixel_size;// * 2.0; + + float closest_depth = abs(textureLod(source_depth_mipmaps,closest_uv,0.0).r-depth); + + vec2 offsets[4]=vec2[](vec2(ps2.x,0),vec2(-ps2.x,0),vec2(0,ps2.y),vec2(0,-ps2.y)); + for(int i=0;i<4;i++) { + vec2 neighbour = from_uv + offsets[i]; + float neighbour_depth = abs(textureLod(source_depth_mipmaps,neighbour,0.0).r-depth); + if (neighbour_depth < closest_depth ) { + closest_uv = neighbour; + closest_depth = neighbour_depth; + } + } + + float visibility = textureLod(source_ssao,closest_uv,0.0).r; + imageStore(dest_image,ssC,vec4(visibility)); +#else + + float depth = texelFetch(source_depth, ssC, 0).r; + +#ifdef MODE_FULL_SIZE + depth = depth * 2.0 - 1.0; + + if (params.orthogonal) { + depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); + } + +#endif + float depth_divide = 1.0 / params.z_far; + + //depth *= depth_divide; + + /* + if (depth > params.z_far * 0.999) { + discard; //skybox + } + */ + + float sum = texelFetch(source_ssao, ssC, 0).r; + + // Base weight for depth falloff. Increase this for more blurriness, + // decrease it for better edge discrimination + float BASE = gaussian[0]; + float totalWeight = BASE; + sum *= totalWeight; + + ivec2 clamp_limit = params.screen_size - ivec2(1); + + for (int r = -R; r <= R; ++r) { + // We already handled the zero case above. This loop should be unrolled and the static branch optimized out, + // so the IF statement has no runtime cost + if (r != 0) { + + ivec2 ppos = ssC + params.axis * (r * params.filter_scale); + float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r; + ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit); + + + float temp_depth = texelFetch(source_depth, rpos, 0).r; +#ifdef MODE_FULL_SIZE + temp_depth = temp_depth * 2.0 - 1.0; + if (params.orthogonal) { + temp_depth = ((temp_depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + temp_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - temp_depth * (params.z_far - params.z_near)); + } + //temp_depth *= depth_divide; +#endif + // spatial domain: offset gaussian tap + float weight = 0.3 + gaussian[abs(r)]; + //weight *= max(0.0, dot(temp_normal, normal)); + + // range domain (the "bilateral" weight). As depth difference increases, decrease weight. + weight *= max(0.0, 1.0 - params.edge_sharpness * abs(temp_depth - depth)); + + sum += value * weight; + totalWeight += weight; + } + } + + const float epsilon = 0.0001; + float visibility = sum / (totalWeight + epsilon); + + imageStore(dest_image,ssC,vec4(visibility)); +#endif +} diff --git a/servers/visual/rasterizer_rd/shaders/ssao_minify.glsl b/servers/visual/rasterizer_rd/shaders/ssao_minify.glsl new file mode 100644 index 00000000000..0e6f8b7d9a7 --- /dev/null +++ b/servers/visual/rasterizer_rd/shaders/ssao_minify.glsl @@ -0,0 +1,49 @@ +/* clang-format off */ +[compute] +/* clang-format on */ + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +layout(push_constant, binding = 1, std430) uniform Params { + vec2 pixel_size; + float z_far; + float z_near; + ivec2 source_size; + bool orthogonal; + uint pad; +} params; + + +#ifdef MINIFY_START +layout(set = 0, binding = 0) uniform sampler2D source_texture; +#else +layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D source_image; +#endif +layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_image; + +void main() { + + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + + if (any(greaterThan(pos,params.source_size>>1))) { //too large, do nothing + return; + } + +#ifdef MINIFY_START + float depth = texelFetch(source_texture,pos<<1,0).r * 2.0 - 1.0; + if (params.orthogonal) { + depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); + } +#else + float depth = imageLoad(source_image,pos<<1).r; +#endif + + imageStore(dest_image,pos,vec4(depth)); + +} diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 51ce4403205..bcb327a6008 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -518,14 +518,15 @@ public: BIND2(environment_set_bg_color, RID, const Color &) BIND2(environment_set_bg_energy, RID, float) BIND2(environment_set_canvas_max_layer, RID, int) - BIND6(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource) + BIND7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &) // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 BIND2(environment_set_camera_feed_id, RID, int) #endif BIND7(environment_set_ssr, RID, bool, int, float, float, float, bool) - BIND13(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float) + BIND9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float) + BIND2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool) BIND12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool) diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 0bb16003a13..30fdef93258 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -450,6 +450,9 @@ void VisualServerViewport::viewport_set_size(RID p_viewport, int p_width, int p_ Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); + // if (viewport->size.width == p_width && viewport->size.height == p_height) { + // return; //nothing to do + // } viewport->size = Size2(p_width, p_height); VSG::storage->render_target_set_size(viewport->render_target, p_width, p_height); if (viewport->render_buffers.is_valid()) { diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index ddb0f8e76c4..cb5fef3ba0b 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -432,14 +432,16 @@ public: FUNC2(environment_set_bg_color, RID, const Color &) FUNC2(environment_set_bg_energy, RID, float) FUNC2(environment_set_canvas_max_layer, RID, int) - FUNC6(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource) + FUNC7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &) // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 FUNC2(environment_set_camera_feed_id, RID, int) #endif FUNC7(environment_set_ssr, RID, bool, int, float, float, float, bool) - FUNC13(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float) + FUNC9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float) + + FUNC2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool) FUNC12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 47e2d11af94..a8511b12c75 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1825,7 +1825,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &VisualServer::environment_set_tonemap); ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "ramp"), &VisualServer::environment_set_adjustment); ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance", "roughness"), &VisualServer::environment_set_ssr); - ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "radius2", "intensity2", "bias", "light_affect", "ao_channel_affect", "color", "quality", "blur", "bilateral_sharpness"), &VisualServer::environment_set_ssao); + ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "radius2", "intensity2", "bias", "light_affect", "ao_channel_affect", "color", "blur", "bilateral_sharpness"), &VisualServer::environment_set_ssao); ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "color", "sun_color", "sun_amount"), &VisualServer::environment_set_fog); ClassDB::bind_method(D_METHOD("environment_set_fog_depth", "env", "enable", "depth_begin", "depth_end", "depth_curve", "transmit", "transmit_curve"), &VisualServer::environment_set_fog_depth); @@ -2322,6 +2322,10 @@ VisualServer::VisualServer() { GLOBAL_DEF("rendering/quality/filters/depth_of_field_bokeh_quality", 2); ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/depth_of_field_bokeh_quality", PropertyInfo(Variant::INT, "rendering/quality/filters/depth_of_field_bokeh_quality", PROPERTY_HINT_ENUM, "Very Low (Fast),Low,Medium,High (Slow)")); GLOBAL_DEF("rendering/quality/filters/depth_of_field_use_jitter", false); + + GLOBAL_DEF("rendering/quality/ssao/quality", 1); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/ssao/quality", PropertyInfo(Variant::INT, "rendering/quality/ssao/quality", PROPERTY_HINT_ENUM, "Low (Fast),Medium,High (Slow),Ultra (Very Slow)")); + GLOBAL_DEF("rendering/quality/ssao/half_size", false); } VisualServer::~VisualServer() { diff --git a/servers/visual_server.h b/servers/visual_server.h index dde8025eb24..13ca4f4d1ae 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -664,6 +664,7 @@ public: VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS, VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS, VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE, + VIEWPORT_DEBUG_DRAW_SSAO, }; @@ -718,7 +719,7 @@ public: virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; - virtual void environment_set_ambient_light(RID p_env, const Color &p_color, EnvironmentAmbientSource p_ambient = ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, EnvironmentReflectionSource p_reflection_source = ENV_REFLECTION_SOURCE_BG) = 0; + virtual void environment_set_ambient_light(RID p_env, const Color &p_color, EnvironmentAmbientSource p_ambient = ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, EnvironmentReflectionSource p_reflection_source = ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0; // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; @@ -745,12 +746,6 @@ public: virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0; - enum EnvironmentSSAOQuality { - ENV_SSAO_QUALITY_LOW, - ENV_SSAO_QUALITY_MEDIUM, - ENV_SSAO_QUALITY_HIGH, - }; - enum EnvironmentSSAOBlur { ENV_SSAO_BLUR_DISABLED, ENV_SSAO_BLUR_1x1, @@ -758,7 +753,16 @@ public: ENV_SSAO_BLUR_3x3, }; - virtual 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, EnvironmentSSAOQuality p_quality, EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; + + enum EnvironmentSSAOQuality { + ENV_SSAO_QUALITY_LOW, + ENV_SSAO_QUALITY_MEDIUM, + ENV_SSAO_QUALITY_HIGH, + ENV_SSAO_QUALITY_ULTRA, + }; + + virtual void environment_set_ssao_quality(EnvironmentSSAOQuality p_quality, bool p_half_size) = 0; virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0; virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;