diff options
Diffstat (limited to 'servers/rendering/renderer_rd')
67 files changed, 5376 insertions, 3945 deletions
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index 228933d618..1bb45cbcc1 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -374,7 +374,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID } } -void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y) { +void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projection &p_cam_projection, bool p_flip_y) { view_xform = p_view_transform.affine_inverse(); projection = p_cam_projection; z_near = projection.get_z_near(); @@ -385,7 +385,7 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMa adjusted_projection.adjust_perspective_znear(0.0001); } - CameraMatrix correction; + Projection correction; correction.set_depth_correction(p_flip_y); projection = correction * projection; adjusted_projection = correction * adjusted_projection; diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h index 74ca530ff6..17ca1986c6 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.h +++ b/servers/rendering/renderer_rd/cluster_builder_rd.h @@ -168,8 +168,8 @@ private: uint32_t render_element_max = 0; Transform3D view_xform; - CameraMatrix adjusted_projection; - CameraMatrix projection; + Projection adjusted_projection; + Projection projection; float z_far = 0; float z_near = 0; bool orthogonal = false; @@ -220,7 +220,7 @@ private: public: void setup(Size2i p_screen_size, uint32_t p_max_elements, RID p_depth_buffer, RID p_depth_buffer_sampler, RID p_color_buffer); - void begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y); + void begin(const Transform3D &p_view_transform, const Projection &p_cam_projection, bool p_flip_y); _FORCE_INLINE_ void add_light(LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) { if (p_type == LIGHT_TYPE_OMNI && cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT] == max_elements_by_type) { @@ -375,4 +375,4 @@ public: ~ClusterBuilderRD(); }; -#endif // CLUSTER_BUILDER_H +#endif // CLUSTER_BUILDER_RD_H diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.h b/servers/rendering/renderer_rd/effects/bokeh_dof.h index d7b736119c..30b33be168 100644 --- a/servers/rendering/renderer_rd/effects/bokeh_dof.h +++ b/servers/rendering/renderer_rd/effects/bokeh_dof.h @@ -117,4 +117,4 @@ public: } // namespace RendererRD -#endif // !BOKEH_DOF_RD_H +#endif // BOKEH_DOF_RD_H diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index c30e8ed58f..5507483cee 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -100,11 +100,11 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) { { Vector<String> copy_modes; - copy_modes.push_back("\n"); - copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); - copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); - copy_modes.push_back("\n#define MULTIVIEW\n"); - copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); + copy_modes.push_back("\n"); // COPY_TO_FB_COPY + copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); // COPY_TO_FB_COPY_PANORAMA_TO_DP + copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2 + copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW + copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH copy_to_fb.shader.initialize(copy_modes); @@ -249,6 +249,56 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) { roughness.raster_pipeline.clear(); } } + + { + Vector<String> specular_modes; + specular_modes.push_back("\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD + specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR + specular_modes.push_back("\n"); // SPECULAR_MERGE_ADDITIVE_ADD + specular_modes.push_back("\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR + + specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD_MULTIVIEW + specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR_MULTIVIEW + specular_modes.push_back("\n#define USE_MULTIVIEW\n"); // SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW + specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW + + specular_merge.shader.initialize(specular_modes); + + if (!RendererCompositorRD::singleton->is_xr_enabled()) { + specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADD_MULTIVIEW, false); + specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_SSR_MULTIVIEW, false); + specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW, false); + specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW, false); + } + + specular_merge.shader_version = specular_merge.shader.version_create(); + + //use additive + + RD::PipelineColorBlendState::Attachment ba; + ba.enable_blend = true; + ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE; + ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; + ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + ba.color_blend_op = RD::BLEND_OP_ADD; + ba.alpha_blend_op = RD::BLEND_OP_ADD; + + RD::PipelineColorBlendState blend_additive; + blend_additive.attachments.push_back(ba); + + for (int i = 0; i < SPECULAR_MERGE_MAX; i++) { + if (specular_merge.shader.is_variant_enabled(i)) { + RD::PipelineColorBlendState blend_state; + if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR || i == SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW || i == SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW) { + blend_state = blend_additive; + } else { + blend_state = RD::PipelineColorBlendState::create_disabled(); + } + specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } + } + } } CopyEffects::~CopyEffects() { @@ -264,6 +314,8 @@ CopyEffects::~CopyEffects() { roughness.compute_shader.version_free(roughness.shader_version); } + specular_merge.shader.version_free(specular_merge.shader_version); + RD::get_singleton()->free(filter.coefficient_buffer); if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { @@ -1083,3 +1135,57 @@ void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_f RD::get_singleton()->draw_list_draw(draw_list, true); RD::get_singleton()->draw_list_end(); } + +void CopyEffects::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection, uint32_t p_view_count) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::get_singleton()->draw_command_begin_label("Merge specular"); + + 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_READ, Vector<Color>()); + + int mode; + if (p_reflection.is_valid()) { + if (p_base.is_valid()) { + mode = SPECULAR_MERGE_SSR; + } else { + mode = SPECULAR_MERGE_ADDITIVE_SSR; + } + } else { + if (p_base.is_valid()) { + mode = SPECULAR_MERGE_ADD; + } else { + mode = SPECULAR_MERGE_ADDITIVE_ADD; + } + } + + if (p_view_count > 1) { + mode += SPECULAR_MERGE_ADD_MULTIVIEW; + } + + RID shader = specular_merge.shader.version_get_shader(specular_merge.shader_version, mode); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + + if (p_base.is_valid()) { + RD::Uniform u_base(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_base })); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_base), 2); + } + + RD::Uniform u_specular(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_specular })); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_specular), 0); + + if (p_reflection.is_valid()) { + RD::Uniform u_reflection(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_reflection })); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_reflection), 1); + } + + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + RD::get_singleton()->draw_command_end_label(); +} diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h index 882b446964..d25555eee5 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.h +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COPY_RD_H -#define COPY_RD_H +#ifndef COPY_EFFECTS_RD_H +#define COPY_EFFECTS_RD_H #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl.gen.h" @@ -42,6 +42,7 @@ #include "servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering_server.h" @@ -274,6 +275,33 @@ private: PipelineCacheRD raster_pipeline; } roughness; + // Merge specular + + enum SpecularMergeMode { + SPECULAR_MERGE_ADD, + SPECULAR_MERGE_SSR, + SPECULAR_MERGE_ADDITIVE_ADD, + SPECULAR_MERGE_ADDITIVE_SSR, + + SPECULAR_MERGE_ADD_MULTIVIEW, + SPECULAR_MERGE_SSR_MULTIVIEW, + SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW, + SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW, + + SPECULAR_MERGE_MAX + }; + + /* Specular merge must be done using raster, rather than compute + * because it must continue the existing color buffer + */ + + struct SpecularMerge { + SpecularMergeShaderRD shader; + RID shader_version; + PipelineCacheRD pipelines[SPECULAR_MERGE_MAX]; + + } specular_merge; + static CopyEffects *singleton; public: @@ -309,8 +337,10 @@ public: void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); + + void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection, uint32_t p_view_count); }; } // namespace RendererRD -#endif // !COPY_RD_H +#endif // COPY_EFFECTS_RD_H diff --git a/servers/rendering/renderer_rd/effects/resolve.h b/servers/rendering/renderer_rd/effects/resolve.h index d4b24a610f..2a4cd06827 100644 --- a/servers/rendering/renderer_rd/effects/resolve.h +++ b/servers/rendering/renderer_rd/effects/resolve.h @@ -71,4 +71,4 @@ public: } // namespace RendererRD -#endif // !RESOLVE_RD_H +#endif // RESOLVE_RD_H diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp new file mode 100644 index 0000000000..0f896a8aa7 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -0,0 +1,1715 @@ +/*************************************************************************/ +/* ss_effects.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "ss_effects.h" + +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" + +using namespace RendererRD; + +SSEffects *SSEffects::singleton = nullptr; + +static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + p_array[i * 4 + j] = p_mtx.matrix[i][j]; + } + } +} + +SSEffects::SSEffects() { + singleton = this; + + { + // Initialize depth buffer for screen space effects + Vector<String> downsampler_modes; + downsampler_modes.push_back("\n"); + downsampler_modes.push_back("\n#define USE_HALF_SIZE\n"); + downsampler_modes.push_back("\n#define GENERATE_MIPS\n"); + downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n"); + downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n"); + downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n"); + downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS"); + + ss_effects.downsample_shader.initialize(downsampler_modes); + + ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create(); + + for (int i = 0; i < SS_EFFECTS_MAX; i++) { + ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i)); + } + + ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants)); + SSEffectsGatherConstants gather_constants; + + const int sub_pass_count = 5; + for (int pass = 0; pass < 4; pass++) { + for (int subPass = 0; subPass < sub_pass_count; subPass++) { + int a = pass; + int b = subPass; + + int spmap[5]{ 0, 1, 4, 3, 2 }; + b = spmap[subPass]; + + float ca, sa; + float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f; + + ca = Math::cos(angle0); + sa = Math::sin(angle0); + + float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f; + + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca; + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa; + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa; + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca; + } + } + + RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants); + } + + // Initialize Screen Space Indirect Lighting (SSIL) + + { + Vector<String> ssil_modes; + ssil_modes.push_back("\n"); + ssil_modes.push_back("\n#define SSIL_BASE\n"); + ssil_modes.push_back("\n#define ADAPTIVE\n"); + + ssil.gather_shader.initialize(ssil_modes); + + ssil.gather_shader_version = ssil.gather_shader.version_create(); + + for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) { + ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i)); + } + ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms)); + } + + { + Vector<String> ssil_modes; + ssil_modes.push_back("\n#define GENERATE_MAP\n"); + ssil_modes.push_back("\n#define PROCESS_MAPA\n"); + ssil_modes.push_back("\n#define PROCESS_MAPB\n"); + + ssil.importance_map_shader.initialize(ssil_modes); + + ssil.importance_map_shader_version = ssil.importance_map_shader.version_create(); + + for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) { + ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP)); + } + ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t)); + int zero[1] = { 0 }; + RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero); + RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter"); + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(ssil.importance_map_load_counter); + uniforms.push_back(u); + } + ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2); + RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set"); + } + + { + Vector<String> ssil_modes; + ssil_modes.push_back("\n#define MODE_NON_SMART\n"); + ssil_modes.push_back("\n#define MODE_SMART\n"); + ssil_modes.push_back("\n#define MODE_WIDE\n"); + + ssil.blur_shader.initialize(ssil_modes); + + ssil.blur_shader_version = ssil.blur_shader.version_create(); + for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) { + ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS)); + } + } + + { + Vector<String> ssil_modes; + ssil_modes.push_back("\n#define MODE_NON_SMART\n"); + ssil_modes.push_back("\n#define MODE_SMART\n"); + ssil_modes.push_back("\n#define MODE_HALF\n"); + + ssil.interleave_shader.initialize(ssil_modes); + + ssil.interleave_shader_version = ssil.interleave_shader.version_create(); + for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) { + ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE)); + } + } + + { + // Initialize Screen Space Ambient Occlusion (SSAO) + + RD::SamplerState sampler; + sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler.min_filter = RD::SAMPLER_FILTER_NEAREST; + sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST; + sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler.max_lod = 4; + + uint32_t pipeline = 0; + { + Vector<String> ssao_modes; + + ssao_modes.push_back("\n"); + ssao_modes.push_back("\n#define SSAO_BASE\n"); + ssao_modes.push_back("\n#define ADAPTIVE\n"); + + ssao.gather_shader.initialize(ssao_modes); + + ssao.gather_shader_version = ssao.gather_shader.version_create(); + + for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i)); + pipeline++; + } + } + + { + Vector<String> ssao_modes; + ssao_modes.push_back("\n#define GENERATE_MAP\n"); + ssao_modes.push_back("\n#define PROCESS_MAPA\n"); + ssao_modes.push_back("\n#define PROCESS_MAPB\n"); + + ssao.importance_map_shader.initialize(ssao_modes); + + ssao.importance_map_shader_version = ssao.importance_map_shader.version_create(); + + for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP)); + + pipeline++; + } + + ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t)); + int zero[1] = { 0 }; + RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero); + RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter"); + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(ssao.importance_map_load_counter); + uniforms.push_back(u); + } + ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2); + RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set"); + } + + { + Vector<String> ssao_modes; + ssao_modes.push_back("\n#define MODE_NON_SMART\n"); + ssao_modes.push_back("\n#define MODE_SMART\n"); + ssao_modes.push_back("\n#define MODE_WIDE\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_PASS_WIDE; 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++; + } + } + + { + Vector<String> ssao_modes; + ssao_modes.push_back("\n#define MODE_NON_SMART\n"); + ssao_modes.push_back("\n#define MODE_SMART\n"); + ssao_modes.push_back("\n#define MODE_HALF\n"); + + ssao.interleave_shader.initialize(ssao_modes); + + ssao.interleave_shader_version = ssao.interleave_shader.version_create(); + for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE)); + RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i)); + pipeline++; + } + } + + ERR_FAIL_COND(pipeline != SSAO_MAX); + + ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler); + } + + { + // Screen Space Reflections + + Vector<RD::PipelineSpecializationConstant> specialization_constants; + + { + RD::PipelineSpecializationConstant sc; + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sc.constant_id = 0; // SSR_USE_FULL_PROJECTION_MATRIX + sc.bool_value = false; + specialization_constants.push_back(sc); + } + + { + Vector<String> ssr_scale_modes; + ssr_scale_modes.push_back("\n"); + + ssr_scale.shader.initialize(ssr_scale_modes); + ssr_scale.shader_version = ssr_scale.shader.version_create(); + + for (int v = 0; v < SSR_VARIATIONS; v++) { + specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false; + ssr_scale.pipelines[v] = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), specialization_constants); + } + } + + { + Vector<String> ssr_modes; + ssr_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_NORMAL + ssr_modes.push_back("\n#define MODE_ROUGH\n"); // SCREEN_SPACE_REFLECTION_ROUGH + + ssr.shader.initialize(ssr_modes); + ssr.shader_version = ssr.shader.version_create(); + + for (int v = 0; v < SSR_VARIATIONS; v++) { + specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false; + for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) { + ssr.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i), specialization_constants); + } + } + } + + { + Vector<String> ssr_filter_modes; + ssr_filter_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL + ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n"); // SCREEN_SPACE_REFLECTION_FILTER_VERTICAL + + ssr_filter.shader.initialize(ssr_filter_modes); + ssr_filter.shader_version = ssr_filter.shader.version_create(); + + for (int v = 0; v < SSR_VARIATIONS; v++) { + specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false; + for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) { + ssr_filter.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i), specialization_constants); + } + } + } + } +} + +SSEffects::~SSEffects() { + { + // Cleanup SS Reflections + ssr.shader.version_free(ssr.shader_version); + ssr_filter.shader.version_free(ssr_filter.shader_version); + ssr_scale.shader.version_free(ssr_scale.shader_version); + + if (ssr.ubo.is_valid()) { + RD::get_singleton()->free(ssr.ubo); + } + } + + { + // Cleanup SS downsampler + ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version); + + RD::get_singleton()->free(ss_effects.mirror_sampler); + RD::get_singleton()->free(ss_effects.gather_constants_buffer); + } + + { + // Cleanup SSIL + ssil.blur_shader.version_free(ssil.blur_shader_version); + ssil.gather_shader.version_free(ssil.gather_shader_version); + ssil.interleave_shader.version_free(ssil.interleave_shader_version); + ssil.importance_map_shader.version_free(ssil.importance_map_shader_version); + + RD::get_singleton()->free(ssil.importance_map_load_counter); + RD::get_singleton()->free(ssil.projection_uniform_buffer); + } + + { + // Cleanup SSAO + ssao.blur_shader.version_free(ssao.blur_shader_version); + ssao.gather_shader.version_free(ssao.gather_shader_version); + ssao.interleave_shader.version_free(ssao.interleave_shader_version); + ssao.importance_map_shader.version_free(ssao.importance_map_shader_version); + + RD::get_singleton()->free(ssao.importance_map_load_counter); + } + + singleton = nullptr; +} + +/* SS Downsampler */ + +void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const Projection &p_projection) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + // Downsample and deinterleave the depth buffer for SSAO and SSIL + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + int downsample_mode = SS_EFFECTS_DOWNSAMPLE; + bool use_mips = p_ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || p_ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM; + + if (p_ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && p_ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { + downsample_mode = SS_EFFECTS_DOWNSAMPLE_HALF; + } else if (use_mips) { + downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP; + } + + bool use_half_size = false; + bool use_full_mips = false; + + if (p_ssao_half_size && p_ssil_half_size) { + downsample_mode++; + use_half_size = true; + } else if (p_ssao_half_size != p_ssil_half_size) { + if (use_mips) { + downsample_mode = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS; + use_full_mips = true; + } else { + // Only need the first two mipmaps, but the cost to generate the next two is trivial + // TODO investigate the benefit of a shader version to generate only 2 mips + downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP; + use_mips = true; + } + } + + int depth_index = use_half_size ? 1 : 0; + + RD::get_singleton()->draw_command_begin_label("Downsample Depth"); + if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.append_id(p_depth_mipmaps[depth_index + 1]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.append_id(p_depth_mipmaps[depth_index + 2]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.append_id(p_depth_mipmaps[depth_index + 3]); + uniforms.push_back(u); + } + if (use_full_mips) { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 3; + u.append_id(p_depth_mipmaps[4]); + uniforms.push_back(u); + } + ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2); + } + + float depth_linearize_mul = -p_projection.matrix[3][2]; + float depth_linearize_add = p_projection.matrix[2][2]; + if (depth_linearize_mul * depth_linearize_add < 0) { + depth_linearize_add = -depth_linearize_add; + } + + ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal(); + ss_effects.downsample_push_constant.z_near = depth_linearize_mul; + ss_effects.downsample_push_constant.z_far = depth_linearize_add; + if (ss_effects.downsample_push_constant.orthogonal) { + ss_effects.downsample_push_constant.z_near = p_projection.get_z_near(); + ss_effects.downsample_push_constant.z_far = p_projection.get_z_far(); + } + ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x; + ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y; + ss_effects.downsample_push_constant.radius_sq = 1.0; + + RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode); + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_buffer })); + RD::Uniform u_depth_mipmaps(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_depth_mipmaps[depth_index + 0] })); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmaps), 1); + if (use_mips) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2); + } + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant)); + + Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1))); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + RD::get_singleton()->draw_command_end_label(); + + RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE); + + ss_effects.used_full_mips_last_frame = use_full_mips; + ss_effects.used_half_size_last_frame = use_half_size; +} + +/* SSIL */ + +void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0); + if ((p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) { + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1); + } + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3); + + RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0); + + for (int i = 0; i < 4; i++) { + if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + continue; + } + + RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_slices[i] })); + RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_edges_slices[i] })); + + ssil.gather_push_constant.pass_coord_offset[0] = i % 2; + ssil.gather_push_constant.pass_coord_offset[1] = i / 2; + ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x; + ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y; + ssil.gather_push_constant.pass = i; + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ssil_slice, u_edges_slice), 2); + RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant)); + + Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); + + RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1); + } + RD::get_singleton()->compute_list_add_barrier(p_compute_list); +} + +void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth) { + if (p_ssil_buffers.half_size != p_settings.half_size) { + ssil_free(p_ssil_buffers); + } + + if (p_settings.half_size) { + p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4; + p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4; + p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8; + p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8; + } else { + p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2; + p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2; + p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4; + p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4; + } + + if (p_ssil_buffers.ssil_final.is_null()) { + { + p_ssil_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, p_settings.half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); + } + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = p_settings.full_screen_size.x; + tf.height = p_settings.full_screen_size.y; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + p_ssil_buffers.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.ssil_final, "SSIL texture"); + RD::get_singleton()->texture_clear(p_ssil_buffers.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1); + if (p_ssil_buffers.last_frame.is_null()) { + tf.mipmaps = 6; + p_ssil_buffers.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.last_frame, "Last Frame Radiance"); + RD::get_singleton()->texture_clear(p_ssil_buffers.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1); + for (uint32_t i = 0; i < 6; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.last_frame, 0, i); + p_ssil_buffers.last_frame_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " "); + } + } + } + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = p_ssil_buffers.buffer_width; + tf.height = p_ssil_buffers.buffer_height; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssil_buffers.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.deinterleaved, "SSIL deinterleaved buffer"); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.deinterleaved, i, 0); + p_ssil_buffers.deinterleaved_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " "); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = p_ssil_buffers.buffer_width; + tf.height = p_ssil_buffers.buffer_height; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssil_buffers.pong = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.pong, "SSIL deinterleaved pong buffer"); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.pong, i, 0); + p_ssil_buffers.pong_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " "); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = p_ssil_buffers.buffer_width; + tf.height = p_ssil_buffers.buffer_height; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssil_buffers.edges = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.edges, "SSIL edges buffer"); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.edges, i, 0); + p_ssil_buffers.edges_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " "); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = p_ssil_buffers.half_buffer_width; + tf.height = p_ssil_buffers.half_buffer_height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssil_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[0], "SSIL Importance Map"); + p_ssil_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[1], "SSIL Importance Map Pong"); + } + p_ssil_buffers.half_size = p_settings.half_size; + } +} + +void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting"); + //Store projection info before starting the compute list + SSILProjectionUniforms projection_uniforms; + store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix); + + RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms); + + memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant)); + + RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0); + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + { + RD::get_singleton()->draw_command_begin_label("Gather Samples"); + ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; + ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; + + ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width; + ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height; + float tan_half_fov_x = 1.0 / p_projection.matrix[0][0]; + float tan_half_fov_y = 1.0 / p_projection.matrix[1][1]; + ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; + ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0; + ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0; + ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; + ssil.gather_push_constant.z_near = p_projection.get_z_near(); + ssil.gather_push_constant.z_far = p_projection.get_z_far(); + ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); + + ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25; + ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25; + + ssil.gather_push_constant.radius = p_settings.radius; + float radius_near_limit = (p_settings.radius * 1.2f); + if (p_settings.quality <= RS::ENV_SSIL_QUALITY_LOW) { + radius_near_limit *= 1.50f; + + if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { + ssil.gather_push_constant.radius *= 0.8f; + } + } + radius_near_limit /= tan_half_fov_y; + ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI; + ssil.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from); + ssil.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0; + ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit; + ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius; + ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection; + + ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssil_buffers.half_buffer_width) * (p_ssil_buffers.half_buffer_height) * 255); + ssil.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target; + + ssil.gather_push_constant.quality = MAX(0, p_settings.quality - 1); + ssil.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1; + + if (p_ssil_buffers.projection_uniform_set.is_null()) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.append_id(default_mipmap_sampler); + u.append_id(p_ssil_buffers.last_frame); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 1; + u.append_id(ssil.projection_uniform_buffer); + uniforms.push_back(u); + } + p_ssil_buffers.projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3); + } + + if (p_ssil_buffers.gather_uniform_set.is_null()) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.append_id(default_sampler); + u.append_id(p_ssil_buffers.depth_texture_view); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.append_id(p_normal_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 2; + u.append_id(ss_effects.gather_constants_buffer); + uniforms.push_back(u); + } + p_ssil_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0); + } + + if (p_ssil_buffers.importance_map_uniform_set.is_null()) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.append_id(p_ssil_buffers.pong); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 1; + u.append_id(default_sampler); + u.append_id(p_ssil_buffers.importance_map[0]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.append_id(ssil.importance_map_load_counter); + uniforms.push_back(u); + } + p_ssil_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1); + } + + if (p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) { + RD::get_singleton()->draw_command_begin_label("Generate Importance Map"); + ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width; + ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height; + ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI; + //base pass + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]); + gather_ssil(compute_list, p_ssil_buffers.pong_slices, p_ssil_buffers.edges_slices, p_settings, true, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set); + + //generate importance map + RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong })); + RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[0] })); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + // process Importance Map A + RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[0] })); + RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[1] })); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + // process Importance Map B + RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[1] })); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + RD::get_singleton()->draw_command_end_label(); // Importance Map + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]); + } else { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]); + } + + gather_ssil(compute_list, p_ssil_buffers.deinterleaved_slices, p_ssil_buffers.edges_slices, p_settings, false, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set); + RD::get_singleton()->draw_command_end_label(); //Gather + } + + { + RD::get_singleton()->draw_command_begin_label("Edge Aware Blur"); + ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness; + ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width; + ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height; + + int blur_passes = p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? p_settings.blur_passes : 1; + + shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, 0); + + for (int pass = 0; pass < blur_passes; pass++) { + int blur_pipeline = SSIL_BLUR_PASS; + if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) { + blur_pipeline = SSIL_BLUR_PASS_SMART; + if (pass < blur_passes - 2) { + blur_pipeline = SSIL_BLUR_PASS_WIDE; + } + } + + for (int i = 0; i < 4; i++) { + if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + continue; + } + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]); + if (pass % 2 == 0) { + if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { + RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0); + } else { + RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0); + } + + RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong_slice), 1); + } else { + if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { + RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0); + } else { + RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0); + } + + RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_slice), 1); + } + + RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges_slice), 2); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant)); + + int x_groups = (p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)); + int y_groups = (p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1); + if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) { + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + } + } + + RD::get_singleton()->draw_command_end_label(); // Blur + } + + { + RD::get_singleton()->draw_command_begin_label("Interleave Buffers"); + ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness; + ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; + ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y; + ssil.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2); + + int interleave_pipeline = SSIL_INTERLEAVE_HALF; + if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) { + interleave_pipeline = SSIL_INTERLEAVE; + } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) { + interleave_pipeline = SSIL_INTERLEAVE_SMART; + } + + shader = ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, 0); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]); + + RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.ssil_final })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0); + + if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) { + RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1); + } else { + RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong), 1); + } + + RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges), 2); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + RD::get_singleton()->draw_command_end_label(); // Interleave + } + + RD::get_singleton()->draw_command_end_label(); // SSIL + + RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); + + int zero[1] = { 0 }; + RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier +} + +void SSEffects::ssil_free(SSILRenderBuffers &p_ssil_buffers) { + if (p_ssil_buffers.ssil_final.is_valid()) { + RD::get_singleton()->free(p_ssil_buffers.ssil_final); + RD::get_singleton()->free(p_ssil_buffers.deinterleaved); + RD::get_singleton()->free(p_ssil_buffers.pong); + RD::get_singleton()->free(p_ssil_buffers.edges); + RD::get_singleton()->free(p_ssil_buffers.importance_map[0]); + RD::get_singleton()->free(p_ssil_buffers.importance_map[1]); + RD::get_singleton()->free(p_ssil_buffers.last_frame); + + p_ssil_buffers.ssil_final = RID(); + p_ssil_buffers.deinterleaved = RID(); + p_ssil_buffers.pong = RID(); + p_ssil_buffers.edges = RID(); + p_ssil_buffers.deinterleaved_slices.clear(); + p_ssil_buffers.pong_slices.clear(); + p_ssil_buffers.edges_slices.clear(); + p_ssil_buffers.importance_map[0] = RID(); + p_ssil_buffers.importance_map[1] = RID(); + p_ssil_buffers.last_frame = RID(); + p_ssil_buffers.last_frame_slices.clear(); + + p_ssil_buffers.gather_uniform_set = RID(); + p_ssil_buffers.importance_map_uniform_set = RID(); + p_ssil_buffers.projection_uniform_set = RID(); + } +} + +/* SSAO */ + +void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0); + if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) { + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 0); + } + + RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); // + + for (int i = 0; i < 4; i++) { + if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + continue; + } + + RD::Uniform u_ao_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ao_slices[i] })); + + ssao.gather_push_constant.pass_coord_offset[0] = i % 2; + ssao.gather_push_constant.pass_coord_offset[1] = i / 2; + ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x; + ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y; + ssao.gather_push_constant.pass = i; + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ao_slice), 2); + RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant)); + + Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); + + RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1); + } + RD::get_singleton()->compute_list_add_barrier(p_compute_list); +} + +void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth) { + if (p_ssao_buffers.half_size != p_settings.half_size) { + ssao_free(p_ssao_buffers); + } + + if (p_settings.half_size) { + p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4; + p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4; + p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8; + p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8; + } else { + p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2; + p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2; + p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4; + p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4; + } + + if (p_ssao_buffers.ao_deinterleaved.is_null()) { + { + p_ssao_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, p_settings.half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); + } + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8G8_UNORM; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = p_ssao_buffers.buffer_width; + tf.height = p_ssao_buffers.buffer_height; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssao_buffers.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_deinterleaved, "SSAO De-interleaved Array"); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_deinterleaved, i, 0); + p_ssao_buffers.ao_deinterleaved_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " "); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8G8_UNORM; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = p_ssao_buffers.buffer_width; + tf.height = p_ssao_buffers.buffer_height; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssao_buffers.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_pong, "SSAO De-interleaved Array Pong"); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_pong, i, 0); + p_ssao_buffers.ao_pong_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong"); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = p_ssao_buffers.buffer_width; + tf.height = p_ssao_buffers.buffer_height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssao_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[0], "SSAO Importance Map"); + p_ssao_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[1], "SSAO Importance Map Pong"); + } + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = p_settings.full_screen_size.x; + tf.height = p_settings.full_screen_size.y; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + p_ssao_buffers.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_final, "SSAO Final"); + } + p_ssao_buffers.half_size = p_settings.half_size; + } +} + +void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant)); + /* FIRST PASS */ + + RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0); + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion"); + /* SECOND PASS */ + // Sample SSAO + { + RD::get_singleton()->draw_command_begin_label("Gather Samples"); + ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; + ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; + + ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width; + ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height; + float tan_half_fov_x = 1.0 / p_projection.matrix[0][0]; + float tan_half_fov_y = 1.0 / p_projection.matrix[1][1]; + ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; + ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0; + ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0; + ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; + ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); + + ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25; + ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25; + + ssao.gather_push_constant.radius = p_settings.radius; + float radius_near_limit = (p_settings.radius * 1.2f); + if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) { + radius_near_limit *= 1.50f; + + if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { + ssao.gather_push_constant.radius *= 0.8f; + } + } + radius_near_limit /= tan_half_fov_y; + ssao.gather_push_constant.intensity = p_settings.intensity; + ssao.gather_push_constant.shadow_power = p_settings.power; + ssao.gather_push_constant.shadow_clamp = 0.98; + ssao.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from); + ssao.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0; + ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon; + ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit; + ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius; + + ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssao_buffers.half_buffer_width) * (p_ssao_buffers.half_buffer_height) * 255); + ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target; + + ssao.gather_push_constant.detail_intensity = p_settings.detail; + ssao.gather_push_constant.quality = MAX(0, p_settings.quality - 1); + ssao.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1; + + if (p_ssao_buffers.gather_uniform_set.is_null()) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.append_id(default_sampler); + u.append_id(p_ssao_buffers.depth_texture_view); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.append_id(p_normal_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 2; + u.append_id(ss_effects.gather_constants_buffer); + uniforms.push_back(u); + } + p_ssao_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader, 0); + RD::get_singleton()->set_resource_name(p_ssao_buffers.gather_uniform_set, "SSAO Gather Uniform Set"); + } + + if (p_ssao_buffers.importance_map_uniform_set.is_null()) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.append_id(p_ssao_buffers.ao_pong); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 1; + u.append_id(default_sampler); + u.append_id(p_ssao_buffers.importance_map[0]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.append_id(ssao.importance_map_load_counter); + uniforms.push_back(u); + } + p_ssao_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1); + RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map_uniform_set, "SSAO Importance Map Uniform Set"); + } + + if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) { + RD::get_singleton()->draw_command_begin_label("Generate Importance Map"); + ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width; + ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height; + ssao.importance_map_push_constant.intensity = p_settings.intensity; + ssao.importance_map_push_constant.power = p_settings.power; + + //base pass + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]); + gather_ssao(compute_list, p_ssao_buffers.ao_pong_slices, p_settings, true, p_ssao_buffers.gather_uniform_set, RID()); + + //generate importance map + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]); + + RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_with_sampler), 0); + + RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[0] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //process importance map A + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]); + + RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[0] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0); + + RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[1] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //process Importance Map B + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]); + + RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[1] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]); + RD::get_singleton()->draw_command_end_label(); // Importance Map + } else { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]); + } + + gather_ssao(compute_list, p_ssao_buffers.ao_deinterleaved_slices, p_settings, false, p_ssao_buffers.gather_uniform_set, p_ssao_buffers.importance_map_uniform_set); + RD::get_singleton()->draw_command_end_label(); // Gather SSAO + } + + // /* THIRD PASS */ + // // Blur + // + { + RD::get_singleton()->draw_command_begin_label("Edge Aware Blur"); + ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness; + ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width; + ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height; + + int blur_passes = p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? p_settings.blur_passes : 1; + + shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0); + + for (int pass = 0; pass < blur_passes; pass++) { + int blur_pipeline = SSAO_BLUR_PASS; + if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { + blur_pipeline = SSAO_BLUR_PASS_SMART; + if (pass < blur_passes - 2) { + blur_pipeline = SSAO_BLUR_PASS_WIDE; + } else { + blur_pipeline = SSAO_BLUR_PASS_SMART; + } + } + + for (int i = 0; i < 4; i++) { + if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + continue; + } + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]); + if (pass % 2 == 0) { + if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { + RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0); + } else { + RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0); + } + + RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_pong_slices), 1); + } else { + if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { + RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0); + } else { + RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0); + } + + RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_slices), 1); + } + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); + + Size2i size(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1); + } + + if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + } + RD::get_singleton()->draw_command_end_label(); // Blur + } + + /* FOURTH PASS */ + // Interleave buffers + // back to full size + { + RD::get_singleton()->draw_command_begin_label("Interleave Buffers"); + ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness; + ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; + ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y; + ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2); + + shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, 0); + + int interleave_pipeline = SSAO_INTERLEAVE_HALF; + if (p_settings.quality == RS::ENV_SSAO_QUALITY_LOW) { + interleave_pipeline = SSAO_INTERLEAVE; + } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) { + interleave_pipeline = SSAO_INTERLEAVE_SMART; + } + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]); + + RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_final })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_buffer), 0); + + if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) { + RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1); + } else { + RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1); + } + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + RD::get_singleton()->draw_command_end_label(); // Interleave + } + RD::get_singleton()->draw_command_end_label(); //SSAO + RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer + + int zero[1] = { 0 }; + RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier +} + +void SSEffects::ssao_free(SSAORenderBuffers &p_ssao_buffers) { + if (p_ssao_buffers.ao_final.is_valid()) { + RD::get_singleton()->free(p_ssao_buffers.ao_deinterleaved); + RD::get_singleton()->free(p_ssao_buffers.ao_pong); + RD::get_singleton()->free(p_ssao_buffers.ao_final); + + RD::get_singleton()->free(p_ssao_buffers.importance_map[0]); + RD::get_singleton()->free(p_ssao_buffers.importance_map[1]); + + p_ssao_buffers.ao_deinterleaved = RID(); + p_ssao_buffers.ao_pong = RID(); + p_ssao_buffers.ao_final = RID(); + p_ssao_buffers.importance_map[0] = RID(); + p_ssao_buffers.importance_map[1] = RID(); + p_ssao_buffers.ao_deinterleaved_slices.clear(); + p_ssao_buffers.ao_pong_slices.clear(); + + p_ssao_buffers.gather_uniform_set = RID(); + p_ssao_buffers.importance_map_uniform_set = RID(); + } +} + +/* Screen Space Reflection */ + +void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const Size2i &p_screen_size, const uint32_t p_view_count) { + // As we are processing one view at a time, we can reuse buffers, only our output needs to have layers for each view. + + if (p_ssr_buffers.depth_scaled.is_null()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + tf.width = p_screen_size.x; + tf.height = p_screen_size.y; + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; + + p_ssr_buffers.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.depth_scaled, "SSR Depth Scaled"); + + tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + + p_ssr_buffers.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.normal_scaled, "SSR Normal Scaled"); + } + + if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_ssr_buffers.blur_radius[0].is_valid()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = p_screen_size.x; + tf.height = p_screen_size.y; + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + + p_ssr_buffers.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[0], "SSR Blur Radius 0"); + p_ssr_buffers.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[1], "SSR Blur Radius 1"); + } + + if (p_ssr_buffers.intermediate.is_null()) { + RD::TextureFormat tf; + tf.format = p_color_format; + tf.width = p_screen_size.x; + tf.height = p_screen_size.y; + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + + p_ssr_buffers.intermediate = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.intermediate, "SSR Intermediate"); + + if (p_view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.array_layers = p_view_count; + } else { + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + } + + p_ssr_buffers.output = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(p_ssr_buffers.output, "SSR Output"); + + for (uint32_t v = 0; v < p_view_count; v++) { + p_ssr_buffers.output_slices[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssr_buffers.output, v, 0); + } + } +} + +void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + { + // Store some scene data in a UBO, in the near future we will use a UBO shared with other shaders + ScreenSpaceReflectionSceneData scene_data; + + if (ssr.ubo.is_null()) { + ssr.ubo = RD::get_singleton()->uniform_buffer_create(sizeof(ScreenSpaceReflectionSceneData)); + } + + for (uint32_t v = 0; v < p_view_count; v++) { + store_camera(p_projections[v], scene_data.projection[v]); + store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]); + scene_data.eye_offset[v][0] = p_eye_offsets[v].x; + scene_data.eye_offset[v][1] = p_eye_offsets[v].y; + scene_data.eye_offset[v][2] = p_eye_offsets[v].z; + scene_data.eye_offset[v][3] = 0.0; + } + + RD::get_singleton()->buffer_update(ssr.ubo, 0, sizeof(ScreenSpaceReflectionSceneData), &scene_data, RD::BARRIER_MASK_COMPUTE); + } + + uint32_t pipeline_specialization = 0; + if (p_view_count > 1) { + pipeline_specialization |= SSR_MULTIVIEW; + } + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + for (uint32_t v = 0; v < p_view_count; v++) { + RD::get_singleton()->draw_command_begin_label(String("SSR View ") + itos(v)); + + { //scale color and depth to half + RD::get_singleton()->draw_command_begin_label("SSR Scale"); + + ScreenSpaceReflectionScalePushConstant push_constant; + push_constant.view_index = v; + push_constant.camera_z_far = p_projections[v].get_z_far(); + push_constant.camera_z_near = p_projections[v].get_z_near(); + push_constant.orthogonal = p_projections[v].is_orthogonal(); + push_constant.filter = false; //enabling causes arctifacts + push_constant.screen_size[0] = p_screen_size.x; + push_constant.screen_size[1] = p_screen_size.y; + + RID shader = ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipelines[pipeline_specialization]); + + RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse_slices[v] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse), 0); + + RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_slices[v] })); + RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_normal_roughness_slices[v] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth, u_normal_roughness), 1); + + RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur), 2); + + RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled })); + RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.normal_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth, u_scale_normal), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionScalePushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + + RD::get_singleton()->compute_list_add_barrier(compute_list); + + RD::get_singleton()->draw_command_end_label(); + } + + { + RD::get_singleton()->draw_command_begin_label("SSR main"); + + ScreenSpaceReflectionPushConstant push_constant; + push_constant.view_index = v; + push_constant.camera_z_far = p_projections[v].get_z_far(); + push_constant.camera_z_near = p_projections[v].get_z_near(); + push_constant.orthogonal = p_projections[v].is_orthogonal(); + push_constant.screen_size[0] = p_screen_size.x; + push_constant.screen_size[1] = p_screen_size.y; + push_constant.curve_fade_in = p_fade_in; + push_constant.distance_fade = p_fade_out; + push_constant.num_steps = p_max_steps; + push_constant.depth_tolerance = p_tolerance; + push_constant.use_half_res = true; + push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]); + push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]); + push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0]; + push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1]; + push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255); + push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255); + push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255); + push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255); + + ScreenSpaceReflectionMode mode = (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL; + RID shader = ssr.shader.version_get_shader(ssr.shader_version, mode); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[pipeline_specialization][mode]); + + RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4); + + RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] })); + RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_scale_depth), 0); + + if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { + RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate })); + RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate, u_blur_radius), 1); + } else { + RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1); + } + + RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_scale_normal), 2); + + RD::Uniform u_metallic(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_metallic_slices[v] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_metallic), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + + RD::get_singleton()->draw_command_end_label(); + } + + if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { + RD::get_singleton()->draw_command_begin_label("SSR filter"); + //blur + + RD::get_singleton()->compute_list_add_barrier(compute_list); + + ScreenSpaceReflectionFilterPushConstant push_constant; + push_constant.view_index = v; + push_constant.orthogonal = p_projections[v].is_orthogonal(); + push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0)); + push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]); + push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]); + push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0]; + push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1]; + push_constant.vertical = 0; + if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) { + push_constant.steps = p_max_steps / 3; + push_constant.increment = 3; + } else if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) { + push_constant.steps = p_max_steps / 2; + push_constant.increment = 2; + } else { + push_constant.steps = p_max_steps; + push_constant.increment = 1; + } + + push_constant.screen_size[0] = p_screen_size.width; + push_constant.screen_size[1] = p_screen_size.height; + + // Horizontal pass + + SSRReflectionMode mode = SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL; + + RID shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]); + + RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4); + + RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate })); + RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_blur_radius), 0); + + RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1); + + RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] })); + RD::Uniform u_blur_radius2(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[1] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur, u_blur_radius2), 2); + + RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + // Vertical pass + + mode = SCREEN_SPACE_REFLECTION_FILTER_VERTICAL; + shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]); + + push_constant.vertical = 1; + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_blur_radius2), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + + if (v != p_view_count - 1) { + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + + RD::get_singleton()->draw_command_end_label(); + } + + RD::get_singleton()->draw_command_end_label(); + } + + RD::get_singleton()->compute_list_end(); +} + +void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) { + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + p_ssr_buffers.output_slices[v] = RID(); + } + + if (p_ssr_buffers.output.is_valid()) { + RD::get_singleton()->free(p_ssr_buffers.output); + p_ssr_buffers.output = RID(); + } + + if (p_ssr_buffers.intermediate.is_valid()) { + RD::get_singleton()->free(p_ssr_buffers.intermediate); + p_ssr_buffers.intermediate = RID(); + } + + if (p_ssr_buffers.blur_radius[0].is_valid()) { + RD::get_singleton()->free(p_ssr_buffers.blur_radius[0]); + RD::get_singleton()->free(p_ssr_buffers.blur_radius[1]); + p_ssr_buffers.blur_radius[0] = RID(); + p_ssr_buffers.blur_radius[1] = RID(); + } + + if (p_ssr_buffers.depth_scaled.is_valid()) { + RD::get_singleton()->free(p_ssr_buffers.depth_scaled); + p_ssr_buffers.depth_scaled = RID(); + RD::get_singleton()->free(p_ssr_buffers.normal_scaled); + p_ssr_buffers.normal_scaled = RID(); + } +} diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h new file mode 100644 index 0000000000..c31271ffd2 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/ss_effects.h @@ -0,0 +1,508 @@ +/*************************************************************************/ +/* ss_effects.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SS_EFFECTS_RD_H +#define SS_EFFECTS_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssao.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssil.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" +#include "servers/rendering_server.h" + +namespace RendererRD { + +class SSEffects { +private: + static SSEffects *singleton; + +public: + static SSEffects *get_singleton() { return singleton; } + + SSEffects(); + ~SSEffects(); + + /* SS Downsampler */ + + void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const Projection &p_projection); + + /* SSIL */ + + struct SSILRenderBuffers { + bool half_size = false; + int buffer_width; + int buffer_height; + int half_buffer_width; + int half_buffer_height; + + RID ssil_final; + RID deinterleaved; + Vector<RID> deinterleaved_slices; + RID pong; + Vector<RID> pong_slices; + RID edges; + Vector<RID> edges_slices; + RID importance_map[2]; + RID depth_texture_view; + + RID last_frame; + Vector<RID> last_frame_slices; + + RID gather_uniform_set; + RID importance_map_uniform_set; + RID projection_uniform_set; + }; + + struct SSILSettings { + float radius = 1.0; + float intensity = 2.0; + float sharpness = 0.98; + float normal_rejection = 1.0; + + RS::EnvironmentSSILQuality quality = RS::ENV_SSIL_QUALITY_MEDIUM; + bool half_size = true; + float adaptive_target = 0.5; + int blur_passes = 4; + float fadeout_from = 50.0; + float fadeout_to = 300.0; + + Size2i full_screen_size = Size2i(); + }; + + void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth); + void screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings); + void ssil_free(SSILRenderBuffers &p_ssil_buffers); + + /* SSAO */ + + struct SSAORenderBuffers { + bool half_size = false; + int buffer_width; + int buffer_height; + int half_buffer_width; + int half_buffer_height; + + RID ao_deinterleaved; + Vector<RID> ao_deinterleaved_slices; + RID ao_pong; + Vector<RID> ao_pong_slices; + RID ao_final; + RID importance_map[2]; + RID depth_texture_view; + + RID gather_uniform_set; + RID importance_map_uniform_set; + }; + + struct SSAOSettings { + float radius = 1.0; + float intensity = 2.0; + float power = 1.5; + float detail = 0.5; + float horizon = 0.06; + float sharpness = 0.98; + + RS::EnvironmentSSAOQuality quality = RS::ENV_SSAO_QUALITY_MEDIUM; + bool half_size = false; + float adaptive_target = 0.5; + int blur_passes = 2; + float fadeout_from = 50.0; + float fadeout_to = 300.0; + + Size2i full_screen_size = Size2i(); + }; + + void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth); + void generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings); + void ssao_free(SSAORenderBuffers &p_ssao_buffers); + + /* Screen Space Reflection */ + + struct SSRRenderBuffers { + RID normal_scaled; + RID depth_scaled; + RID blur_radius[2]; + RID intermediate; + RID output; + RID output_slices[RendererSceneRender::MAX_RENDER_VIEWS]; + }; + + void ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const Size2i &p_screen_size, const uint32_t p_view_count); + void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets); + void ssr_free(SSRRenderBuffers &p_ssr_buffers); + +private: + /* SS Downsampler */ + + struct SSEffectsDownsamplePushConstant { + float pixel_size[2]; + float z_far; + float z_near; + uint32_t orthogonal; + float radius_sq; + uint32_t pad[2]; + }; + + enum SSEffectsMode { + SS_EFFECTS_DOWNSAMPLE, + SS_EFFECTS_DOWNSAMPLE_HALF_RES, + SS_EFFECTS_DOWNSAMPLE_MIPMAP, + SS_EFFECTS_DOWNSAMPLE_MIPMAP_HALF_RES, + SS_EFFECTS_DOWNSAMPLE_HALF, + SS_EFFECTS_DOWNSAMPLE_HALF_RES_HALF, + SS_EFFECTS_DOWNSAMPLE_FULL_MIPS, + SS_EFFECTS_MAX + }; + + struct SSEffectsGatherConstants { + float rotation_matrices[80]; //5 vec4s * 4 + }; + + struct SSEffectsShader { + SSEffectsDownsamplePushConstant downsample_push_constant; + SsEffectsDownsampleShaderRD downsample_shader; + RID downsample_shader_version; + RID downsample_uniform_set; + bool used_half_size_last_frame = false; + bool used_mips_last_frame = false; + bool used_full_mips_last_frame = false; + + RID gather_constants_buffer; + + RID mirror_sampler; + + RID pipelines[SS_EFFECTS_MAX]; + } ss_effects; + + /* SSIL */ + + enum SSILMode { + SSIL_GATHER, + SSIL_GATHER_BASE, + SSIL_GATHER_ADAPTIVE, + SSIL_GENERATE_IMPORTANCE_MAP, + SSIL_PROCESS_IMPORTANCE_MAPA, + SSIL_PROCESS_IMPORTANCE_MAPB, + SSIL_BLUR_PASS, + SSIL_BLUR_PASS_SMART, + SSIL_BLUR_PASS_WIDE, + SSIL_INTERLEAVE, + SSIL_INTERLEAVE_SMART, + SSIL_INTERLEAVE_HALF, + SSIL_MAX + }; + + struct SSILGatherPushConstant { + int32_t screen_size[2]; + int pass; + int quality; + + float half_screen_pixel_size[2]; + float half_screen_pixel_size_x025[2]; + + float NDC_to_view_mul[2]; + float NDC_to_view_add[2]; + + float pad2[2]; + float z_near; + float z_far; + + float radius; + float intensity; + int size_multiplier; + int pad; + + float fade_out_mul; + float fade_out_add; + float normal_rejection_amount; + float inv_radius_near_limit; + + uint32_t is_orthogonal; + float neg_inv_radius; + float load_counter_avg_div; + float adaptive_sample_limit; + + int32_t pass_coord_offset[2]; + float pass_uv_offset[2]; + }; + + struct SSILImportanceMapPushConstant { + float half_screen_pixel_size[2]; + float intensity; + float pad; + }; + + struct SSILBlurPushConstant { + float edge_sharpness; + float pad; + float half_screen_pixel_size[2]; + }; + + struct SSILInterleavePushConstant { + float inv_sharpness; + uint32_t size_modifier; + float pixel_size[2]; + }; + + struct SSILProjectionUniforms { + float inv_last_frame_projection_matrix[16]; + }; + + struct SSIL { + SSILGatherPushConstant gather_push_constant; + SsilShaderRD gather_shader; + RID gather_shader_version; + RID projection_uniform_buffer; + + SSILImportanceMapPushConstant importance_map_push_constant; + SsilImportanceMapShaderRD importance_map_shader; + RID importance_map_shader_version; + RID importance_map_load_counter; + RID counter_uniform_set; + + SSILBlurPushConstant blur_push_constant; + SsilBlurShaderRD blur_shader; + RID blur_shader_version; + + SSILInterleavePushConstant interleave_push_constant; + SsilInterleaveShaderRD interleave_shader; + RID interleave_shader_version; + + RID pipelines[SSIL_MAX]; + } ssil; + + void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set); + + /* SSAO */ + + enum SSAOMode { + SSAO_GATHER, + SSAO_GATHER_BASE, + SSAO_GATHER_ADAPTIVE, + SSAO_GENERATE_IMPORTANCE_MAP, + SSAO_PROCESS_IMPORTANCE_MAPA, + SSAO_PROCESS_IMPORTANCE_MAPB, + SSAO_BLUR_PASS, + SSAO_BLUR_PASS_SMART, + SSAO_BLUR_PASS_WIDE, + SSAO_INTERLEAVE, + SSAO_INTERLEAVE_SMART, + SSAO_INTERLEAVE_HALF, + SSAO_MAX + }; + + struct SSAOGatherPushConstant { + int32_t screen_size[2]; + int pass; + int quality; + + float half_screen_pixel_size[2]; + int size_multiplier; + float detail_intensity; + + float NDC_to_view_mul[2]; + float NDC_to_view_add[2]; + + float pad[2]; + float half_screen_pixel_size_x025[2]; + + float radius; + float intensity; + float shadow_power; + float shadow_clamp; + + float fade_out_mul; + float fade_out_add; + float horizon_angle_threshold; + float inv_radius_near_limit; + + uint32_t is_orthogonal; + float neg_inv_radius; + float load_counter_avg_div; + float adaptive_sample_limit; + + int32_t pass_coord_offset[2]; + float pass_uv_offset[2]; + }; + + struct SSAOImportanceMapPushConstant { + float half_screen_pixel_size[2]; + float intensity; + float power; + }; + + struct SSAOBlurPushConstant { + float edge_sharpness; + float pad; + float half_screen_pixel_size[2]; + }; + + struct SSAOInterleavePushConstant { + float inv_sharpness; + uint32_t size_modifier; + float pixel_size[2]; + }; + + struct SSAO { + SSAOGatherPushConstant gather_push_constant; + SsaoShaderRD gather_shader; + RID gather_shader_version; + + SSAOImportanceMapPushConstant importance_map_push_constant; + SsaoImportanceMapShaderRD importance_map_shader; + RID importance_map_shader_version; + RID importance_map_load_counter; + RID counter_uniform_set; + + SSAOBlurPushConstant blur_push_constant; + SsaoBlurShaderRD blur_shader; + RID blur_shader_version; + + SSAOInterleavePushConstant interleave_push_constant; + SsaoInterleaveShaderRD interleave_shader; + RID interleave_shader_version; + + RID pipelines[SSAO_MAX]; + } ssao; + + void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set); + + /* Screen Space Reflection */ + + enum SSRShaderSpecializations { + SSR_MULTIVIEW = 1 << 0, + SSR_VARIATIONS = 2, + }; + + struct ScreenSpaceReflectionSceneData { + float projection[2][16]; + float inv_projection[2][16]; + float eye_offset[2][4]; + }; + + // SSR Scale + + struct ScreenSpaceReflectionScalePushConstant { + int32_t screen_size[2]; + float camera_z_near; + float camera_z_far; + + uint32_t orthogonal; + uint32_t filter; + uint32_t view_index; + uint32_t pad1; + }; + + struct ScreenSpaceReflectionScale { + ScreenSpaceReflectionScaleShaderRD shader; + RID shader_version; + RID pipelines[SSR_VARIATIONS]; + } ssr_scale; + + // SSR main + + enum ScreenSpaceReflectionMode { + SCREEN_SPACE_REFLECTION_NORMAL, + SCREEN_SPACE_REFLECTION_ROUGH, + SCREEN_SPACE_REFLECTION_MAX, + }; + + struct ScreenSpaceReflectionPushConstant { + float proj_info[4]; // 16 - 16 + + int32_t screen_size[2]; // 8 - 24 + float camera_z_near; // 4 - 28 + float camera_z_far; // 4 - 32 + + int32_t num_steps; // 4 - 36 + float depth_tolerance; // 4 - 40 + float distance_fade; // 4 - 44 + float curve_fade_in; // 4 - 48 + + uint32_t orthogonal; // 4 - 52 + float filter_mipmap_levels; // 4 - 56 + uint32_t use_half_res; // 4 - 60 + uint8_t metallic_mask[4]; // 4 - 64 + + uint32_t view_index; // 4 - 68 + uint32_t pad[3]; // 12 - 80 + + // float projection[16]; // this is in our ScreenSpaceReflectionSceneData now + }; + + struct ScreenSpaceReflection { + ScreenSpaceReflectionShaderRD shader; + RID shader_version; + RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_MAX]; + + RID ubo; + } ssr; + + // SSR Filter + + struct ScreenSpaceReflectionFilterPushConstant { + float proj_info[4]; // 16 - 16 + + uint32_t orthogonal; // 4 - 20 + float edge_tolerance; // 4 - 24 + int32_t increment; // 4 - 28 + uint32_t view_index; // 4 - 32 + + int32_t screen_size[2]; // 8 - 40 + uint32_t vertical; // 4 - 44 + uint32_t steps; // 4 - 48 + }; + + enum SSRReflectionMode { + SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL, + SCREEN_SPACE_REFLECTION_FILTER_VERTICAL, + SCREEN_SPACE_REFLECTION_FILTER_MAX, + }; + + struct ScreenSpaceReflectionFilter { + ScreenSpaceReflectionFilterShaderRD shader; + RID shader_version; + RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX]; + } ssr_filter; +}; + +} // namespace RendererRD + +#endif // SS_EFFECTS_RD_H diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h index a90849dbeb..05db4a0cbe 100644 --- a/servers/rendering/renderer_rd/effects/tone_mapper.h +++ b/servers/rendering/renderer_rd/effects/tone_mapper.h @@ -149,4 +149,4 @@ public: } // namespace RendererRD -#endif // !TONE_MAPPER_RD_H +#endif // TONE_MAPPER_RD_H diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp new file mode 100644 index 0000000000..fa0b99fef9 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/vrs.cpp @@ -0,0 +1,171 @@ +/*************************************************************************/ +/* vrs.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "vrs.h" +#include "../renderer_compositor_rd.h" +#include "../storage_rd/texture_storage.h" +#include "../uniform_set_cache_rd.h" +#include "servers/xr_server.h" + +using namespace RendererRD; + +VRS::VRS() { + { + Vector<String> vrs_modes; + vrs_modes.push_back("\n"); // VRS_DEFAULT + vrs_modes.push_back("\n#define MULTIVIEW\n"); // VRS_MULTIVIEW + + vrs_shader.shader.initialize(vrs_modes); + + if (!RendererCompositorRD::singleton->is_xr_enabled()) { + vrs_shader.shader.set_variant_enabled(VRS_MULTIVIEW, false); + } + + vrs_shader.shader_version = vrs_shader.shader.version_create(); + + //use additive + + for (int i = 0; i < VRS_MAX; i++) { + if (vrs_shader.shader.is_variant_enabled(i)) { + vrs_shader.pipelines[i].setup(vrs_shader.shader.version_get_shader(vrs_shader.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } else { + vrs_shader.pipelines[i].clear(); + } + } + } +} + +VRS::~VRS() { + vrs_shader.shader.version_free(vrs_shader.shader_version); +} + +void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + VRSMode mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT; + + RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + 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<Color>()); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + // RD::get_singleton()->draw_list_set_push_constant(draw_list, &vrs_shader.push_constant, sizeof(VRSPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void VRS::create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb) { + // TODO find a way to skip this if VRS is not supported, but we don't have access to VulkanContext here, even though we're in vulkan.. hmmm + + // TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we + // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating + // our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size + // of the VRS buffer to supply. + Size2i texel_size = Size2i(16, 16); + + RD::TextureFormat tf; + if (p_view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + } else { + tf.texture_type = RD::TEXTURE_TYPE_2D; + } + tf.format = RD::DATA_FORMAT_R8_UINT; + tf.width = p_base_width / texel_size.x; + if (p_base_width % texel_size.x != 0) { + tf.width++; + } + tf.height = p_base_height / texel_size.y; + if (p_base_height % texel_size.y != 0) { + tf.height++; + } + tf.array_layers = p_view_count; // create a layer for every view + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + tf.samples = RD::TEXTURE_SAMPLES_1; + + p_vrs_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + // by default VRS is assumed to be our VRS attachment, but if we need to write into it, we need a bit more control + Vector<RID> fb; + fb.push_back(p_vrs_texture); + + RD::FramebufferPass pass; + pass.color_attachments.push_back(0); + + Vector<RD::FramebufferPass> passes; + passes.push_back(pass); + + p_vrs_fb = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, p_view_count); +} + +void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) { + TextureStorage *texture_storage = TextureStorage::get_singleton(); + RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target); + + if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) { + RD::get_singleton()->draw_command_begin_label("VRS Setup"); + + // TODO figure out if image has changed since it was last copied so we can save some resources.. + + if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) { + RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target); + if (vrs_texture.is_valid()) { + Texture *texture = texture_storage->get_texture(vrs_texture); + if (texture) { + // Copy into our density buffer + copy_vrs(texture->rd_texture, p_vrs_fb, texture->layers > 1); + } + } + } else if (vrs_mode == RS::VIEWPORT_VRS_XR) { + Ref<XRInterface> interface = XRServer::get_singleton()->get_primary_interface(); + if (interface.is_valid()) { + RID vrs_texture = interface->get_vrs_texture(); + if (vrs_texture.is_valid()) { + Texture *texture = texture_storage->get_texture(vrs_texture); + if (texture) { + // Copy into our density buffer + copy_vrs(texture->rd_texture, p_vrs_fb, texture->layers > 1); + } + } + } + } + + RD::get_singleton()->draw_command_end_label(); + } +} diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h new file mode 100644 index 0000000000..dd15df615e --- /dev/null +++ b/servers/rendering/renderer_rd/effects/vrs.h @@ -0,0 +1,75 @@ +/*************************************************************************/ +/* vrs.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VRS_RD_H +#define VRS_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/vrs.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" + +#include "servers/rendering_server.h" + +namespace RendererRD { + +class VRS { +private: + enum VRSMode { + VRS_DEFAULT, + VRS_MULTIVIEW, + VRS_MAX, + }; + + /* we have no push constant here (yet) + struct VRSPushConstant { + + }; + */ + + struct VRSShader { + // VRSPushConstant push_constant; + VrsShaderRD shader; + RID shader_version; + PipelineCacheRD pipelines[VRS_MAX]; + } vrs_shader; + +public: + VRS(); + ~VRS(); + + void copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview = false); + + void create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb); + void update_vrs_texture(RID p_vrs_fb, RID p_render_target); +}; + +} // namespace RendererRD + +#endif // VRS_RD_H diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index d45ddbc392..8d59b24f3f 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -41,14 +41,6 @@ bool EffectsRD::get_prefer_raster_effects() { return prefer_raster_effects; } -static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - p_array[i * 4 + j] = p_mtx.matrix[i][j]; - } - } -} - RID EffectsRD::_get_uniform_set_from_image(RID p_image) { if (image_to_uniform_set_cache.has(p_image)) { RID uniform_set = image_to_uniform_set_cache[p_image]; @@ -86,7 +78,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) u.append_id(p_texture); uniforms.push_back(u); // anything with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, specular_merge.shader.version_get_shader(specular_merge.shader_version, 0), 0); + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, 0), 0); texture_to_uniform_set_cache[p_texture] = uniform_set; @@ -116,105 +108,6 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m return uniform_set; } -RID EffectsRD::_get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler) { - TextureSamplerPair tsp; - tsp.texture = p_texture; - tsp.sampler = p_sampler; - - if (texture_sampler_to_compute_uniform_set_cache.has(tsp)) { - RID uniform_set = texture_sampler_to_compute_uniform_set_cache[tsp]; - if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - return uniform_set; - } - } - - Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(p_sampler); - u.append_id(p_texture); - uniforms.push_back(u); - //any thing with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0), 0); - - texture_sampler_to_compute_uniform_set_cache[tsp] = uniform_set; - - return uniform_set; -} - -RID EffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps) { - TexturePair tp; - tp.texture1 = p_texture1; - tp.texture2 = p_texture2; - - if (texture_pair_to_compute_uniform_set_cache.has(tp)) { - RID uniform_set = texture_pair_to_compute_uniform_set_cache[tp]; - if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - return uniform_set; - } - } - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.append_id(p_texture1); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 1; - u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.append_id(p_texture2); - uniforms.push_back(u); - } - //any thing with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 1); - - texture_pair_to_compute_uniform_set_cache[tp] = uniform_set; - - return uniform_set; -} - -RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_texture2) { - TexturePair tp; - tp.texture1 = p_texture1; - tp.texture2 = p_texture2; - - if (image_pair_to_compute_uniform_set_cache.has(tp)) { - RID uniform_set = image_pair_to_compute_uniform_set_cache[tp]; - if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - return uniform_set; - } - } - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.append_id(p_texture1); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.append_id(p_texture2); - uniforms.push_back(u); - } - //any thing with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 3); - - image_pair_to_compute_uniform_set_cache[tp] = uniform_set; - - return uniform_set; -} - void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) { memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant)); @@ -281,126 +174,7 @@ void EffectsRD::taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity RD::get_singleton()->compute_list_end(); } -void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) { - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - { //scale color and depth to half - ssr_scale.push_constant.camera_z_far = p_camera.get_z_far(); - ssr_scale.push_constant.camera_z_near = p_camera.get_z_near(); - ssr_scale.push_constant.orthogonal = p_camera.is_orthogonal(); - ssr_scale.push_constant.filter = false; //enabling causes arctifacts - ssr_scale.push_constant.screen_size[0] = p_screen_size.x; - ssr_scale.push_constant.screen_size[1] = p_screen_size.y; - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipeline); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_depth, p_normal_roughness), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output_blur), 2); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_scale_depth, p_scale_normal), 3); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_scale.push_constant, sizeof(ScreenSpaceReflectionScalePushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); - - RD::get_singleton()->compute_list_add_barrier(compute_list); - } - - { - ssr.push_constant.camera_z_far = p_camera.get_z_far(); - ssr.push_constant.camera_z_near = p_camera.get_z_near(); - ssr.push_constant.orthogonal = p_camera.is_orthogonal(); - ssr.push_constant.screen_size[0] = p_screen_size.x; - ssr.push_constant.screen_size[1] = p_screen_size.y; - ssr.push_constant.curve_fade_in = p_fade_in; - ssr.push_constant.distance_fade = p_fade_out; - ssr.push_constant.num_steps = p_max_steps; - ssr.push_constant.depth_tolerance = p_tolerance; - ssr.push_constant.use_half_res = true; - ssr.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]); - ssr.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]); - ssr.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0]; - ssr.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1]; - ssr.push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255); - ssr.push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255); - ssr.push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255); - ssr.push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255); - store_camera(p_camera, ssr.push_constant.projection); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[(p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL]); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr.push_constant, sizeof(ScreenSpaceReflectionPushConstant)); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_scale_depth), 0); - - if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 1); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 1); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_metallic), 3); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 2); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); - } - - if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { - //blur - - RD::get_singleton()->compute_list_add_barrier(compute_list); - - ssr_filter.push_constant.orthogonal = p_camera.is_orthogonal(); - ssr_filter.push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0)); - ssr_filter.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]); - ssr_filter.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]); - ssr_filter.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0]; - ssr_filter.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1]; - ssr_filter.push_constant.vertical = 0; - if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) { - ssr_filter.push_constant.steps = p_max_steps / 3; - ssr_filter.push_constant.increment = 3; - } else if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) { - ssr_filter.push_constant.steps = p_max_steps / 2; - ssr_filter.push_constant.increment = 2; - } else { - ssr_filter.push_constant.steps = p_max_steps; - ssr_filter.push_constant.increment = 1; - } - - ssr_filter.push_constant.screen_size[0] = p_screen_size.width; - ssr_filter.push_constant.screen_size[1] = p_screen_size.height; - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 2); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); - - RD::get_singleton()->compute_list_add_barrier(compute_list); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_VERTICAL]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 2); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3); - - ssr_filter.push_constant.vertical = 1; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); - } - - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) { +void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) { RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); Plane p = p_camera.xform4(Plane(1, 0, -1, 1)); @@ -443,36 +217,6 @@ void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_dept } } -void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection) { - 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_READ, Vector<Color>()); - - if (p_reflection.is_valid()) { - if (p_base.is_valid()) { - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2); - } else { - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - } - - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_reflection), 1); - - } else { - if (p_base.is_valid()) { - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2); - } else { - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - } - - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0); - } - - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) { ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer."); @@ -546,674 +290,6 @@ void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_ } } -void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection) { - // Downsample and deinterleave the depth buffer for SSAO and SSIL - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - int downsample_pipeline = SS_EFFECTS_DOWNSAMPLE; - bool use_mips = p_ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || p_ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM; - - if (p_ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && p_ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { - downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_HALF; - } else if (use_mips) { - downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP; - } - - bool use_half_size = false; - bool use_full_mips = false; - - if (p_ssao_half_size && p_ssil_half_size) { - downsample_pipeline++; - use_half_size = true; - } else if (p_ssao_half_size != p_ssil_half_size) { - if (use_mips) { - downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS; - use_full_mips = true; - } else { - // Only need the first two mipmaps, but the cost to generate the next two is trivial - // TODO investigate the benefit of a shader version to generate only 2 mips - downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP; - use_mips = true; - } - } - - int depth_index = use_half_size ? 1 : 0; - - RD::get_singleton()->draw_command_begin_label("Downsample Depth"); - if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.append_id(p_depth_mipmaps[depth_index + 1]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.append_id(p_depth_mipmaps[depth_index + 2]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 2; - u.append_id(p_depth_mipmaps[depth_index + 3]); - uniforms.push_back(u); - } - if (use_full_mips) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 3; - u.append_id(p_depth_mipmaps[4]); - uniforms.push_back(u); - } - ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2); - } - - float depth_linearize_mul = -p_projection.matrix[3][2]; - float depth_linearize_add = p_projection.matrix[2][2]; - if (depth_linearize_mul * depth_linearize_add < 0) { - depth_linearize_add = -depth_linearize_add; - } - - ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal(); - ss_effects.downsample_push_constant.z_near = depth_linearize_mul; - ss_effects.downsample_push_constant.z_far = depth_linearize_add; - if (ss_effects.downsample_push_constant.orthogonal) { - ss_effects.downsample_push_constant.z_near = p_projection.get_z_near(); - ss_effects.downsample_push_constant.z_far = p_projection.get_z_far(); - } - ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x; - ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y; - ss_effects.downsample_push_constant.radius_sq = 1.0; - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_pipeline]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[depth_index + 0]), 1); - if (use_mips) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2); - } - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant)); - - Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1))); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - RD::get_singleton()->draw_command_end_label(); - - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE); - - ss_effects.used_full_mips_last_frame = use_full_mips; - ss_effects.used_half_size_last_frame = use_half_size; -} - -void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) { - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0); - if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) { - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1); - } - - for (int i = 0; i < 4; i++) { - if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { - continue; - } - - ssao.gather_push_constant.pass_coord_offset[0] = i % 2; - ssao.gather_push_constant.pass_coord_offset[1] = i / 2; - ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x; - ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y; - ssao.gather_push_constant.pass = i; - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 2); - RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant)); - - Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); - - RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1); - } - RD::get_singleton()->compute_list_add_barrier(p_compute_list); -} - -void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set) { - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant)); - /* FIRST PASS */ - - RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion"); - /* SECOND PASS */ - // Sample SSAO - { - RD::get_singleton()->draw_command_begin_label("Gather Samples"); - ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; - ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; - - ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - float tan_half_fov_x = 1.0 / p_projection.matrix[0][0]; - float tan_half_fov_y = 1.0 / p_projection.matrix[1][1]; - ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; - ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0; - ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0; - ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; - ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); - - ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25; - ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25; - - ssao.gather_push_constant.radius = p_settings.radius; - float radius_near_limit = (p_settings.radius * 1.2f); - if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) { - radius_near_limit *= 1.50f; - - if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { - ssao.gather_push_constant.radius *= 0.8f; - } - } - radius_near_limit /= tan_half_fov_y; - ssao.gather_push_constant.intensity = p_settings.intensity; - ssao.gather_push_constant.shadow_power = p_settings.power; - ssao.gather_push_constant.shadow_clamp = 0.98; - ssao.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from); - ssao.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0; - ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon; - ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit; - ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius; - - ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255); - ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target; - - ssao.gather_push_constant.detail_intensity = p_settings.detail; - ssao.gather_push_constant.quality = MAX(0, p_settings.quality - 1); - ssao.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1; - - if (p_invalidate_uniform_sets) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(default_sampler); - u.append_id(p_depth_mipmaps_texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.append_id(p_normal_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.append_id(ss_effects.gather_constants_buffer); - uniforms.push_back(u); - } - r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0); - } - - if (p_invalidate_uniform_sets) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.append_id(p_ao_pong); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 1; - u.append_id(default_sampler); - u.append_id(p_importance_map); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 2; - u.append_id(ssao.importance_map_load_counter); - uniforms.push_back(u); - } - r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1); - } - - if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) { - RD::get_singleton()->draw_command_begin_label("Generate Importance Map"); - ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - ssao.importance_map_push_constant.intensity = p_settings.intensity; - ssao.importance_map_push_constant.power = p_settings.power; - //base pass - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]); - gather_ssao(compute_list, p_ao_pong_slices, p_settings, true, r_gather_uniform_set, RID()); - //generate importance map - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - //process importance map A - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - //process Importance Map B - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]); - RD::get_singleton()->draw_command_end_label(); // Importance Map - } else { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]); - } - - gather_ssao(compute_list, p_ao_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set); - RD::get_singleton()->draw_command_end_label(); // Gather SSAO - } - - // /* THIRD PASS */ - // // Blur - // - { - RD::get_singleton()->draw_command_begin_label("Edge Aware Blur"); - ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness; - ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - - int blur_passes = p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? p_settings.blur_passes : 1; - - for (int pass = 0; pass < blur_passes; pass++) { - int blur_pipeline = SSAO_BLUR_PASS; - if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { - blur_pipeline = SSAO_BLUR_PASS_SMART; - if (pass < blur_passes - 2) { - blur_pipeline = SSAO_BLUR_PASS_WIDE; - } else { - blur_pipeline = SSAO_BLUR_PASS_SMART; - } - } - - for (int i = 0; i < 4; i++) { - if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { - continue; - } - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]); - if (pass % 2 == 0) { - if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_slices[i]), 0); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_slices[i], ss_effects.mirror_sampler), 0); - } - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_pong_slices[i]), 1); - } else { - if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong_slices[i]), 0); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_pong_slices[i], ss_effects.mirror_sampler), 0); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 1); - } - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); - - Size2i size(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1); - } - - if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_add_barrier(compute_list); - } - } - RD::get_singleton()->draw_command_end_label(); // Blur - } - - /* FOURTH PASS */ - // Interleave buffers - // back to full size - { - RD::get_singleton()->draw_command_begin_label("Interleave Buffers"); - ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness; - ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; - ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y; - ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2); - - int interleave_pipeline = SSAO_INTERLEAVE_HALF; - if (p_settings.quality == RS::ENV_SSAO_QUALITY_LOW) { - interleave_pipeline = SSAO_INTERLEAVE; - } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) { - interleave_pipeline = SSAO_INTERLEAVE_SMART; - } - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_upscale_buffer), 0); - if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao), 1); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 1); - } - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - RD::get_singleton()->draw_command_end_label(); // Interleave - } - RD::get_singleton()->draw_command_end_label(); //SSAO - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer - - int zero[1] = { 0 }; - RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier -} - -void EffectsRD::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) { - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0); - if ((p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) { - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1); - } - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3); - - for (int i = 0; i < 4; i++) { - if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { - continue; - } - - ssil.gather_push_constant.pass_coord_offset[0] = i % 2; - ssil.gather_push_constant.pass_coord_offset[1] = i / 2; - ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x; - ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y; - ssil.gather_push_constant.pass = i; - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_compute_uniform_set_from_image_pair(p_ssil_slices[i], p_edges_slices[i]), 2); - RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant)); - - Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); - - RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1); - } - RD::get_singleton()->compute_list_add_barrier(p_compute_list); -} - -void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ssil, const Vector<RID> p_ssil_slices, RID p_ssil_pong, const Vector<RID> p_ssil_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set) { - RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting"); - //Store projection info before starting the compute list - SSILProjectionUniforms projection_uniforms; - store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix); - - RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms); - - memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant)); - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - { - RD::get_singleton()->draw_command_begin_label("Gather Samples"); - ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; - ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; - - ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - float tan_half_fov_x = 1.0 / p_projection.matrix[0][0]; - float tan_half_fov_y = 1.0 / p_projection.matrix[1][1]; - ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; - ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0; - ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0; - ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; - ssil.gather_push_constant.z_near = p_projection.get_z_near(); - ssil.gather_push_constant.z_far = p_projection.get_z_far(); - ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); - - ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25; - ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25; - - ssil.gather_push_constant.radius = p_settings.radius; - float radius_near_limit = (p_settings.radius * 1.2f); - if (p_settings.quality <= RS::ENV_SSIL_QUALITY_LOW) { - radius_near_limit *= 1.50f; - - if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { - ssil.gather_push_constant.radius *= 0.8f; - } - } - radius_near_limit /= tan_half_fov_y; - ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI; - ssil.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from); - ssil.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0; - ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit; - ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius; - ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection; - - ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255); - ssil.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target; - - ssil.gather_push_constant.quality = MAX(0, p_settings.quality - 1); - ssil.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1; - - if (p_invalidate_uniform_sets) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(default_mipmap_sampler); - u.append_id(p_diffuse); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 1; - u.append_id(ssil.projection_uniform_buffer); - uniforms.push_back(u); - } - r_projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3); - } - - if (p_invalidate_uniform_sets) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(default_sampler); - u.append_id(p_depth_mipmaps_texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.append_id(p_normal_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.append_id(ss_effects.gather_constants_buffer); - uniforms.push_back(u); - } - r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0); - } - - if (p_invalidate_uniform_sets) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.append_id(p_ssil_pong); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 1; - u.append_id(default_sampler); - u.append_id(p_importance_map); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 2; - u.append_id(ssil.importance_map_load_counter); - uniforms.push_back(u); - } - r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1); - } - - if (p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) { - RD::get_singleton()->draw_command_begin_label("Generate Importance Map"); - ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI; - //base pass - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]); - gather_ssil(compute_list, p_ssil_pong_slices, p_edges_slices, p_settings, true, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set); - //generate importance map - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - // process Importance Map A - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - // process Importance Map B - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - RD::get_singleton()->draw_command_end_label(); // Importance Map - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]); - } else { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]); - } - - gather_ssil(compute_list, p_ssil_slices, p_edges_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set); - RD::get_singleton()->draw_command_end_label(); //Gather - } - - { - RD::get_singleton()->draw_command_begin_label("Edge Aware Blur"); - ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness; - ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; - ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; - - int blur_passes = p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? p_settings.blur_passes : 1; - - for (int pass = 0; pass < blur_passes; pass++) { - int blur_pipeline = SSIL_BLUR_PASS; - if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) { - blur_pipeline = SSIL_BLUR_PASS_SMART; - if (pass < blur_passes - 2) { - blur_pipeline = SSIL_BLUR_PASS_WIDE; - } - } - - for (int i = 0; i < 4; i++) { - if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { - continue; - } - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]); - if (pass % 2 == 0) { - if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_slices[i]), 0); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_slices[i], ss_effects.mirror_sampler), 0); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_pong_slices[i]), 1); - } else { - if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong_slices[i]), 0); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_pong_slices[i], ss_effects.mirror_sampler), 0); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_slices[i]), 1); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges_slices[i]), 2); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant)); - - int x_groups = (p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)); - int y_groups = (p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1); - if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) { - RD::get_singleton()->compute_list_add_barrier(compute_list); - } - } - } - - RD::get_singleton()->draw_command_end_label(); // Blur - } - - { - RD::get_singleton()->draw_command_begin_label("Interleave Buffers"); - ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness; - ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; - ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y; - ssil.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2); - - int interleave_pipeline = SSIL_INTERLEAVE_HALF; - if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) { - interleave_pipeline = SSIL_INTERLEAVE; - } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) { - interleave_pipeline = SSIL_INTERLEAVE_SMART; - } - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination), 0); - - if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil), 1); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 1); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges), 2); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - RD::get_singleton()->draw_command_end_label(); // Interleave - } - - RD::get_singleton()->draw_command_end_label(); // SSIL - - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); - - int zero[1] = { 0 }; - RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier -} - void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) { roughness_limiter.push_constant.screen_size[0] = p_size.x; roughness_limiter.push_constant.screen_size[1] = p_size.y; @@ -1304,12 +380,12 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { { Vector<String> FSR_upscale_modes; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) // MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though. FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); #else // Everyone else can use normal mode when available. - if (RD::get_singleton()->get_device_capabilities()->supports_fsr_half_float) { + if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) { FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n"); } else { FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); @@ -1358,154 +434,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } if (!prefer_raster_effects) { - { - // Initialize depth buffer for screen space effects - Vector<String> downsampler_modes; - downsampler_modes.push_back("\n"); - downsampler_modes.push_back("\n#define USE_HALF_SIZE\n"); - downsampler_modes.push_back("\n#define GENERATE_MIPS\n"); - downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n"); - downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n"); - downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n"); - downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS"); - - ss_effects.downsample_shader.initialize(downsampler_modes); - - ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create(); - - for (int i = 0; i < SS_EFFECTS_MAX; i++) { - ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i)); - } - - ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants)); - SSEffectsGatherConstants gather_constants; - - const int sub_pass_count = 5; - for (int pass = 0; pass < 4; pass++) { - for (int subPass = 0; subPass < sub_pass_count; subPass++) { - int a = pass; - int b = subPass; - - int spmap[5]{ 0, 1, 4, 3, 2 }; - b = spmap[subPass]; - - float ca, sa; - float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f; - - ca = Math::cos(angle0); - sa = Math::sin(angle0); - - float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f; - - gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca; - gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa; - gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa; - gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca; - } - } - - RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants); - } - - { - // Initialize ssao - - RD::SamplerState sampler; - sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler.min_filter = RD::SAMPLER_FILTER_NEAREST; - sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST; - sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - sampler.max_lod = 4; - - ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler); - - uint32_t pipeline = 0; - { - Vector<String> ssao_modes; - - ssao_modes.push_back("\n"); - ssao_modes.push_back("\n#define SSAO_BASE\n"); - ssao_modes.push_back("\n#define ADAPTIVE\n"); - - ssao.gather_shader.initialize(ssao_modes); - - ssao.gather_shader_version = ssao.gather_shader.version_create(); - - for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i)); - pipeline++; - } - } - { - Vector<String> ssao_modes; - ssao_modes.push_back("\n#define GENERATE_MAP\n"); - ssao_modes.push_back("\n#define PROCESS_MAPA\n"); - ssao_modes.push_back("\n#define PROCESS_MAPB\n"); - - ssao.importance_map_shader.initialize(ssao_modes); - - ssao.importance_map_shader_version = ssao.importance_map_shader.version_create(); - - for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP)); - - pipeline++; - } - ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t)); - int zero[1] = { 0 }; - RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero); - RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter"); - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(ssao.importance_map_load_counter); - uniforms.push_back(u); - } - ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2); - RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set"); - } - { - Vector<String> ssao_modes; - ssao_modes.push_back("\n#define MODE_NON_SMART\n"); - ssao_modes.push_back("\n#define MODE_SMART\n"); - ssao_modes.push_back("\n#define MODE_WIDE\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_PASS_WIDE; 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++; - } - } - { - Vector<String> ssao_modes; - ssao_modes.push_back("\n#define MODE_NON_SMART\n"); - ssao_modes.push_back("\n#define MODE_SMART\n"); - ssao_modes.push_back("\n#define MODE_HALF\n"); - - ssao.interleave_shader.initialize(ssao_modes); - - ssao.interleave_shader_version = ssao.interleave_shader.version_create(); - for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE)); - RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i)); - pipeline++; - } - } - - ERR_FAIL_COND(pipeline != SSAO_MAX); - } - } - - if (!prefer_raster_effects) { // Initialize roughness limiter Vector<String> shader_modes; shader_modes.push_back(""); @@ -1518,81 +446,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } if (!prefer_raster_effects) { - Vector<String> specular_modes; - specular_modes.push_back("\n#define MODE_MERGE\n"); - specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n"); - specular_modes.push_back("\n"); - specular_modes.push_back("\n#define MODE_SSR\n"); - - specular_merge.shader.initialize(specular_modes); - - specular_merge.shader_version = specular_merge.shader.version_create(); - - //use additive - - RD::PipelineColorBlendState::Attachment ba; - ba.enable_blend = true; - ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE; - ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; - ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - ba.color_blend_op = RD::BLEND_OP_ADD; - ba.alpha_blend_op = RD::BLEND_OP_ADD; - - RD::PipelineColorBlendState blend_additive; - blend_additive.attachments.push_back(ba); - - for (int i = 0; i < SPECULAR_MERGE_MAX; i++) { - RD::PipelineColorBlendState blend_state; - if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR) { - blend_state = blend_additive; - } else { - blend_state = RD::PipelineColorBlendState::create_disabled(); - } - specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); - } - } - - if (!prefer_raster_effects) { - { - Vector<String> ssr_modes; - ssr_modes.push_back("\n"); - ssr_modes.push_back("\n#define MODE_ROUGH\n"); - - ssr.shader.initialize(ssr_modes); - - ssr.shader_version = ssr.shader.version_create(); - - for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) { - ssr.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i)); - } - } - - { - Vector<String> ssr_filter_modes; - ssr_filter_modes.push_back("\n"); - ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n"); - - ssr_filter.shader.initialize(ssr_filter_modes); - - ssr_filter.shader_version = ssr_filter.shader.version_create(); - - for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) { - ssr_filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i)); - } - } - - { - Vector<String> ssr_scale_modes; - ssr_scale_modes.push_back("\n"); - - ssr_scale.shader.initialize(ssr_scale_modes); - - ssr_scale.shader_version = ssr_scale.shader.version_create(); - - ssr_scale.pipeline = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0)); - } - { Vector<String> sss_modes; sss_modes.push_back("\n#define USE_11_SAMPLES\n"); @@ -1607,79 +460,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i)); } } - - { - Vector<String> ssil_modes; - ssil_modes.push_back("\n"); - ssil_modes.push_back("\n#define SSIL_BASE\n"); - ssil_modes.push_back("\n#define ADAPTIVE\n"); - - ssil.gather_shader.initialize(ssil_modes); - - ssil.gather_shader_version = ssil.gather_shader.version_create(); - - for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) { - ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i)); - } - ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms)); - } - - { - Vector<String> ssil_modes; - ssil_modes.push_back("\n#define GENERATE_MAP\n"); - ssil_modes.push_back("\n#define PROCESS_MAPA\n"); - ssil_modes.push_back("\n#define PROCESS_MAPB\n"); - - ssil.importance_map_shader.initialize(ssil_modes); - - ssil.importance_map_shader_version = ssil.importance_map_shader.version_create(); - - for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) { - ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP)); - } - ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t)); - int zero[1] = { 0 }; - RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero); - RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter"); - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(ssil.importance_map_load_counter); - uniforms.push_back(u); - } - ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2); - RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set"); - } - { - Vector<String> ssil_modes; - ssil_modes.push_back("\n#define MODE_NON_SMART\n"); - ssil_modes.push_back("\n#define MODE_SMART\n"); - ssil_modes.push_back("\n#define MODE_WIDE\n"); - - ssil.blur_shader.initialize(ssil_modes); - - ssil.blur_shader_version = ssil.blur_shader.version_create(); - for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) { - ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS)); - } - } - - { - Vector<String> ssil_modes; - ssil_modes.push_back("\n#define MODE_NON_SMART\n"); - ssil_modes.push_back("\n#define MODE_SMART\n"); - ssil_modes.push_back("\n#define MODE_HALF\n"); - - ssil.interleave_shader.initialize(ssil_modes); - - ssil.interleave_shader_version = ssil.interleave_shader.version_create(); - for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) { - ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE)); - } - } } { @@ -1751,27 +531,8 @@ EffectsRD::~EffectsRD() { luminance_reduce.shader.version_free(luminance_reduce.shader_version); } if (!prefer_raster_effects) { - specular_merge.shader.version_free(specular_merge.shader_version); - ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version); - ssao.blur_shader.version_free(ssao.blur_shader_version); - ssao.gather_shader.version_free(ssao.gather_shader_version); - ssao.interleave_shader.version_free(ssao.interleave_shader_version); - ssao.importance_map_shader.version_free(ssao.importance_map_shader_version); - ssil.blur_shader.version_free(ssil.blur_shader_version); - ssil.gather_shader.version_free(ssil.gather_shader_version); - ssil.interleave_shader.version_free(ssil.interleave_shader_version); - ssil.importance_map_shader.version_free(ssil.importance_map_shader_version); roughness_limiter.shader.version_free(roughness_limiter.shader_version); - ssr.shader.version_free(ssr.shader_version); - ssr_filter.shader.version_free(ssr_filter.shader_version); - ssr_scale.shader.version_free(ssr_scale.shader_version); sss.shader.version_free(sss.shader_version); - - RD::get_singleton()->free(ss_effects.mirror_sampler); - RD::get_singleton()->free(ss_effects.gather_constants_buffer); - RD::get_singleton()->free(ssao.importance_map_load_counter); - RD::get_singleton()->free(ssil.importance_map_load_counter); - RD::get_singleton()->free(ssil.projection_uniform_buffer); } sort.shader.version_free(sort.shader_version); } diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index 76627a8d7d..94cd26fae9 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -31,26 +31,13 @@ #ifndef EFFECTS_RD_H #define EFFECTS_RD_H -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/specular_merge.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssao.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssao_blur.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssao_interleave.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssil.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssil_blur.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/ssil_interleave.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/taa_resolve.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" @@ -142,231 +129,6 @@ private: PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX]; } luminance_reduce_raster; - struct SSEffectsDownsamplePushConstant { - float pixel_size[2]; - float z_far; - float z_near; - uint32_t orthogonal; - float radius_sq; - uint32_t pad[2]; - }; - - enum SSEffectsMode { - SS_EFFECTS_DOWNSAMPLE, - SS_EFFECTS_DOWNSAMPLE_HALF_RES, - SS_EFFECTS_DOWNSAMPLE_MIPMAP, - SS_EFFECTS_DOWNSAMPLE_MIPMAP_HALF_RES, - SS_EFFECTS_DOWNSAMPLE_HALF, - SS_EFFECTS_DOWNSAMPLE_HALF_RES_HALF, - SS_EFFECTS_DOWNSAMPLE_FULL_MIPS, - SS_EFFECTS_MAX - }; - - struct SSEffectsGatherConstants { - float rotation_matrices[80]; //5 vec4s * 4 - }; - - struct SSEffects { - SSEffectsDownsamplePushConstant downsample_push_constant; - SsEffectsDownsampleShaderRD downsample_shader; - RID downsample_shader_version; - RID downsample_uniform_set; - bool used_half_size_last_frame = false; - bool used_mips_last_frame = false; - bool used_full_mips_last_frame = false; - - RID gather_constants_buffer; - - RID mirror_sampler; - - RID pipelines[SS_EFFECTS_MAX]; - } ss_effects; - - enum SSAOMode { - SSAO_GATHER, - SSAO_GATHER_BASE, - SSAO_GATHER_ADAPTIVE, - SSAO_GENERATE_IMPORTANCE_MAP, - SSAO_PROCESS_IMPORTANCE_MAPA, - SSAO_PROCESS_IMPORTANCE_MAPB, - SSAO_BLUR_PASS, - SSAO_BLUR_PASS_SMART, - SSAO_BLUR_PASS_WIDE, - SSAO_INTERLEAVE, - SSAO_INTERLEAVE_SMART, - SSAO_INTERLEAVE_HALF, - SSAO_MAX - }; - - struct SSAOGatherPushConstant { - int32_t screen_size[2]; - int pass; - int quality; - - float half_screen_pixel_size[2]; - int size_multiplier; - float detail_intensity; - - float NDC_to_view_mul[2]; - float NDC_to_view_add[2]; - - float pad[2]; - float half_screen_pixel_size_x025[2]; - - float radius; - float intensity; - float shadow_power; - float shadow_clamp; - - float fade_out_mul; - float fade_out_add; - float horizon_angle_threshold; - float inv_radius_near_limit; - - uint32_t is_orthogonal; - float neg_inv_radius; - float load_counter_avg_div; - float adaptive_sample_limit; - - int32_t pass_coord_offset[2]; - float pass_uv_offset[2]; - }; - - struct SSAOImportanceMapPushConstant { - float half_screen_pixel_size[2]; - float intensity; - float power; - }; - - struct SSAOBlurPushConstant { - float edge_sharpness; - float pad; - float half_screen_pixel_size[2]; - }; - - struct SSAOInterleavePushConstant { - float inv_sharpness; - uint32_t size_modifier; - float pixel_size[2]; - }; - - struct SSAO { - SSAOGatherPushConstant gather_push_constant; - SsaoShaderRD gather_shader; - RID gather_shader_version; - - SSAOImportanceMapPushConstant importance_map_push_constant; - SsaoImportanceMapShaderRD importance_map_shader; - RID importance_map_shader_version; - RID importance_map_load_counter; - RID counter_uniform_set; - - SSAOBlurPushConstant blur_push_constant; - SsaoBlurShaderRD blur_shader; - RID blur_shader_version; - - SSAOInterleavePushConstant interleave_push_constant; - SsaoInterleaveShaderRD interleave_shader; - RID interleave_shader_version; - - RID pipelines[SSAO_MAX]; - } ssao; - - enum SSILMode { - SSIL_GATHER, - SSIL_GATHER_BASE, - SSIL_GATHER_ADAPTIVE, - SSIL_GENERATE_IMPORTANCE_MAP, - SSIL_PROCESS_IMPORTANCE_MAPA, - SSIL_PROCESS_IMPORTANCE_MAPB, - SSIL_BLUR_PASS, - SSIL_BLUR_PASS_SMART, - SSIL_BLUR_PASS_WIDE, - SSIL_INTERLEAVE, - SSIL_INTERLEAVE_SMART, - SSIL_INTERLEAVE_HALF, - SSIL_MAX - }; - - struct SSILGatherPushConstant { - int32_t screen_size[2]; - int pass; - int quality; - - float half_screen_pixel_size[2]; - float half_screen_pixel_size_x025[2]; - - float NDC_to_view_mul[2]; - float NDC_to_view_add[2]; - - float pad2[2]; - float z_near; - float z_far; - - float radius; - float intensity; - int size_multiplier; - int pad; - - float fade_out_mul; - float fade_out_add; - float normal_rejection_amount; - float inv_radius_near_limit; - - uint32_t is_orthogonal; - float neg_inv_radius; - float load_counter_avg_div; - float adaptive_sample_limit; - - int32_t pass_coord_offset[2]; - float pass_uv_offset[2]; - }; - - struct SSILImportanceMapPushConstant { - float half_screen_pixel_size[2]; - float intensity; - float pad; - }; - - struct SSILBlurPushConstant { - float edge_sharpness; - float pad; - float half_screen_pixel_size[2]; - }; - - struct SSILInterleavePushConstant { - float inv_sharpness; - uint32_t size_modifier; - float pixel_size[2]; - }; - - struct SSILProjectionUniforms { - float inv_last_frame_projection_matrix[16]; - }; - - struct SSIL { - SSILGatherPushConstant gather_push_constant; - SsilShaderRD gather_shader; - RID gather_shader_version; - RID projection_uniform_buffer; - - SSILImportanceMapPushConstant importance_map_push_constant; - SsilImportanceMapShaderRD importance_map_shader; - RID importance_map_shader_version; - RID importance_map_load_counter; - RID counter_uniform_set; - - SSILBlurPushConstant blur_push_constant; - SsilBlurShaderRD blur_shader; - RID blur_shader_version; - - SSILInterleavePushConstant interleave_push_constant; - SsilInterleaveShaderRD interleave_shader; - RID interleave_shader_version; - - RID pipelines[SSIL_MAX]; - } ssil; - struct RoughnessLimiterPushConstant { int32_t screen_size[2]; float curve; @@ -381,101 +143,6 @@ private: } roughness_limiter; - enum SpecularMergeMode { - SPECULAR_MERGE_ADD, - SPECULAR_MERGE_SSR, - SPECULAR_MERGE_ADDITIVE_ADD, - SPECULAR_MERGE_ADDITIVE_SSR, - SPECULAR_MERGE_MAX - }; - - /* Specular merge must be done using raster, rather than compute - * because it must continue the existing color buffer - */ - - struct SpecularMerge { - SpecularMergeShaderRD shader; - RID shader_version; - PipelineCacheRD pipelines[SPECULAR_MERGE_MAX]; - - } specular_merge; - - enum ScreenSpaceReflectionMode { - SCREEN_SPACE_REFLECTION_NORMAL, - SCREEN_SPACE_REFLECTION_ROUGH, - SCREEN_SPACE_REFLECTION_MAX, - }; - - struct ScreenSpaceReflectionPushConstant { - float proj_info[4]; - - int32_t screen_size[2]; - float camera_z_near; - float camera_z_far; - - int32_t num_steps; - float depth_tolerance; - float distance_fade; - float curve_fade_in; - - uint32_t orthogonal; - float filter_mipmap_levels; - uint32_t use_half_res; - uint8_t metallic_mask[4]; - - float projection[16]; - }; - - struct ScreenSpaceReflection { - ScreenSpaceReflectionPushConstant push_constant; - ScreenSpaceReflectionShaderRD shader; - RID shader_version; - RID pipelines[SCREEN_SPACE_REFLECTION_MAX]; - - } ssr; - - struct ScreenSpaceReflectionFilterPushConstant { - float proj_info[4]; - - uint32_t orthogonal; - float edge_tolerance; - int32_t increment; - uint32_t pad; - - int32_t screen_size[2]; - uint32_t vertical; - uint32_t steps; - }; - enum { - SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL, - SCREEN_SPACE_REFLECTION_FILTER_VERTICAL, - SCREEN_SPACE_REFLECTION_FILTER_MAX, - }; - - struct ScreenSpaceReflectionFilter { - ScreenSpaceReflectionFilterPushConstant push_constant; - ScreenSpaceReflectionFilterShaderRD shader; - RID shader_version; - RID pipelines[SCREEN_SPACE_REFLECTION_FILTER_MAX]; - } ssr_filter; - - struct ScreenSpaceReflectionScalePushConstant { - int32_t screen_size[2]; - float camera_z_near; - float camera_z_far; - - uint32_t orthogonal; - uint32_t filter; - uint32_t pad[2]; - }; - - struct ScreenSpaceReflectionScale { - ScreenSpaceReflectionScalePushConstant push_constant; - ScreenSpaceReflectionScaleShaderRD shader; - RID shader_version; - RID pipeline; - } ssr_scale; - struct SubSurfaceScatteringPushConstant { int32_t screen_size[2]; float camera_z_far; @@ -559,9 +226,6 @@ private: RID _get_uniform_set_from_image(RID p_texture); RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); - RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler); - RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false); - RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2); public: bool get_prefer_raster_effects(); @@ -572,57 +236,9 @@ public: void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); - struct SSAOSettings { - float radius = 1.0; - float intensity = 2.0; - float power = 1.5; - float detail = 0.5; - float horizon = 0.06; - float sharpness = 0.98; - - RS::EnvironmentSSAOQuality quality = RS::ENV_SSAO_QUALITY_MEDIUM; - bool half_size = false; - float adaptive_target = 0.5; - int blur_passes = 2; - float fadeout_from = 50.0; - float fadeout_to = 300.0; - - Size2i full_screen_size = Size2i(); - Size2i half_screen_size = Size2i(); - Size2i quarter_screen_size = Size2i(); - }; - - struct SSILSettings { - float radius = 1.0; - float intensity = 2.0; - float sharpness = 0.98; - float normal_rejection = 1.0; - - RS::EnvironmentSSILQuality quality = RS::ENV_SSIL_QUALITY_MEDIUM; - bool half_size = true; - float adaptive_target = 0.5; - int blur_passes = 4; - float fadeout_from = 50.0; - float fadeout_to = 300.0; - - Size2i full_screen_size = Size2i(); - Size2i half_screen_size = Size2i(); - Size2i quarter_screen_size = Size2i(); - }; - - void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection); - - void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set); - void generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set); - - void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set); - void screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set); - void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve); - void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera); - void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection); - void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality); + void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality); void sort_buffer(RID p_uniform_set, int p_size); @@ -630,4 +246,4 @@ public: ~EffectsRD(); }; -#endif // !RASTERIZER_EFFECTS_RD_H +#endif // EFFECTS_RD_H diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 2a6c96480e..987c1dbb52 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -30,6 +30,11 @@ #include "fog.h" +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" +#include "servers/rendering/rendering_server_default.h" + using namespace RendererRD; Fog *Fog::singleton = nullptr; @@ -126,3 +131,1074 @@ Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const { ERR_FAIL_COND_V(!fog_volume, Vector3()); return fog_volume->extents; } + +//////////////////////////////////////////////////////////////////////////////// +// Fog material + +bool Fog::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + uniform_set_updated = true; + + return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL); +} + +Fog::FogMaterialData::~FogMaterialData() { + free_parameters_uniform_set(uniform_set); +} + +RendererRD::ShaderData *Fog::_create_fog_shader_func() { + FogShaderData *shader_data = memnew(FogShaderData); + return shader_data; +} + +RendererRD::ShaderData *Fog::_create_fog_shader_funcs() { + return Fog::get_singleton()->_create_fog_shader_func(); +}; + +RendererRD::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) { + FogMaterialData *material_data = memnew(FogMaterialData); + material_data->shader_data = p_shader; + //update will happen later anyway so do nothing. + return material_data; +} + +RendererRD::MaterialData *Fog::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) { + return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); +}; + +//////////////////////////////////////////////////////////////////////////////// +// FOG VOLUMES INSTANCE + +RID Fog::fog_volume_instance_create(RID p_fog_volume) { + FogVolumeInstance fvi; + fvi.volume = p_fog_volume; + return fog_volume_instance_owner.make_rid(fvi); +} + +void Fog::fog_instance_free(RID p_rid) { + fog_volume_instance_owner.free(p_rid); +} + +//////////////////////////////////////////////////////////////////////////////// +// Volumetric Fog Shader + +void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array) { + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + + { + // Initialize local fog shader + Vector<String> volumetric_fog_modes; + volumetric_fog_modes.push_back(""); + volumetric_fog.shader.initialize(volumetric_fog_modes); + + material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs); + volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO)); + } + + { + ShaderCompiler::DefaultIdentifierActions actions; + + actions.renames["TIME"] = "scene_params.time"; + actions.renames["PI"] = _MKSTR(Math_PI); + actions.renames["TAU"] = _MKSTR(Math_TAU); + actions.renames["E"] = _MKSTR(Math_E); + actions.renames["WORLD_POSITION"] = "world.xyz"; + actions.renames["OBJECT_POSITION"] = "params.position"; + actions.renames["UVW"] = "uvw"; + actions.renames["EXTENTS"] = "params.extents"; + actions.renames["ALBEDO"] = "albedo"; + actions.renames["DENSITY"] = "density"; + actions.renames["EMISSION"] = "emission"; + actions.renames["SDF"] = "sdf"; + + actions.usage_defines["SDF"] = "#define SDF_USED\n"; + actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n"; + actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n"; + actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n"; + + actions.sampler_array_name = "material_samplers"; + actions.base_texture_binding_index = 1; + actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL; + actions.base_uniform_string = "material."; + + actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; + actions.default_repeat = ShaderLanguage::REPEAT_DISABLE; + actions.global_buffer_array_variable = "global_variables.data"; + + volumetric_fog.compiler.initialize(actions); + } + + { + // default material and shader for fog shader + volumetric_fog.default_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(volumetric_fog.default_shader); + material_storage->shader_set_code(volumetric_fog.default_shader, R"( +// Default fog shader. + +shader_type fog; + +void fog() { +DENSITY = 1.0; +ALBEDO = vec3(1.0); +} +)"); + volumetric_fog.default_material = material_storage->material_allocate(); + material_storage->material_initialize(volumetric_fog.default_material); + material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader); + + FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG)); + volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0); + + Vector<RD::Uniform> uniforms; + + { + Vector<RID> ids; + ids.resize(12); + RID *ids_ptr = ids.ptrw(); + ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + + RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); + uniforms.push_back(u); + } + + volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE); + } + { + String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(p_max_directional_lights) + "\n"; + defines += "\n#define MAX_SKY_LOD " + itos(p_roughness_layers - 1) + ".0\n"; + if (p_is_using_radiance_cubemap_array) { + defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; + } + Vector<String> volumetric_fog_modes; + volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n"); + volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n"); + volumetric_fog_modes.push_back("\n#define MODE_FILTER\n"); + volumetric_fog_modes.push_back("\n#define MODE_FOG\n"); + volumetric_fog_modes.push_back("\n#define MODE_COPY\n"); + + volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines); + volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create(); + for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) { + volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i)); + } + volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO)); + } +} + +void Fog::free_fog_shader() { + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + + volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version); + RD::get_singleton()->free(volumetric_fog.volume_ubo); + RD::get_singleton()->free(volumetric_fog.params_ubo); + material_storage->shader_free(volumetric_fog.default_shader); + material_storage->material_free(volumetric_fog.default_material); +} + +void Fog::FogShaderData::set_path_hint(const String &p_path) { + path = p_path; +} + +void Fog::FogShaderData::set_code(const String &p_code) { + //compile + + code = p_code; + valid = false; + ubo_size = 0; + uniforms.clear(); + + if (code.is_empty()) { + return; //just invalid, but no error + } + + ShaderCompiler::GeneratedCode gen_code; + ShaderCompiler::IdentifierActions actions; + actions.entry_point_stages["fog"] = ShaderCompiler::STAGE_COMPUTE; + + uses_time = false; + + actions.usage_flag_pointers["TIME"] = &uses_time; + + actions.uniforms = &uniforms; + + Fog *fog_singleton = Fog::get_singleton(); + + Error err = fog_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code); + ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed."); + + if (version.is_null()) { + version = fog_singleton->volumetric_fog.shader.version_create(); + } + + fog_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines); + ERR_FAIL_COND(!fog_singleton->volumetric_fog.shader.version_is_valid(version)); + + ubo_size = gen_code.uniform_total_size; + ubo_offsets = gen_code.uniform_offsets; + texture_uniforms = gen_code.texture_uniforms; + + pipeline = RD::get_singleton()->compute_pipeline_create(fog_singleton->volumetric_fog.shader.version_get_shader(version, 0)); + + valid = true; +} + +void Fog::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { + if (!p_texture.is_valid()) { + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } + } else { + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = HashMap<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; + } +} + +void Fog::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { + RBMap<int, StringName> order; + + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + continue; + } + + if (E.value.texture_order >= 0) { + order[E.value.texture_order + 100000] = E.key; + } else { + order[E.value.order] = E.key; + } + } + + String last_group; + for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); + pi.name = E.value; + p_param_list->push_back(pi); + } +} + +void Fog::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + continue; + } + + RendererMaterialStorage::InstanceShaderParam p; + p.info = ShaderLanguage::uniform_to_property_info(E.value); + p.info.name = E.key; //supply name + p.index = E.value.instance_index; + p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); + p_param_list->push_back(p); + } +} + +bool Fog::FogShaderData::is_param_texture(const StringName &p_param) const { + if (!uniforms.has(p_param)) { + return false; + } + + return uniforms[p_param].texture_order >= 0; +} + +bool Fog::FogShaderData::is_animated() const { + return false; +} + +bool Fog::FogShaderData::casts_shadows() const { + return false; +} + +Variant Fog::FogShaderData::get_default_parameter(const StringName &p_parameter) const { + if (uniforms.has(p_parameter)) { + ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; + Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; + return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); + } + return Variant(); +} + +RS::ShaderNativeSourceCode Fog::FogShaderData::get_native_source_code() const { + Fog *fog_singleton = Fog::get_singleton(); + + return fog_singleton->volumetric_fog.shader.version_get_native_source_code(version); +} + +Fog::FogShaderData::~FogShaderData() { + Fog *fog_singleton = Fog::get_singleton(); + ERR_FAIL_COND(!fog_singleton); + //pipeline variants will clear themselves if shader is gone + if (version.is_valid()) { + fog_singleton->volumetric_fog.shader.version_free(version); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Volumetric Fog + +Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) { + width = fog_size.x; + height = fog_size.y; + depth = fog_size.z; + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = fog_size.x; + tf.height = fog_size.y; + tf.depth = fog_size.z; + tf.texture_type = RD::TEXTURE_TYPE_3D; + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + + light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(light_density_map, "Fog light-density map"); + + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + + prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(prev_light_density_map, "Fog previous light-density map"); + RD::get_singleton()->texture_clear(prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1); + + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + + fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(fog_map, "Fog map"); + +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + Vector<uint8_t> dm; + dm.resize(fog_size.x * fog_size.y * fog_size.z * 4); + dm.fill(0); + + density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); + RD::get_singleton()->set_resource_name(density_map, "Fog density map"); + light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); + RD::get_singleton()->set_resource_name(light_map, "Fog light map"); + emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); + RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map"); +#else + tf.format = RD::DATA_FORMAT_R32_UINT; + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(density_map, "Fog density map"); + RD::get_singleton()->texture_clear(density_map, Color(0, 0, 0, 0), 0, 1, 0, 1); + light_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(light_map, "Fog light map"); + RD::get_singleton()->texture_clear(light_map, Color(0, 0, 0, 0), 0, 1, 0, 1); + emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map"); + RD::get_singleton()->texture_clear(emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1); +#endif + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.append_id(fog_map); + uniforms.push_back(u); + } + + sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_sky_shader, RendererRD::SkyRD::SKY_SET_FOG); +} + +Fog::VolumetricFog::~VolumetricFog() { + RD::get_singleton()->free(prev_light_density_map); + RD::get_singleton()->free(light_density_map); + RD::get_singleton()->free(fog_map); + RD::get_singleton()->free(density_map); + RD::get_singleton()->free(light_map); + RD::get_singleton()->free(emissive_map); + + if (fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(fog_uniform_set)) { + RD::get_singleton()->free(fog_uniform_set); + } + if (process_uniform_set_density.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set_density)) { + RD::get_singleton()->free(process_uniform_set_density); + } + if (process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set)) { + RD::get_singleton()->free(process_uniform_set); + } + if (process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set2)) { + RD::get_singleton()->free(process_uniform_set2); + } + if (sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_uniform_set)) { + RD::get_singleton()->free(sdfgi_uniform_set); + } + if (sky_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_uniform_set)) { + RD::get_singleton()->free(sky_uniform_set); + } +} + +Vector3i Fog::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) { + Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point); + view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera + Vector3 fog_position = Vector3(0, 0, 0); + + view_position.y = -view_position.y; + fog_position.z = -view_position.z / fog_end; + fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5; + fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5; + fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread)); + fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5); + + fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x); + fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y); + fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z); + + return Vector3i(fog_position); +} + +void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + + RENDER_TIMESTAMP("> Volumetric Fog"); + RD::get_singleton()->draw_command_begin_label("Volumetric Fog"); + + if (p_fog_volumes.size() > 0) { + RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes"); + + RENDER_TIMESTAMP("Render FogVolumes"); + + VolumetricFogShader::VolumeUBO params; + + Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents(); + Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents(); + float z_near = p_cam_projection.get_z_near(); + float z_far = p_cam_projection.get_z_far(); + float fog_end = p_settings.env->volumetric_fog_length; + + Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near)); + Vector2 fog_near_size; + if (p_cam_projection.is_orthogonal()) { + fog_near_size = fog_far_size; + } else { + fog_near_size = Vector2(); + } + + params.fog_frustum_size_begin[0] = fog_near_size.x; + params.fog_frustum_size_begin[1] = fog_near_size.y; + + params.fog_frustum_size_end[0] = fog_far_size.x; + params.fog_frustum_size_end[1] = fog_far_size.y; + + params.fog_frustum_end = fog_end; + params.z_near = z_near; + params.z_far = z_far; + params.time = p_settings.time; + + params.fog_volume_size[0] = p_settings.vfog->width; + params.fog_volume_size[1] = p_settings.vfog->height; + params.fog_volume_size[2] = p_settings.vfog->depth; + + params.use_temporal_reprojection = p_settings.env->volumetric_fog_temporal_reprojection; + params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; + params.detail_spread = p_settings.env->volumetric_fog_detail_spread; + params.temporal_blend = p_settings.env->volumetric_fog_temporal_reprojection_amount; + + Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; + RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); + RendererRD::MaterialStorage::store_transform(p_cam_transform, params.transform); + + RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); + + if (p_settings.vfog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->fog_uniform_set)) { + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 1; + u.append_id(p_settings.vfog->emissive_map); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 2; + u.append_id(volumetric_fog.volume_ubo); + uniforms.push_back(u); + } + + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 3; + u.append_id(p_settings.vfog->density_map); + uniforms.push_back(u); + } + + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 4; + u.append_id(p_settings.vfog->light_map); + uniforms.push_back(u); + } + + p_settings.vfog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); + } + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + bool any_uses_time = false; + + for (int i = 0; i < (int)p_fog_volumes.size(); i++) { + FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]); + ERR_FAIL_COND(!fog_volume_instance); + RID fog_volume = fog_volume_instance->volume; + + RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume); + + FogMaterialData *material = nullptr; + + if (fog_material.is_valid()) { + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); + if (!material || !material->shader_data->valid) { + material = nullptr; + } + } + + if (!material) { + fog_material = volumetric_fog.default_material; + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); + } + + ERR_FAIL_COND(!material); + + FogShaderData *shader_data = material->shader_data; + + ERR_FAIL_COND(!shader_data); + + any_uses_time |= shader_data->uses_time; + + Vector3i min = Vector3i(); + Vector3i max = Vector3i(); + Vector3i kernel_size = Vector3i(); + + Vector3 position = fog_volume_instance->transform.get_origin(); + RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); + Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_extents(fog_volume); + + if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) { + // Local fog volume. + Vector3i points[8]; + Vector3 fog_size = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, p_settings.env->volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, p_settings.env->volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, p_settings.env->volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, p_settings.env->volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, p_settings.env->volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, p_settings.env->volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, p_settings.env->volumetric_fog_detail_spread, fog_size, p_cam_transform); + points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, p_settings.env->volumetric_fog_detail_spread, fog_size, p_cam_transform); + + min = Vector3i(int32_t(p_settings.vfog->width) - 1, int32_t(p_settings.vfog->height) - 1, int32_t(p_settings.vfog->depth) - 1); + max = Vector3i(1, 1, 1); + + for (int j = 0; j < 8; j++) { + min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z)); + max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z)); + } + + kernel_size = max - min; + } else { + // Volume type global runs on all cells + extents = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + min = Vector3i(0, 0, 0); + kernel_size = Vector3i(int32_t(p_settings.vfog->width), int32_t(p_settings.vfog->height), int32_t(p_settings.vfog->depth)); + } + + if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) { + continue; + } + + VolumetricFogShader::FogPushConstant push_constant; + push_constant.position[0] = position.x; + push_constant.position[1] = position.y; + push_constant.position[2] = position.z; + push_constant.extents[0] = extents.x; + push_constant.extents[1] = extents.y; + push_constant.extents[2] = extents.z; + push_constant.corner[0] = min.x; + push_constant.corner[1] = min.y; + push_constant.corner[2] = min.z; + push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume)); + RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), push_constant.transform); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant)); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE); + if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set. + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL); + } + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z); + } + if (any_uses_time || p_settings.env->volumetric_fog_temporal_reprojection) { + RenderingServerDefault::redraw_request(); + } + + RD::get_singleton()->draw_command_end_label(); + + RD::get_singleton()->compute_list_end(); + } + + if (p_settings.vfog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->process_uniform_set_density)) { + //re create uniform set if needed + Vector<RD::Uniform> uniforms; + Vector<RD::Uniform> copy_uniforms; + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + if (p_settings.shadow_atlas_depth.is_null()) { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); + } else { + u.append_id(p_settings.shadow_atlas_depth); + } + + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + if (p_settings.directional_shadow_depth.is_valid()) { + u.append_id(p_settings.directional_shadow_depth); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); + } + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 3; + u.append_id(p_settings.omni_light_buffer); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 4; + u.append_id(p_settings.spot_light_buffer); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 5; + u.append_id(p_settings.directional_light_buffer); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 6; + u.append_id(p_settings.cluster_builder->get_cluster_buffer()); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 7; + u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 8; + u.append_id(p_settings.vfog->light_density_map); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 9; + u.append_id(p_settings.vfog->fog_map); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 9; + u.append_id(p_settings.vfog->prev_light_density_map); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 10; + u.append_id(p_settings.shadow_sampler); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 11; + u.append_id(p_settings.voxel_gl_buffer); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 12; + for (int i = 0; i < RendererRD::GI::MAX_VOXEL_GI_INSTANCES; i++) { + u.append_id(p_settings.rbgi->voxel_gi_textures[i]); + } + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 13; + u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 14; + u.append_id(volumetric_fog.params_ubo); + uniforms.push_back(u); + copy_uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 15; + u.append_id(p_settings.vfog->prev_light_density_map); + uniforms.push_back(u); + } + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 16; + u.append_id(p_settings.vfog->density_map); + uniforms.push_back(u); + } + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 17; + u.append_id(p_settings.vfog->light_map); + uniforms.push_back(u); + } + + { + RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif + u.binding = 18; + u.append_id(p_settings.vfog->emissive_map); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 19; + RID radiance_texture = texture_storage->texture_rd_get_default(p_settings.is_using_radiance_cubemap_array ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID sky_texture = p_settings.env->sky.is_valid() ? p_settings.sky->sky_get_radiance_texture_rd(p_settings.env->sky) : RID(); + u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture); + uniforms.push_back(u); + } + + p_settings.vfog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0); + + p_settings.vfog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); + + RID aux7 = uniforms.write[7].get_id(0); + RID aux8 = uniforms.write[8].get_id(0); + + uniforms.write[7].set_id(0, aux8); + uniforms.write[8].set_id(0, aux7); + + p_settings.vfog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); + + uniforms.remove_at(8); + uniforms.write[7].set_id(0, aux7); + p_settings.vfog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); + } + + bool using_sdfgi = p_settings.env->volumetric_fog_gi_inject > 0.0001 && p_settings.env->sdfgi_enabled && (p_settings.sdfgi != nullptr); + + if (using_sdfgi) { + if (p_settings.vfog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->sdfgi_uniform_set)) { + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.append_id(p_settings.gi->sdfgi_ubo); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + u.append_id(p_settings.sdfgi->ambient_texture); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + u.append_id(p_settings.sdfgi->occlusion_texture); + uniforms.push_back(u); + } + + p_settings.vfog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1); + } + } + + p_settings.vfog->length = p_settings.env->volumetric_fog_length; + p_settings.vfog->spread = p_settings.env->volumetric_fog_detail_spread; + + VolumetricFogShader::ParamsUBO params; + + Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents(); + Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents(); + float z_near = p_cam_projection.get_z_near(); + float z_far = p_cam_projection.get_z_far(); + float fog_end = p_settings.env->volumetric_fog_length; + + Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near)); + Vector2 fog_near_size; + if (p_cam_projection.is_orthogonal()) { + fog_near_size = fog_far_size; + } else { + fog_near_size = Vector2(); + } + + params.fog_frustum_size_begin[0] = fog_near_size.x; + params.fog_frustum_size_begin[1] = fog_near_size.y; + + params.fog_frustum_size_end[0] = fog_far_size.x; + params.fog_frustum_size_end[1] = fog_far_size.y; + + params.ambient_inject = p_settings.env->volumetric_fog_ambient_inject * p_settings.env->ambient_light_energy; + params.z_far = z_far; + + params.fog_frustum_end = fog_end; + + Color ambient_color = p_settings.env->ambient_light.srgb_to_linear(); + params.ambient_color[0] = ambient_color.r; + params.ambient_color[1] = ambient_color.g; + params.ambient_color[2] = ambient_color.b; + params.sky_contribution = p_settings.env->ambient_sky_contribution; + + params.fog_volume_size[0] = p_settings.vfog->width; + params.fog_volume_size[1] = p_settings.vfog->height; + params.fog_volume_size[2] = p_settings.vfog->depth; + + params.directional_light_count = p_directional_light_count; + + Color emission = p_settings.env->volumetric_fog_emission.srgb_to_linear(); + params.base_emission[0] = emission.r * p_settings.env->volumetric_fog_emission_energy; + params.base_emission[1] = emission.g * p_settings.env->volumetric_fog_emission_energy; + params.base_emission[2] = emission.b * p_settings.env->volumetric_fog_emission_energy; + params.base_density = p_settings.env->volumetric_fog_density; + + Color base_scattering = p_settings.env->volumetric_fog_scattering.srgb_to_linear(); + params.base_scattering[0] = base_scattering.r; + params.base_scattering[1] = base_scattering.g; + params.base_scattering[2] = base_scattering.b; + params.phase_g = p_settings.env->volumetric_fog_anisotropy; + + params.detail_spread = p_settings.env->volumetric_fog_detail_spread; + params.gi_inject = p_settings.env->volumetric_fog_gi_inject; + + params.cam_rotation[0] = p_cam_transform.basis[0][0]; + params.cam_rotation[1] = p_cam_transform.basis[1][0]; + params.cam_rotation[2] = p_cam_transform.basis[2][0]; + params.cam_rotation[3] = 0; + params.cam_rotation[4] = p_cam_transform.basis[0][1]; + params.cam_rotation[5] = p_cam_transform.basis[1][1]; + params.cam_rotation[6] = p_cam_transform.basis[2][1]; + params.cam_rotation[7] = 0; + params.cam_rotation[8] = p_cam_transform.basis[0][2]; + params.cam_rotation[9] = p_cam_transform.basis[1][2]; + params.cam_rotation[10] = p_cam_transform.basis[2][2]; + params.cam_rotation[11] = 0; + params.filter_axis = 0; + params.max_voxel_gi_instances = p_settings.env->volumetric_fog_gi_inject > 0.001 ? p_voxel_gi_count : 0; + params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; + + Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; + RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); + + params.use_temporal_reprojection = p_settings.env->volumetric_fog_temporal_reprojection; + params.temporal_blend = p_settings.env->volumetric_fog_temporal_reprojection_amount; + + { + uint32_t cluster_size = p_settings.cluster_builder->get_cluster_size(); + params.cluster_shift = get_shift_from_power_of_2(cluster_size); + + uint32_t cluster_screen_width = (p_settings.rb_size.x - 1) / cluster_size + 1; + uint32_t cluster_screen_height = (p_settings.rb_size.y - 1) / cluster_size + 1; + params.max_cluster_element_count_div_32 = p_settings.max_cluster_elements / 32; + params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32); + params.cluster_width = cluster_screen_width; + + params.screen_size[0] = p_settings.rb_size.x; + params.screen_size[1] = p_settings.rb_size.y; + } + + Basis sky_transform = p_settings.env->sky_orientation; + sky_transform = sky_transform.inverse() * p_cam_transform.basis; + RendererRD::MaterialStorage::store_transform_3x3(sky_transform, params.radiance_inverse_xform); + + RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog"); + + RENDER_TIMESTAMP("Render Fog"); + RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set_density, 0); + + if (using_sdfgi) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->sdfgi_uniform_set, 1); + } + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + // Copy fog to history buffer + if (p_settings.env->volumetric_fog_temporal_reprojection) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->copy_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + RD::get_singleton()->draw_command_end_label(); + + if (p_settings.volumetric_fog_filter_active) { + RD::get_singleton()->draw_command_begin_label("Filter Fog"); + + RENDER_TIMESTAMP("Filter Fog"); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + + RD::get_singleton()->compute_list_end(); + //need restart for buffer update + + params.filter_axis = 1; + RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms); + + compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set2, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + + RD::get_singleton()->compute_list_add_barrier(compute_list); + RD::get_singleton()->draw_command_end_label(); + } + + RENDER_TIMESTAMP("Integrate Fog"); + RD::get_singleton()->draw_command_begin_label("Integrate Fog"); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, 1); + + RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER); + + RENDER_TIMESTAMP("< Volumetric Fog"); + RD::get_singleton()->draw_command_end_label(); + RD::get_singleton()->draw_command_end_label(); +} diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index 55a01c3616..61a5d80d20 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -34,12 +34,19 @@ #include "core/templates/local_vector.h" #include "core/templates/rid_owner.h" #include "servers/rendering/environment/renderer_fog.h" +#include "servers/rendering/renderer_rd/cluster_builder_rd.h" +#include "servers/rendering/renderer_rd/environment/gi.h" +#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" +#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h" #include "servers/rendering/storage/utilities.h" namespace RendererRD { class Fog : public RendererFog { public: + /* FOG VOLUMES */ + struct FogVolume { RID material; Vector3 extents = Vector3(1, 1, 1); @@ -49,10 +56,179 @@ public: Dependency dependency; }; + struct FogVolumeInstance { + RID volume; + Transform3D transform; + bool active = false; + }; + private: static Fog *singleton; mutable RID_Owner<FogVolume, true> fog_volume_owner; + mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner; + + /* Volumetric Fog */ + struct VolumetricFogShader { + enum FogSet { + FOG_SET_BASE, + FOG_SET_UNIFORMS, + FOG_SET_MATERIAL, + FOG_SET_MAX, + }; + + struct FogPushConstant { + float position[3]; + float pad; + + float extents[3]; + float pad2; + + int32_t corner[3]; + uint32_t shape; + + float transform[16]; + }; + + struct VolumeUBO { + float fog_frustum_size_begin[2]; + float fog_frustum_size_end[2]; + + float fog_frustum_end; + float z_near; + float z_far; + float time; + + int32_t fog_volume_size[3]; + uint32_t directional_light_count; + + uint32_t use_temporal_reprojection; + uint32_t temporal_frame; + float detail_spread; + float temporal_blend; + + float to_prev_view[16]; + float transform[16]; + }; + + ShaderCompiler compiler; + VolumetricFogShaderRD shader; + RID volume_ubo; + + RID default_shader; + RID default_material; + RID default_shader_rd; + + RID base_uniform_set; + + RID params_ubo; + + enum { + VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY, + VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI, + VOLUMETRIC_FOG_PROCESS_SHADER_FILTER, + VOLUMETRIC_FOG_PROCESS_SHADER_FOG, + VOLUMETRIC_FOG_PROCESS_SHADER_COPY, + VOLUMETRIC_FOG_PROCESS_SHADER_MAX, + }; + + struct ParamsUBO { + float fog_frustum_size_begin[2]; + float fog_frustum_size_end[2]; + + float fog_frustum_end; + float ambient_inject; + float z_far; + uint32_t filter_axis; + + float ambient_color[3]; + float sky_contribution; + + int32_t fog_volume_size[3]; + uint32_t directional_light_count; + + float base_emission[3]; + float base_density; + + float base_scattering[3]; + float phase_g; + + float detail_spread; + float gi_inject; + uint32_t max_voxel_gi_instances; + uint32_t cluster_type_size; + + float screen_size[2]; + uint32_t cluster_shift; + uint32_t cluster_width; + + uint32_t max_cluster_element_count_div_32; + uint32_t use_temporal_reprojection; + uint32_t temporal_frame; + float temporal_blend; + + float cam_rotation[12]; + float to_prev_view[16]; + float radiance_inverse_xform[12]; + }; + + VolumetricFogProcessShaderRD process_shader; + + RID process_shader_version; + RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX]; + + } volumetric_fog; + + Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform); + + struct FogShaderData : public RendererRD::ShaderData { + bool valid = false; + RID version; + + RID pipeline; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; + + Vector<uint32_t> ubo_offsets; + uint32_t ubo_size = 0; + + String path; + String code; + HashMap<StringName, HashMap<int, RID>> default_texture_params; + + bool uses_time = false; + + virtual void set_path_hint(const String &p_hint); + virtual void set_code(const String &p_Code); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); + virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; + virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_animated() const; + virtual bool casts_shadows() const; + virtual Variant get_default_parameter(const StringName &p_parameter) const; + virtual RS::ShaderNativeSourceCode get_native_source_code() const; + + FogShaderData() {} + virtual ~FogShaderData(); + }; + + struct FogMaterialData : public RendererRD::MaterialData { + FogShaderData *shader_data = nullptr; + RID uniform_set; + bool uniform_set_updated; + + virtual void set_render_priority(int p_priority) {} + virtual void set_next_pass(RID p_pass) {} + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual ~FogMaterialData(); + }; + + RendererRD::ShaderData *_create_fog_shader_func(); + static RendererRD::ShaderData *_create_fog_shader_funcs(); + + RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader); + static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader); public: static Fog *get_singleton() { return singleton; } @@ -76,8 +252,78 @@ public: RID fog_volume_get_material(RID p_fog_volume) const; virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override; Vector3 fog_volume_get_extents(RID p_fog_volume) const; + + /* FOG VOLUMES INSTANCE */ + + FogVolumeInstance *get_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.get_or_null(p_rid); }; + bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); }; + + RID fog_volume_instance_create(RID p_fog_volume); + void fog_instance_free(RID p_rid); + + /* Volumetric FOG */ + struct VolumetricFog { + enum { + MAX_TEMPORAL_FRAMES = 16 + }; + + uint32_t width = 0; + uint32_t height = 0; + uint32_t depth = 0; + + float length; + float spread; + + RID light_density_map; + RID prev_light_density_map; + RID fog_map; + RID density_map; + RID light_map; + RID emissive_map; + + RID fog_uniform_set; + RID copy_uniform_set; + RID process_uniform_set_density; + RID process_uniform_set; + RID process_uniform_set2; + RID sdfgi_uniform_set; + RID sky_uniform_set; + + int last_shadow_filter = -1; + + VolumetricFog(const Vector3i &fog_size, RID p_sky_shader); + ~VolumetricFog(); + }; + + void init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array); + void free_fog_shader(); + + struct VolumetricFogSettings { + Vector2i rb_size; + double time; + bool is_using_radiance_cubemap_array; + uint32_t max_cluster_elements; + bool volumetric_fog_filter_active; + RID shadow_sampler; + RID voxel_gl_buffer; + RID shadow_atlas_depth; + RID omni_light_buffer; + RID spot_light_buffer; + RID directional_shadow_depth; + RID directional_light_buffer; + + // Objects related to our render buffer + VolumetricFog *vfog; + ClusterBuilderRD *cluster_builder; + GI *gi; + GI::SDFGI *sdfgi; + GI::RenderBuffersGI *rbgi; + RendererSceneEnvironmentRD *env; + SkyRD *sky; + }; + void volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); }; } // namespace RendererRD -#endif // !FOG_RD_H +#endif // FOG_RD_H diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index a749e7d5bc..cb3de07c31 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -109,6 +109,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo Vector<Vector<uint8_t>> s; s.push_back(p_distance_field); voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s); + RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture"); } #if 0 { @@ -122,6 +123,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM); tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT); voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture"); } RID shared_tex; { @@ -402,29 +404,38 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world RD::TextureFormat tf_render = tf_sdf; tf_render.format = RD::DATA_FORMAT_R16_UINT; render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_albedo, "VoxelGI Render Albedo"); tf_render.format = RD::DATA_FORMAT_R32_UINT; render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_emission, "VoxelGI Render Emission"); render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_emission_aniso, "VoxelGI Render Emission Aniso"); tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize for (int i = 0; i < 8; i++) { render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_occlusion[i], String("VoxelGI Render Occlusion ") + itos(i)); } tf_render.format = RD::DATA_FORMAT_R32_UINT; render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_geom_facing, "VoxelGI Render Geometry Facing"); tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT; render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf[0], "VoxelGI Render SDF 0"); render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf[1], "VoxelGI Render SDF 1"); tf_render.width /= 2; tf_render.height /= 2; tf_render.depth /= 2; render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf_half[0], "VoxelGI Render SDF Half 0"); render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf_half[1], "VoxelGI Render SDF Half 1"); } RD::TextureFormat tf_occlusion = tf_sdf; @@ -465,7 +476,9 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D; lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView()); + RD::get_singleton()->set_resource_name(lightprobe_history_scroll, "VoxelGI LightProbe History Scroll"); lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView()); + RD::get_singleton()->set_resource_name(lightprobe_average_scroll, "VoxelGI LightProbe Average Scroll"); { //octahedral lightprobes @@ -479,6 +492,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world //lightprobe texture is an octahedral texture lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView()); + RD::get_singleton()->set_resource_name(lightprobe_data, "VoxelGI LightProbe Data"); RD::TextureView tv; tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, lightprobe_data); @@ -492,11 +506,13 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; //lightprobe texture is an octahedral texture ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView()); + RD::get_singleton()->set_resource_name(ambient_texture, "VoxelGI Ambient Texture"); } cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES); occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView()); + RD::get_singleton()->set_resource_name(occlusion_data, "VoxelGI Occlusion Data"); { RD::TextureView tv; tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16; @@ -509,11 +525,15 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world /* 3D Textures */ cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.sdf_tex, "VoxelGI Cascade SDF Texture"); cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.light_data, "VoxelGI Cascade Light Data"); cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.light_aniso_0_tex, "VoxelGI Cascade Light Aniso 0 Texture"); cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.light_aniso_1_tex, "VoxelGI Cascade Light Aniso 1 Texture"); { RD::TextureView tv; @@ -540,9 +560,11 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world /* Probe History */ cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.lightprobe_history_tex, "VoxelGI Cascade LightProbe History Texture"); RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.lightprobe_average_tex, "VoxelGI Cascade LightProbe Average Texture"); RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work /* Buffers */ @@ -788,7 +810,8 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world uniforms.push_back(u); } - cascade.sdf_direct_light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, 0), 0); + cascade.sdf_direct_light_static_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_STATIC), 0); + cascade.sdf_direct_light_dynamic_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_DYNAMIC), 0); } //preprocess initialize uniform set @@ -1237,7 +1260,7 @@ void GI::SDFGI::update_light() { } cascades[i].all_dynamic_lights_dirty = false; - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_dynamic_uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DirectLightPushConstant)); RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer, 0); } @@ -1245,7 +1268,7 @@ void GI::SDFGI::update_light() { RD::get_singleton()->draw_command_end_label(); } -void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky) { +void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, SkyRD::Sky *p_sky) { RD::get_singleton()->draw_command_begin_label("SDFGI Update Probes"); SDFGIShader::IntegratePushConstant push_constant; @@ -1459,7 +1482,7 @@ void GI::SDFGI::update_cascades() { RD::get_singleton()->buffer_update(cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, RD::BARRIER_MASK_COMPUTE); } -void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views) { +void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); @@ -1592,7 +1615,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti push_constant.cam_transform[15] = 1; // need to properly unproject for asymmetric projection matrices in stereo.. - CameraMatrix inv_projection = p_projections[v].inverse(); + Projection inv_projection = p_projections[v].inverse(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { push_constant.inv_projection[i * 4 + j] = inv_projection.matrix[i][j]; @@ -1609,7 +1632,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true, false, false, false, RID(), p_view_count > 1); } -void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { +void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); // setup scene data @@ -2391,7 +2414,7 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co dl_push_constant.cascade = p_cascade_indices[i]; if (dl_push_constant.light_count > 0) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_static_uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &dl_push_constant, sizeof(SDFGIShader::DirectLightPushConstant)); RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cc.solid_cell_dispatch_buffer, 0); } @@ -2444,6 +2467,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(texture, "VoxelGI Instance Texture"); RD::get_singleton()->texture_clear(texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1); @@ -2573,6 +2597,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.texture, "VoxelGI Instance DMap Texture"); if (dynamic_maps.size() == 0) { // Render depth for first one. @@ -2580,6 +2605,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D16_UNORM, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.fb_depth, "VoxelGI Instance DMap FB Depth"); } //just use depth as-is @@ -2587,13 +2613,17 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.depth, "VoxelGI Instance DMap Depth"); if (dynamic_maps.size() == 0) { dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.albedo, "VoxelGI Instance DMap Albedo"); dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.normal, "VoxelGI Instance DMap Normal"); dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.orm, "VoxelGI Instance DMap ORM"); Vector<RID> fb; fb.push_back(dmap.albedo); @@ -2985,7 +3015,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(1)) < 0); bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(2)) > 0); - CameraMatrix cm; + Projection cm; cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]); if (p_scene_render->cull_argument.size() == 0) { @@ -3110,14 +3140,14 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID last_probe_version = gi->voxel_gi_get_version(probe); } -void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { +void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); if (mipmaps.size() == 0) { return; } - CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse()); + Projection cam_transform = (p_camera_with_transform * Projection(transform)) * Projection(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse()); int level = 0; Vector3i octree_size = gi->voxel_gi_get_octree_size(probe); @@ -3203,7 +3233,7 @@ GI::~GI() { singleton = nullptr; } -void GI::init(RendererSceneSkyRD *p_sky) { +void GI::init(SkyRD *p_sky) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -3322,7 +3352,11 @@ void GI::init(RendererSceneSkyRD *p_sky) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + if (p_sky->sky_use_cubemap_array) { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE)); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + } uniforms.push_back(u); } { @@ -3342,37 +3376,40 @@ void GI::init(RendererSceneSkyRD *p_sky) { //calculate tables String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; Vector<String> gi_modes; + gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_VOXEL_GI gi_modes.push_back("\n#define USE_SDFGI\n"); // MODE_SDFGI gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_COMBINED - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_HALF_RES_VOXEL_GI - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n"); // MODE_HALF_RES_SDFGI - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_HALF_RES_COMBINED - - gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_VOXEL_GI_MULTIVIEW - gi_modes.push_back("\n#define USE_SDFGI\n#define USE_MULTIVIEW\n"); // MODE_SDFGI_MULTIVIEW - gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_COMBINED_MULTIVIEW - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_VOXEL_GI_MULTIVIEW - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_SDFGI_MULTIVIEW - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_COMBINED_MULTIVIEW shader.initialize(gi_modes, defines); + shader_version = shader.version_create(); + + Vector<RD::PipelineSpecializationConstant> specialization_constants; - if (!RendererCompositorRD::singleton->is_xr_enabled()) { - shader.set_variant_enabled(MODE_VOXEL_GI_MULTIVIEW, false); - shader.set_variant_enabled(MODE_SDFGI_MULTIVIEW, false); - shader.set_variant_enabled(MODE_COMBINED_MULTIVIEW, false); - shader.set_variant_enabled(MODE_HALF_RES_VOXEL_GI_MULTIVIEW, false); - shader.set_variant_enabled(MODE_HALF_RES_SDFGI_MULTIVIEW, false); - shader.set_variant_enabled(MODE_HALF_RES_COMBINED_MULTIVIEW, false); + { + RD::PipelineSpecializationConstant sc; + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sc.constant_id = 0; // SHADER_SPECIALIZATION_HALF_RES + sc.bool_value = false; + specialization_constants.push_back(sc); + + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sc.constant_id = 1; // SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX + sc.bool_value = false; + specialization_constants.push_back(sc); + + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sc.constant_id = 2; // SHADER_SPECIALIZATION_USE_VRS + sc.bool_value = false; + specialization_constants.push_back(sc); } - shader_version = shader.version_create(); - for (int i = 0; i < MODE_MAX; i++) { - if (shader.is_variant_enabled(i)) { - pipelines[i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i)); - } else { - pipelines[i] = RID(); + for (int v = 0; v < SHADER_SPECIALIZATION_VARIATIONS; v++) { + specialization_constants.ptrw()[0].bool_value = (v & SHADER_SPECIALIZATION_HALF_RES) ? true : false; + specialization_constants.ptrw()[1].bool_value = (v & SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX) ? true : false; + specialization_constants.ptrw()[2].bool_value = (v & SHADER_SPECIALIZATION_USE_VRS) ? true : false; + for (int i = 0; i < MODE_MAX; i++) { + pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i), specialization_constants); } } @@ -3564,25 +3601,17 @@ void GI::RenderBuffersGI::free() { } if (ambient_buffer.is_valid()) { - if (view_count == 1) { - // Only one view? then these are copies of our main buffers. - ambient_view[0] = RID(); - reflection_view[0] = RID(); - } else { - // Multiple views? free our slices. - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(ambient_view[v]); - RD::get_singleton()->free(reflection_view[v]); - ambient_view[v] = RID(); - reflection_view[v] = RID(); - } - } - - // Now we can free our buffers. RD::get_singleton()->free(ambient_buffer); RD::get_singleton()->free(reflection_buffer); ambient_buffer = RID(); reflection_buffer = RID(); + + // these are automatically freed when we free the textures, so just reset.. + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + ambient_slice[v] = RID(); + reflection_slice[v] = RID(); + } + view_count = 0; } @@ -3592,7 +3621,7 @@ void GI::RenderBuffersGI::free() { } } -void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { +void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -3606,14 +3635,13 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) { // Free our old buffer if applicable if (rb->rbgi.ambient_buffer.is_valid()) { - if (rb->rbgi.view_count > 1) { - for (uint32_t v = 0; v < rb->rbgi.view_count; v++) { - RD::get_singleton()->free(rb->rbgi.ambient_view[v]); - RD::get_singleton()->free(rb->rbgi.reflection_view[v]); - } - } RD::get_singleton()->free(rb->rbgi.ambient_buffer); RD::get_singleton()->free(rb->rbgi.reflection_buffer); + + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + rb->rbgi.ambient_slice[v] = RID(); + rb->rbgi.reflection_slice[v] = RID(); + } } // Remember the view count we're using @@ -3637,18 +3665,19 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v } tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(rb->rbgi.ambient_buffer, "GI Ambient Buffer"); rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(rb->rbgi.reflection_buffer, "GI Reflection Buffer"); rb->rbgi.using_half_size_gi = half_resolution; if (p_view_count == 1) { - // Just one view? Copy our buffers - rb->rbgi.ambient_view[0] = rb->rbgi.ambient_buffer; - rb->rbgi.reflection_view[0] = rb->rbgi.reflection_buffer; + // Just copy, we don't need to create slices + rb->rbgi.ambient_slice[0] = rb->rbgi.ambient_buffer; + rb->rbgi.reflection_slice[0] = rb->rbgi.reflection_buffer; } else { - // More then one view? Create slices for each view for (uint32_t v = 0; v < p_view_count; v++) { - rb->rbgi.ambient_view[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0); - rb->rbgi.reflection_view[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0); + rb->rbgi.ambient_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0); + rb->rbgi.reflection_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0); } } } @@ -3681,29 +3710,45 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v // Now compute the contents of our buffers. RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true); - for (uint32_t v = 0; v < p_view_count; v++) { - // Render each eye seperately. - // We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference.. + // Render each eye separately. + // We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference.. - // setup our push constant + // setup our push constant - PushConstant push_constant; + PushConstant push_constant; - push_constant.view_index = v; - push_constant.orthogonal = p_projections[v].is_orthogonal(); - push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()); - push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH; + push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()); + push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH; + + // these should be the same for all views + push_constant.orthogonal = p_projections[0].is_orthogonal(); + push_constant.z_near = p_projections[0].get_z_near(); + push_constant.z_far = p_projections[0].get_z_far(); + + // these are only used if we have 1 view, else we use the projections in our scene data + push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[0].matrix[0][0]); + push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[0].matrix[1][1]); + push_constant.proj_info[2] = (1.0f - p_projections[0].matrix[0][2]) / p_projections[0].matrix[0][0]; + push_constant.proj_info[3] = (1.0f + p_projections[0].matrix[1][2]) / p_projections[0].matrix[1][1]; - push_constant.z_near = p_projections[v].get_z_near(); - push_constant.z_far = p_projections[v].get_z_far(); + bool use_sdfgi = rb->sdfgi != nullptr; + bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0; + + uint32_t pipeline_specialization = 0; + if (rb->rbgi.using_half_size_gi) { + pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES; + } + if (p_view_count > 1) { + pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX; + } + if (p_vrs_slices[0].is_valid()) { + pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS; + } - push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[v].matrix[0][0]); - push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[v].matrix[1][1]); - push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0]; - push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1]; + Mode mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI); - bool use_sdfgi = rb->sdfgi != nullptr; - bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0; + for (uint32_t v = 0; v < p_view_count; v++) { + push_constant.view_index = v; // setup our uniform set if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) { @@ -3790,7 +3835,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.append_id(rb->rbgi.ambient_view[v]); + u.append_id(rb->rbgi.ambient_slice[v]); uniforms.push_back(u); } @@ -3798,7 +3843,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 10; - u.append_id(rb->rbgi.reflection_view[v]); + u.append_id(rb->rbgi.reflection_slice[v]); uniforms.push_back(u); } @@ -3824,7 +3869,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 13; - u.append_id(p_normal_roughness_views[v]); + u.append_id(p_normal_roughness_slices[v]); uniforms.push_back(u); } { @@ -3865,27 +3910,19 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v u.append_id(rb->rbgi.scene_data_ubo); uniforms.push_back(u); } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 19; + RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_VRS); + u.append_id(buffer); + uniforms.push_back(u); + } rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0); } - Mode mode; - - if (p_view_count > 1) { - if (rb->rbgi.using_half_size_gi) { - mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED_MULTIVIEW : (use_sdfgi ? MODE_HALF_RES_SDFGI_MULTIVIEW : MODE_HALF_RES_VOXEL_GI_MULTIVIEW); - } else { - mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED_MULTIVIEW : (use_sdfgi ? MODE_SDFGI_MULTIVIEW : MODE_VOXEL_GI_MULTIVIEW); - } - } else { - if (rb->rbgi.using_half_size_gi) { - mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_VOXEL_GI); - } else { - mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI); - } - } - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[mode]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); @@ -3930,7 +3967,7 @@ void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vecto voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render); } -void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { +void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_voxel_gi); ERR_FAIL_COND(!voxel_gi); diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index 294b8d3cfd..f4e32a8dd0 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -35,8 +35,8 @@ #include "core/templates/rid_owner.h" #include "servers/rendering/environment/renderer_gi.h" #include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_rd/environment/sky.h" #include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" -#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h" #include "servers/rendering/renderer_rd/shaders/environment/gi.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl.gen.h" @@ -472,7 +472,7 @@ public: Transform3D transform; void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); - void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); + void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); }; mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner; @@ -541,7 +541,8 @@ public: Vector3i dirty_regions; //(0,0,0 is not dirty, negative is refresh from the end, DIRTY_ALL is refresh all. RID sdf_store_uniform_set; - RID sdf_direct_light_uniform_set; + RID sdf_direct_light_static_uniform_set; + RID sdf_direct_light_dynamic_uniform_set; RID scroll_uniform_set; RID scroll_occlusion_uniform_set; RID integrate_uniform_set; @@ -617,13 +618,13 @@ public: void erase(); void update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position); void update_light(); - void update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky); + void update_probes(RendererSceneEnvironmentRD *p_env, RendererRD::SkyRD::Sky *p_sky); void store_probes(); int get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const; void update_cascades(); - void debug_draw(uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views); - void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); + void debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views); + void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render); void render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render); @@ -660,13 +661,13 @@ public: /* GI buffers */ RID ambient_buffer; + RID ambient_slice[RendererSceneRender::MAX_RENDER_VIEWS]; RID reflection_buffer; - RID ambient_view[RendererSceneRender::MAX_RENDER_VIEWS]; - RID reflection_view[RendererSceneRender::MAX_RENDER_VIEWS]; - RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; + RID reflection_slice[RendererSceneRender::MAX_RENDER_VIEWS]; bool using_half_size_gi = false; uint32_t view_count = 1; + RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; RID scene_data_ubo; void free(); @@ -729,63 +730,60 @@ public: }; struct PushConstant { - uint32_t view_index; uint32_t max_voxel_gi_instances; uint32_t high_quality_vct; uint32_t orthogonal; + uint32_t view_index; float proj_info[4]; float z_near; float z_far; - float pad1; float pad2; + float pad3; }; RID sdfgi_ubo; + enum Mode { MODE_VOXEL_GI, MODE_SDFGI, MODE_COMBINED, - MODE_HALF_RES_VOXEL_GI, - MODE_HALF_RES_SDFGI, - MODE_HALF_RES_COMBINED, - - MODE_VOXEL_GI_MULTIVIEW, - MODE_SDFGI_MULTIVIEW, - MODE_COMBINED_MULTIVIEW, - MODE_HALF_RES_VOXEL_GI_MULTIVIEW, - MODE_HALF_RES_SDFGI_MULTIVIEW, - MODE_HALF_RES_COMBINED_MULTIVIEW, - MODE_MAX }; + enum ShaderSpecializations { + SHADER_SPECIALIZATION_HALF_RES = 1 << 0, + SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX = 1 << 1, + SHADER_SPECIALIZATION_USE_VRS = 1 << 2, + SHADER_SPECIALIZATION_VARIATIONS = 8, + }; + RID default_voxel_gi_buffer; bool half_resolution = false; GiShaderRD shader; RID shader_version; - RID pipelines[MODE_MAX]; + RID pipelines[SHADER_SPECIALIZATION_VARIATIONS][MODE_MAX]; GI(); ~GI(); - void init(RendererSceneSkyRD *p_sky); + void init(RendererRD::SkyRD *p_sky); void free(); SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render); - void process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render); + void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render); RID voxel_gi_instance_create(RID p_base); void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform); bool voxel_gi_needs_update(RID p_probe) const; void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); - void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); + void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); }; } // namespace RendererRD -#endif /* !GI_RD_H */ +#endif // GI_RD_H diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 73175d3cf3..6f32c15d95 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_scene_sky_rd.cpp */ +/* sky.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,21 +28,27 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "renderer_scene_sky_rd.h" +#include "sky.h" #include "core/config/project_settings.h" #include "core/math/math_defs.h" -#include "renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/effects/copy_effects.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" #include "servers/rendering/rendering_server_globals.h" +using namespace RendererRD; + //////////////////////////////////////////////////////////////////////////////// // SKY SHADER -void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) { +void SkyRD::SkyShaderData::set_path_hint(const String &p_path) { + path = p_path; +} + +void SkyRD::SkyShaderData::set_code(const String &p_code) { //compile code = p_code; @@ -141,7 +147,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) { valid = true; } -void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void SkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { default_texture_params[p_name].erase(p_index); @@ -158,7 +164,7 @@ void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringNa } } -void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void SkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { @@ -172,15 +178,29 @@ void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_par order[E.value.order] = E.key; } } - + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); } } -void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { +void SkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; @@ -195,7 +215,7 @@ void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMat } } -bool RendererSceneSkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const { +bool SkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } @@ -203,15 +223,15 @@ bool RendererSceneSkyRD::SkyShaderData::is_param_texture(const StringName &p_par return uniforms[p_param].texture_order >= 0; } -bool RendererSceneSkyRD::SkyShaderData::is_animated() const { +bool SkyRD::SkyShaderData::is_animated() const { return false; } -bool RendererSceneSkyRD::SkyShaderData::casts_shadows() const { +bool SkyRD::SkyShaderData::casts_shadows() const { return false; } -Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const { +Variant SkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const { if (uniforms.has(p_parameter)) { ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; @@ -220,13 +240,13 @@ Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringNam return Variant(); } -RS::ShaderNativeSourceCode RendererSceneSkyRD::SkyShaderData::get_native_source_code() const { +RS::ShaderNativeSourceCode SkyRD::SkyShaderData::get_native_source_code() const { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); return scene_singleton->sky.sky_shader.shader.version_get_native_source_code(version); } -RendererSceneSkyRD::SkyShaderData::~SkyShaderData() { +SkyRD::SkyShaderData::~SkyShaderData() { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); ERR_FAIL_COND(!scene_singleton); //pipeline variants will clear themselves if shader is gone @@ -238,7 +258,7 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() { //////////////////////////////////////////////////////////////////////////////// // Sky material -bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool SkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -246,7 +266,7 @@ bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<String return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL); } -RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() { +SkyRD::SkyMaterialData::~SkyMaterialData() { free_parameters_uniform_set(uniform_set); } @@ -268,7 +288,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar p_array[11] = 0; } -void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) { +void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) { SkyPushConstant sky_push_constant; memset(&sky_push_constant, 0, sizeof(SkyPushConstant)); @@ -319,7 +339,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_ //////////////////////////////////////////////////////////////////////////////// // ReflectionData -void RendererSceneSkyRD::ReflectionData::clear_reflection_data() { +void SkyRD::ReflectionData::clear_reflection_data() { layers.clear(); radiance_base_cubemap = RID(); if (downsampled_radiance_cubemap.is_valid()) { @@ -330,7 +350,7 @@ void RendererSceneSkyRD::ReflectionData::clear_reflection_data() { coefficient_buffer = RID(); } -void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) { +void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) { //recreate radiance and all data int mipmaps = p_mipmaps; @@ -438,7 +458,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int } } -void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) { +void SkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); @@ -496,7 +516,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(bool p_us } } -void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) { +void SkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); @@ -565,7 +585,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(boo RD::get_singleton()->draw_command_end_label(); // Filter radiance } -void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) { +void SkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); @@ -590,9 +610,9 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(int p_start, } //////////////////////////////////////////////////////////////////////////////// -// RendererSceneSkyRD::Sky +// SkyRD::Sky -void RendererSceneSkyRD::Sky::free() { +void SkyRD::Sky::free() { if (radiance.is_valid()) { RD::get_singleton()->free(radiance); radiance = RID(); @@ -620,7 +640,7 @@ void RendererSceneSkyRD::Sky::free() { } } -RID RendererSceneSkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) { +RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) { @@ -681,7 +701,7 @@ RID RendererSceneSkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_ return texture_uniform_sets[p_version]; } -bool RendererSceneSkyRD::Sky::set_radiance_size(int p_radiance_size) { +bool SkyRD::Sky::set_radiance_size(int p_radiance_size) { ERR_FAIL_COND_V(p_radiance_size < 32 || p_radiance_size > 2048, false); if (radiance_size == p_radiance_size) { return false; @@ -702,7 +722,7 @@ bool RendererSceneSkyRD::Sky::set_radiance_size(int p_radiance_size) { return true; } -bool RendererSceneSkyRD::Sky::set_mode(RS::SkyMode p_mode) { +bool SkyRD::Sky::set_mode(RS::SkyMode p_mode) { if (mode == p_mode) { return false; } @@ -723,7 +743,7 @@ bool RendererSceneSkyRD::Sky::set_mode(RS::SkyMode p_mode) { return true; } -bool RendererSceneSkyRD::Sky::set_material(RID p_material) { +bool SkyRD::Sky::set_material(RID p_material) { if (material == p_material) { return false; } @@ -732,7 +752,7 @@ bool RendererSceneSkyRD::Sky::set_material(RID p_material) { return true; } -Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) { +Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) { if (radiance.is_valid()) { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); @@ -766,37 +786,37 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughnes } //////////////////////////////////////////////////////////////////////////////// -// RendererSceneSkyRD +// SkyRD -RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() { +RendererRD::ShaderData *SkyRD::_create_sky_shader_func() { SkyShaderData *shader_data = memnew(SkyShaderData); return shader_data; } -RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() { +RendererRD::ShaderData *SkyRD::_create_sky_shader_funcs() { // !BAS! Why isn't _create_sky_shader_func not just static too? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func(); }; -RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) { +RendererRD::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) { SkyMaterialData *material_data = memnew(SkyMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; } -RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) { +RendererRD::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) { // !BAS! same here, we could just make _create_sky_material_func static? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); }; -RendererSceneSkyRD::RendererSceneSkyRD() { +SkyRD::SkyRD() { roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers"); sky_ggx_samples_quality = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples"); sky_use_cubemap_array = GLOBAL_GET("rendering/reflections/sky_reflections/texture_array_reflections"); } -void RendererSceneSkyRD::init() { +void SkyRD::init() { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -1051,11 +1071,11 @@ void sky() { } } -void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) { +void SkyRD::set_texture_format(RD::DataFormat p_texture_format) { texture_format = p_texture_format; } -RendererSceneSkyRD::~RendererSceneSkyRD() { +SkyRD::~SkyRD() { // cleanup anything created in init... RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -1085,7 +1105,7 @@ RendererSceneSkyRD::~RendererSceneSkyRD() { RD::get_singleton()->free(index_buffer); //array gets freed as dependency } -void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { +void SkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); @@ -1297,7 +1317,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo); } -void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { +void SkyRD::update(RendererSceneEnvironmentRD *p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); @@ -1371,9 +1391,9 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM Vector3(0, -1, 0) }; - CameraMatrix cm; + Projection cm; cm.set_perspective(90, 1, 0.01, 10.0); - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); cm = correction * cm; @@ -1466,7 +1486,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM } } -void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) { +void SkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); @@ -1515,9 +1535,9 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont float custom_fov = p_env->sky_custom_fov; // Camera - CameraMatrix camera; + Projection camera; uint32_t view_count = p_view_count; - const CameraMatrix *projections = p_projections; + const Projection *projections = p_projections; if (custom_fov) { // With custom fov we don't support stereo... @@ -1573,7 +1593,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont RD::get_singleton()->draw_list_end(); } -void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { +void SkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); @@ -1613,9 +1633,9 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u float custom_fov = p_env->sky_custom_fov; // Camera - CameraMatrix camera; + Projection camera; uint32_t view_count = p_view_count; - const CameraMatrix *projections = p_projections; + const Projection *projections = p_projections; if (custom_fov) { // With custom fov we don't support stereo... @@ -1658,7 +1678,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u } } -void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { +void SkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(!p_env); @@ -1707,9 +1727,9 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme float custom_fov = p_env->sky_custom_fov; // Camera - CameraMatrix camera; + Projection camera; uint32_t view_count = p_view_count; - const CameraMatrix *projections = p_projections; + const Projection *projections = p_projections; if (custom_fov) { // With custom fov we don't support stereo... @@ -1737,7 +1757,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier); } -void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) { +void SkyRD::invalidate_sky(Sky *p_sky) { if (!p_sky->dirty) { p_sky->dirty = true; p_sky->dirty_list = dirty_sky_list; @@ -1745,7 +1765,7 @@ void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) { } } -void RendererSceneSkyRD::update_dirty_skys() { +void SkyRD::update_dirty_skys() { Sky *sky = dirty_sky_list; while (sky) { @@ -1849,26 +1869,26 @@ void RendererSceneSkyRD::update_dirty_skys() { dirty_sky_list = nullptr; } -RID RendererSceneSkyRD::sky_get_material(RID p_sky) const { +RID SkyRD::sky_get_material(RID p_sky) const { Sky *sky = get_sky(p_sky); ERR_FAIL_COND_V(!sky, RID()); return sky->material; } -RID RendererSceneSkyRD::allocate_sky_rid() { +RID SkyRD::allocate_sky_rid() { return sky_owner.allocate_rid(); } -void RendererSceneSkyRD::initialize_sky_rid(RID p_rid) { +void SkyRD::initialize_sky_rid(RID p_rid) { sky_owner.initialize_rid(p_rid, Sky()); } -RendererSceneSkyRD::Sky *RendererSceneSkyRD::get_sky(RID p_sky) const { +SkyRD::Sky *SkyRD::get_sky(RID p_sky) const { return sky_owner.get_or_null(p_sky); } -void RendererSceneSkyRD::free_sky(RID p_sky) { +void SkyRD::free_sky(RID p_sky) { Sky *sky = get_sky(p_sky); ERR_FAIL_COND(!sky); @@ -1876,7 +1896,7 @@ void RendererSceneSkyRD::free_sky(RID p_sky) { sky_owner.free(p_sky); } -void RendererSceneSkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { +void SkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { Sky *sky = get_sky(p_sky); ERR_FAIL_COND(!sky); @@ -1885,7 +1905,7 @@ void RendererSceneSkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { } } -void RendererSceneSkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { +void SkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { Sky *sky = get_sky(p_sky); ERR_FAIL_COND(!sky); @@ -1894,7 +1914,7 @@ void RendererSceneSkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { } } -void RendererSceneSkyRD::sky_set_material(RID p_sky, RID p_material) { +void SkyRD::sky_set_material(RID p_sky, RID p_material) { Sky *sky = get_sky(p_sky); ERR_FAIL_COND(!sky); @@ -1903,7 +1923,7 @@ void RendererSceneSkyRD::sky_set_material(RID p_sky, RID p_material) { } } -Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) { +Ref<Image> SkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) { Sky *sky = get_sky(p_sky); ERR_FAIL_COND_V(!sky, Ref<Image>()); @@ -1912,7 +1932,7 @@ Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool return sky->bake_panorama(p_energy, p_bake_irradiance ? roughness_layers : 0, p_size); } -RID RendererSceneSkyRD::sky_get_radiance_texture_rd(RID p_sky) const { +RID SkyRD::sky_get_radiance_texture_rd(RID p_sky) const { Sky *sky = get_sky(p_sky); ERR_FAIL_COND_V(!sky, RID()); diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/environment/sky.h index a8ee406abc..c3962f20b7 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/environment/sky.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_scene_sky_rd.h */ +/* sky.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,14 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_SKY_RD_H -#define RENDERING_SERVER_SCENE_SKY_RD_H +#ifndef SKY_RD_H +#define SKY_RD_H #include "core/templates/rid_owner.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" -#include "servers/rendering/renderer_rd/shaders/sky.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/sky.glsl.gen.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" @@ -44,7 +44,9 @@ // Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound class RendererSceneRenderRD; -class RendererSceneSkyRD { +namespace RendererRD { + +class SkyRD { public: enum SkySet { SKY_SET_UNIFORMS, @@ -128,6 +130,7 @@ private: bool uses_light = false; virtual void set_code(const String &p_Code); + virtual void set_path_hint(const String &p_hint); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; @@ -141,7 +144,7 @@ private: virtual ~SkyShaderData(); }; - void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier); + void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier); public: struct SkySceneState { @@ -289,16 +292,16 @@ public: RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader); - RendererSceneSkyRD(); + SkyRD(); void init(); void set_texture_format(RD::DataFormat p_texture_format); - ~RendererSceneSkyRD(); + ~SkyRD(); - void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); - void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); - void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer - void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); - void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); + void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); + void update(RendererSceneEnvironmentRD *p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); + void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer + void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); + void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); void invalidate_sky(Sky *p_sky); void update_dirty_skys(); @@ -317,4 +320,6 @@ public: RID sky_get_radiance_texture_rd(RID p_sky) const; }; -#endif /* RENDERING_SERVER_SCENE_SKY_RD_H */ +} // namespace RendererRD + +#endif // SKY_RD_H diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index f759fa3aa5..4a55a04cd4 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -66,6 +66,13 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() } specular = RD::get_singleton()->texture_create(tf, RD::TextureView()); + if (view_count == 1) { + specular_views[0] = specular; + } else { + for (uint32_t v = 0; v < view_count; v++) { + specular_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), specular, v, 0); + } + } if (msaa == RS::VIEWPORT_MSAA_DISABLED) { { @@ -80,6 +87,14 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; specular_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + if (view_count == 1) { + specular_msaa_views[0] = specular_msaa; + } else { + for (uint32_t v = 0; v < view_count; v++) { + specular_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), specular_msaa, v, 0); + } + } + { Vector<RID> fb; fb.push_back(specular_msaa); @@ -171,29 +186,26 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() } void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { + // note, slices are freed automatically when the parent texture is freed so we just clear them. + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + color_views[v] = RID(); + depth_views[v] = RID(); + specular_views[v] = RID(); + specular_msaa_views[v] = RID(); + color_msaa_views[v] = RID(); + depth_msaa_views[v] = RID(); + normal_roughness_views[v] = RID(); + normal_roughness_msaa_views[v] = RID(); + voxelgi_views[v] = RID(); + voxelgi_msaa_views[v] = RID(); + vrs_views[v] = RID(); + } + if (voxelgi_buffer != RID()) { RD::get_singleton()->free(voxelgi_buffer); voxelgi_buffer = RID(); - if (view_count == 1) { - voxelgi_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(voxelgi_views[v]); - voxelgi_views[v] = RID(); - } - } - if (voxelgi_buffer_msaa.is_valid()) { - if (view_count == 1) { - voxelgi_msaa_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(voxelgi_msaa_views[v]); - voxelgi_msaa_views[v] = RID(); - } - } - RD::get_singleton()->free(voxelgi_buffer_msaa); voxelgi_buffer_msaa = RID(); } @@ -202,35 +214,11 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { } if (color_msaa.is_valid()) { - if (view_count == 1) { - color_views[0] = RID(); - color_msaa_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(color_views[v]); - RD::get_singleton()->free(color_msaa_views[v]); - color_views[v] = RID(); - color_msaa_views[v] = RID(); - } - } - RD::get_singleton()->free(color_msaa); color_msaa = RID(); } if (depth_msaa.is_valid()) { - if (view_count == 1) { - depth_views[0] = RID(); - depth_msaa_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(depth_views[v]); - RD::get_singleton()->free(depth_msaa_views[v]); - depth_views[v] = RID(); - depth_msaa_views[v] = RID(); - } - } - RD::get_singleton()->free(depth_msaa); depth_msaa = RID(); } @@ -245,33 +233,17 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { } color = RID(); + color_only_fb = RID(); depth = RID(); depth_fb = RID(); color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations if (normal_roughness_buffer.is_valid()) { - if (view_count == 1) { - normal_roughness_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(normal_roughness_views[v]); - normal_roughness_views[v] = RID(); - } - } - RD::get_singleton()->free(normal_roughness_buffer); normal_roughness_buffer = RID(); if (normal_roughness_buffer_msaa.is_valid()) { - if (view_count == 1) { - normal_roughness_msaa_views[0] = RID(); - } else { - for (uint32_t v = 0; v < view_count; v++) { - RD::get_singleton()->free(normal_roughness_msaa_views[v]); - normal_roughness_msaa_views[v] = RID(); - } - } RD::get_singleton()->free(normal_roughness_buffer_msaa); normal_roughness_buffer_msaa = RID(); } @@ -294,11 +266,12 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { } } -void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) { +void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) { clear(); msaa = p_msaa; use_taa = p_use_taa; + vrs = p_vrs_texture; width = p_width; height = p_height; @@ -307,11 +280,26 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c color = p_color_buffer; depth = p_depth_buffer; + if (vrs.is_valid()) { + if (view_count == 1) { + // just reuse + vrs_views[0] = vrs; + } else { + // create slices + for (uint32_t v = 0; v < view_count; v++) { + vrs_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), vrs, v, 0); + } + } + } + if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) { { Vector<RID> fb; fb.push_back(p_color_buffer); fb.push_back(depth); + if (vrs.is_valid()) { + fb.push_back(vrs); + } color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } @@ -371,6 +359,9 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c Vector<RID> fb; fb.push_back(color_msaa); fb.push_back(depth_msaa); + if (vrs.is_valid()) { + fb.push_back(vrs); + } color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } @@ -409,6 +400,10 @@ RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb( fb.push_back(use_msaa ? depth_msaa : depth); + if (vrs.is_valid()) { + fb.push_back(vrs); + } + int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1; RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count); color_framebuffers[p_color_pass_flags] = framebuffer; @@ -780,7 +775,7 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis void RenderForwardClustered::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) { uint32_t render_total = p_params->element_count; - uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count(); + uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count(); uint32_t render_from = p_thread * render_total / total_threads; uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads); _render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to); @@ -792,9 +787,10 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time //multi threaded - thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); - RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardClustered::_render_list_thread_function, p_params); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardClustered::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardClusteredRenderList")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); RD::get_singleton()->draw_list_end(p_params->barrier); } else { //single threaded @@ -805,12 +801,12 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p } void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { - //CameraMatrix projection = p_render_data->cam_projection; + //Projection projection = p_render_data->cam_projection; //projection.flip_y(); // Vulkan and modern APIs use Y-Down - CameraMatrix correction; + Projection correction; correction.set_depth_correction(p_flip_y); correction.add_jitter_offset(p_render_data->taa_jitter); - CameraMatrix projection = correction * p_render_data->cam_projection; + Projection projection = correction * p_render_data->cam_projection; //store camera into ubo RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix); @@ -1000,10 +996,10 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat if (render_buffers->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { memcpy(&scene_state.prev_ubo, &scene_state.ubo, sizeof(SceneState::UBO)); - CameraMatrix prev_correction; + Projection prev_correction; prev_correction.set_depth_correction(true); prev_correction.add_jitter_offset(p_render_data->prev_taa_jitter); - CameraMatrix prev_projection = prev_correction * p_render_data->prev_cam_projection; + Projection prev_projection = prev_correction * p_render_data->prev_cam_projection; //store camera into ubo RendererRD::MaterialStorage::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix); @@ -1593,9 +1589,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); RD::get_singleton()->draw_command_begin_label("Setup Sky"); - CameraMatrix projection = p_render_data->cam_projection; + Projection projection = p_render_data->cam_projection; if (p_render_data->reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); projection = correction * p_render_data->cam_projection; } @@ -1673,8 +1669,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co continue_depth = !finish_depth; } - RID null_rids[2]; - _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_views : null_rids, render_buffer ? render_buffer->voxelgi_buffer : RID()); + RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS]; + _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_views : nullrids, render_buffer ? render_buffer->voxelgi_buffer : RID(), render_buffer ? render_buffer->vrs_views : nullrids); RD::get_singleton()->draw_command_begin_label("Render Opaque Pass"); @@ -1724,9 +1720,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only); bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only); - CameraMatrix dc; + Projection dc; dc.set_depth_correction(true); - CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); + Projection cm = (dc * p_render_data->cam_projection) * Projection(p_render_data->cam_transform.affine_inverse()); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs"); for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) { @@ -1741,11 +1737,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only); bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only); - CameraMatrix dc; + Projection dc; dc.set_depth_correction(true); - CameraMatrix cms[RendererSceneRender::MAX_RENDER_VIEWS]; + Projection cms[RendererSceneRender::MAX_RENDER_VIEWS]; for (uint32_t v = 0; v < p_render_data->view_count; v++) { - cms[v] = (dc * p_render_data->view_projection[v]) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); + cms[v] = (dc * p_render_data->view_projection[v]) * Projection(p_render_data->cam_transform.affine_inverse()); } _debug_sdfgi_probes(p_render_data->render_buffers, color_only_framebuffer, p_render_data->view_count, cms, will_continue_color, will_continue_depth); } @@ -1756,9 +1752,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Draw Sky"); if (p_render_data->reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); - CameraMatrix projection = correction * p_render_data->cam_projection; + Projection projection = correction * p_render_data->cam_projection; sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time); } else { sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time); @@ -1771,9 +1767,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co for (uint32_t v = 0; v < render_buffer->view_count; v++) { RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa_views[v], render_buffer->color_views[v]); } - // TODO mame this do multiview if (using_separate_specular) { - RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa, render_buffer->specular); + for (uint32_t v = 0; v < render_buffer->view_count; v++) { + RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa_views[v], render_buffer->specular_views[v]); + } } } @@ -1794,12 +1791,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (using_ssr) { RENDER_TIMESTAMP("Screen-Space Reflections"); RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections"); - _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); + _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_views, render_buffer->specular, render_buffer->specular_views, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->view_projection, p_render_data->view_eye_offset, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); RD::get_singleton()->draw_command_end_label(); } else { //just mix specular back RENDER_TIMESTAMP("Merge Specular"); - RendererCompositorRD::singleton->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID()); + copy_effects->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID(), p_render_data->view_count); } } @@ -1876,7 +1873,7 @@ void RenderForwardClustered::_render_shadow_begin() { scene_state.instance_data[RENDER_LIST_SECONDARY].clear(); } -void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) { +void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) { uint32_t shadow_pass_index = scene_state.shadow_passes.size(); SceneState::ShadowPass shadow_pass; @@ -1966,7 +1963,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) { RD::get_singleton()->draw_command_end_label(); } -void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { +void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D"); RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); @@ -2005,7 +2002,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con RD::get_singleton()->draw_command_end_label(); } -void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering 3D Material"); RD::get_singleton()->draw_command_begin_label("Render 3D Material"); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 9e1f1b9954..2bdf48c72f 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H -#define RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H +#ifndef RENDER_FORWARD_CLUSTERED_H +#define RENDER_FORWARD_CLUSTERED_H #include "core/templates/paged_allocator.h" #include "servers/rendering/renderer_rd/effects/resolve.h" @@ -107,26 +107,32 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID depth_normal_roughness_voxelgi_fb; RID color_only_fb; RID specular_only_fb; + + RID vrs; + int width, height; HashMap<uint32_t, RID> color_framebuffers; // for multiview - uint32_t view_count; + uint32_t view_count = 1; RID color_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this RID depth_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this + RID specular_views[RendererSceneRender::MAX_RENDER_VIEWS]; + RID specular_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID color_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID depth_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID normal_roughness_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID voxelgi_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID voxelgi_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; + RID vrs_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID render_sdfgi_uniform_set; void ensure_specular(); void ensure_voxelgi(); void ensure_velocity(); void clear(); - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count); + virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture); RID get_color_pass_fb(uint32_t p_color_pass_flags); ~RenderBufferDataForwardClustered(); @@ -634,14 +640,14 @@ protected: virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; virtual void _render_shadow_begin() override; - virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override; + virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override; virtual void _render_shadow_process() override; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override; - virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override; + virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override; public: _FORCE_INLINE_ virtual void update_uniform_sets() override { @@ -687,4 +693,5 @@ public: ~RenderForwardClustered(); }; } // namespace RendererSceneRenderImplementation -#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H + +#endif // RENDER_FORWARD_CLUSTERED_H diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 1951bfe915..a2995a8902 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -37,6 +37,10 @@ using namespace RendererSceneRenderImplementation; +void SceneShaderForwardClustered::ShaderData::set_path_hint(const String &p_path) { + path = p_path; +} + void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { //compile @@ -403,7 +407,22 @@ void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 1cfe723174..fb001d6933 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RSSR_SCENE_SHADER_FC_H -#define RSSR_SCENE_SHADER_FC_H +#ifndef SCENE_SHADER_FORWARD_CLUSTERED_H +#define SCENE_SHADER_FORWARD_CLUSTERED_H #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h" @@ -180,6 +180,7 @@ public: uint32_t index = 0; virtual void set_code(const String &p_Code); + virtual void set_path_hint(const String &p_path); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; @@ -251,4 +252,5 @@ public: }; } // namespace RendererSceneRenderImplementation -#endif // !RSSR_SCENE_SHADER_FM_H + +#endif // SCENE_SHADER_FORWARD_CLUSTERED_H diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index e1855ddb36..0ca71080fc 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -87,10 +87,11 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() { } } -void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) { +void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) { clear(); msaa = p_msaa; + vrs = p_vrs_texture; Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer); @@ -108,6 +109,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b Vector<RID> fb; fb.push_back(p_color_buffer); // 0 - color buffer fb.push_back(depth); // 1 - depth buffer + if (vrs.is_valid()) { + fb.push_back(vrs); // 2 - vrs texture + } // Now define our subpasses Vector<RD::FramebufferPass> passes; @@ -116,6 +120,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b // re-using the same attachments pass.color_attachments.push_back(0); pass.depth_attachment = 1; + if (vrs.is_valid()) { + pass.vrs_attachment = 2; + } // - opaque pass passes.push_back(pass); @@ -131,12 +138,13 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b if (!is_scaled) { // - add blit to 2D pass - fb.push_back(p_target_buffer); // 2 - target buffer + int target_buffer_id = fb.size(); + fb.push_back(p_target_buffer); // 2/3 - target buffer RD::FramebufferPass blit_pass; - blit_pass.color_attachments.push_back(2); + blit_pass.color_attachments.push_back(target_buffer_id); blit_pass.input_attachments.push_back(0); - passes.push_back(blit_pass); + passes.push_back(blit_pass); // this doesn't need VRS color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); } else { @@ -179,6 +187,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b Vector<RID> fb; fb.push_back(color_msaa); // 0 - msaa color buffer fb.push_back(depth_msaa); // 1 - msaa depth buffer + if (vrs.is_valid()) { + fb.push_back(vrs); // 2 - vrs texture + } // Now define our subpasses Vector<RD::FramebufferPass> passes; @@ -187,18 +198,22 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b // re-using the same attachments pass.color_attachments.push_back(0); pass.depth_attachment = 1; + if (vrs.is_valid()) { + pass.vrs_attachment = 2; + } // - opaque pass passes.push_back(pass); // - add sky pass - fb.push_back(color); // 2 - color buffer + int color_buffer_id = fb.size(); + fb.push_back(color); // color buffer passes.push_back(pass); // without resolve for our 3 + 4 subpass config { // but with resolve for our 2 subpass config Vector<RD::FramebufferPass> two_passes; two_passes.push_back(pass); // opaque subpass without resolve - pass.resolve_attachments.push_back(2); + pass.resolve_attachments.push_back(color_buffer_id); two_passes.push_back(pass); // sky subpass with resolve color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count); @@ -217,10 +232,11 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b if (!is_scaled) { // - add blit to 2D pass - fb.push_back(p_target_buffer); // 3 - target buffer + int target_buffer_id = fb.size(); + fb.push_back(p_target_buffer); // target buffer RD::FramebufferPass blit_pass; - blit_pass.color_attachments.push_back(3); - blit_pass.input_attachments.push_back(2); + blit_pass.color_attachments.push_back(target_buffer_id); + blit_pass.input_attachments.push_back(color_buffer_id); passes.push_back(blit_pass); color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); @@ -632,9 +648,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); RD::get_singleton()->draw_command_begin_label("Setup Sky"); - CameraMatrix projection = p_render_data->cam_projection; + Projection projection = p_render_data->cam_projection; if (p_render_data->reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); projection = correction * p_render_data->cam_projection; } @@ -664,9 +680,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers"); if (p_render_data->reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); - CameraMatrix projection = correction * p_render_data->cam_projection; + Projection projection = correction * p_render_data->cam_projection; sky.update_res_buffers(env, 1, &projection, p_render_data->cam_transform, time); } else { sky.update_res_buffers(env, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time); @@ -675,8 +691,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers } - RID null_rids[2]; - _pre_opaque_render(p_render_data, false, false, false, null_rids, RID()); + RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS]; + _pre_opaque_render(p_render_data, false, false, false, nullrids, RID(), nullrids); uint32_t spec_constant_base_flags = 0; @@ -742,9 +758,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time //multi threaded - thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); - RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params); + + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderList")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + } else { //single threaded RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); @@ -760,9 +779,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass(); if (p_render_data->reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); - CameraMatrix projection = correction * p_render_data->cam_projection; + Projection projection = correction * p_render_data->cam_projection; sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier()); } else { sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier()); @@ -806,10 +825,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time //multi threaded - thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); RD::get_singleton()->draw_list_switch_to_next_pass_split(thread_draw_lists.size(), thread_draw_lists.ptr()); render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass(); - RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + } else { //single threaded RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass(); @@ -843,9 +864,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time //multi threaded - thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); - RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL); } else { //single threaded @@ -884,7 +907,7 @@ void RenderForwardMobile::_render_shadow_begin() { render_list[RENDER_LIST_SECONDARY].clear(); } -void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) { +void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) { uint32_t shadow_pass_index = scene_state.shadow_passes.size(); SceneState::ShadowPass shadow_pass; @@ -978,7 +1001,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) { /* */ -void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering 3D Material"); RD::get_singleton()->draw_command_begin_label("Render 3D Material"); @@ -1095,7 +1118,7 @@ void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_ // we don't do GI in low end.. } -void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { +void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D"); RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); @@ -1527,11 +1550,11 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, // This populates our UBO with main scene data that is pushed into set 1 - //CameraMatrix projection = p_render_data->cam_projection; + //Projection projection = p_render_data->cam_projection; //projection.flip_y(); // Vulkan and modern APIs use Y-Down - CameraMatrix correction; + Projection correction; correction.set_depth_correction(p_flip_y); - CameraMatrix projection = correction * p_render_data->cam_projection; + Projection projection = correction * p_render_data->cam_projection; //store camera into ubo RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix); @@ -1755,7 +1778,7 @@ void RenderForwardMobile::_render_list(RenderingDevice::DrawListID p_draw_list, void RenderForwardMobile::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) { uint32_t render_total = p_params->element_count; - uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count(); + uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count(); uint32_t render_from = p_thread * render_total / total_threads; uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads); _render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to); @@ -1767,9 +1790,11 @@ void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_para if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time //multi threaded - thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count()); RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); - RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, p_params); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + RD::get_singleton()->draw_list_end(p_params->barrier); } else { //single threaded diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 473a58045c..5b1109512a 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H -#define RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H +#ifndef RENDER_FORWARD_MOBILE_H +#define RENDER_FORWARD_MOBILE_H #include "core/templates/paged_allocator.h" #include "servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h" @@ -131,12 +131,14 @@ protected: RID depth_msaa; // RID normal_roughness_buffer_msaa; + RID vrs; + RID color_fbs[FB_CONFIG_MAX]; int width, height; uint32_t view_count; void clear(); - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count); + virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture); ~RenderBufferDataForwardMobile(); }; @@ -210,14 +212,14 @@ protected: virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; virtual void _render_shadow_begin() override; - virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override; + virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override; virtual void _render_shadow_process() override; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override; - virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override; + virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override; uint64_t lightmap_texture_array_version = 0xFFFFFFFF; @@ -672,4 +674,5 @@ public: ~RenderForwardMobile(); }; } // namespace RendererSceneRenderImplementation -#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H + +#endif // RENDER_FORWARD_MOBILE_H diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index dd00dc2bf9..ee902e5c52 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -39,6 +39,10 @@ using namespace RendererSceneRenderImplementation; /* ShaderData */ +void SceneShaderForwardMobile::ShaderData::set_path_hint(const String &p_path) { + path = p_path; +} + void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { //compile @@ -360,7 +364,22 @@ void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_ } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 88c2143b09..0dbed0b07a 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RSSR_SCENE_SHADER_FM_H -#define RSSR_SCENE_SHADER_FM_H +#ifndef SCENE_SHADER_FORWARD_MOBILE_H +#define SCENE_SHADER_FORWARD_MOBILE_H #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl.gen.h" @@ -139,6 +139,8 @@ public: uint32_t index = 0; virtual void set_code(const String &p_Code); + virtual void set_path_hint(const String &p_path); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; @@ -210,4 +212,5 @@ public: }; } // namespace RendererSceneRenderImplementation -#endif // !RSSR_SCENE_SHADER_FM_H + +#endif // SCENE_SHADER_FORWARD_MOBILE_H diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h index ad83fc76b7..882e459bcd 100644 --- a/servers/rendering/renderer_rd/pipeline_cache_rd.h +++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h @@ -97,4 +97,4 @@ public: ~PipelineCacheRD(); }; -#endif // RENDER_PIPELINE_CACHE_RD_H +#endif // PIPELINE_CACHE_RD_H diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index b87b189d53..a58cdd5066 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -528,7 +528,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } if (rect->flags & CANVAS_RECT_TRANSPOSE) { - dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform + push_constant.flags |= FLAGS_TRANSPOSE_RECT; } if (rect->flags & CANVAS_RECT_CLIP_UV) { @@ -1581,9 +1581,10 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); + RD::InitialAction initial_action = i == 0 ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE; + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, initial_action, i != 3 ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, initial_action, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); - CameraMatrix projection; + Projection projection; { real_t fov = 90; real_t nearp = p_near; @@ -1599,7 +1600,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, } Vector3 cam_target = Basis(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0)); - projection = projection * CameraMatrix(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse()); + projection = projection * Projection(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse()); ShadowRenderPushConstant push_constant; for (int y = 0; y < 4; y++) { @@ -1670,11 +1671,11 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh cc.push_back(Color(1, 1, 1, 1)); Rect2i rect(0, p_shadow_index * 2, state.shadow_texture_size, 2); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); - CameraMatrix projection; + Projection projection; projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance); - projection = projection * CameraMatrix(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse()); + projection = projection * Projection(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse()); ShadowRenderPushConstant push_constant; for (int y = 0; y < 4; y++) { @@ -1742,7 +1743,7 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc); - CameraMatrix projection; + Projection projection; ShadowRenderPushConstant push_constant; for (int y = 0; y < 4; y++) { @@ -1967,6 +1968,10 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS:: oc->cull_mode = p_mode; } +void RendererCanvasRenderRD::CanvasShaderData::set_path_hint(const String &p_path) { + path = p_path; +} + void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { //compile @@ -2180,7 +2185,22 @@ void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); @@ -2431,6 +2451,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n"; + actions.usage_defines["SPECULAR_SHININESS"] = "#define SPECULAR_SHININESS_USED\n"; actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 2ab5a7c831..1c0567b677 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_CANVAS_RENDER_RD_H -#define RENDERING_SERVER_CANVAS_RENDER_RD_H +#ifndef RENDERER_CANVAS_RENDER_RD_H +#define RENDERER_CANVAS_RENDER_RD_H #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_compositor.h" @@ -178,6 +178,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { bool uses_time = false; virtual void set_code(const String &p_Code); + virtual void set_path_hint(const String &p_path); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; @@ -464,4 +465,4 @@ public: ~RendererCanvasRenderRD(); }; -#endif // RASTERIZER_CANVAS_RD_H +#endif // RENDERER_CANVAS_RENDER_RD_H diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 2be55743fb..564c26bfe4 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -28,11 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_COMPOSITOR_RD_H -#define RENDERING_SERVER_COMPOSITOR_RD_H +#ifndef RENDERER_COMPOSITOR_RD_H +#define RENDERER_COMPOSITOR_RD_H #include "core/os/os.h" -#include "core/templates/thread_work_pool.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/effects_rd.h" #include "servers/rendering/renderer_rd/environment/fog.h" @@ -148,4 +147,5 @@ public: RendererCompositorRD(); ~RendererCompositorRD(); }; -#endif // RASTERIZER_RD_H + +#endif // RENDERER_COMPOSITOR_RD_H diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h index 4e170b8cfb..d9f78b3bc3 100644 --- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H -#define RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H +#ifndef RENDERER_SCENE_ENVIRONMENT_RD_H +#define RENDERER_SCENE_ENVIRONMENT_RD_H #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" @@ -164,4 +164,4 @@ public: void set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect); }; -#endif /* !RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H */ +#endif // RENDERER_SCENE_ENVIRONMENT_RD_H diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 5185d537ec..3161f03192 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -558,29 +558,28 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba //////////////////////////////////////////////////////////// RID RendererSceneRenderRD::fog_volume_instance_create(RID p_fog_volume) { - FogVolumeInstance fvi; - fvi.volume = p_fog_volume; - return fog_volume_instance_owner.make_rid(fvi); + return RendererRD::Fog::get_singleton()->fog_volume_instance_create(p_fog_volume); } + void RendererSceneRenderRD::fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) { - FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance); ERR_FAIL_COND(!fvi); fvi->transform = p_transform; } void RendererSceneRenderRD::fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) { - FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance); ERR_FAIL_COND(!fvi); fvi->active = p_active; } RID RendererSceneRenderRD::fog_volume_instance_get_volume(RID p_fog_volume_instance) const { - FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance); ERR_FAIL_COND_V(!fvi, RID()); return fvi->volume; } Vector3 RendererSceneRenderRD::fog_volume_instance_get_position(RID p_fog_volume_instance) const { - FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + RendererRD::Fog::FogVolumeInstance *fvi = RendererRD::Fog::get_singleton()->get_fog_volume_instance(p_fog_volume_instance); ERR_FAIL_COND_V(!fvi, Vector3()); return fvi->transform.get_origin(); @@ -1430,7 +1429,7 @@ void RendererSceneRenderRD::light_instance_set_aabb(RID p_light_instance, const light_instance->aabb = p_aabb; } -void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) { +void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) { LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); ERR_FAIL_COND(!light_instance); @@ -1534,7 +1533,7 @@ void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_ins gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this); } -void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { +void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -1827,6 +1826,16 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { rb->sss_texture = RID(); } + if (rb->vrs_fb.is_valid()) { + RD::get_singleton()->free(rb->vrs_fb); + rb->vrs_fb = RID(); + } + + if (rb->vrs_texture.is_valid()) { + RD::get_singleton()->free(rb->vrs_texture); + rb->vrs_texture = RID(); + } + for (int i = 0; i < 2; i++) { for (int l = 0; l < rb->blur[i].layers.size(); l++) { for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) { @@ -1881,60 +1890,9 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { rb->ss_effects.linear_depth_slices.clear(); } - if (rb->ss_effects.ssao.ao_final.is_valid()) { - RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved); - RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong); - RD::get_singleton()->free(rb->ss_effects.ssao.ao_final); - - RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]); - RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]); - - rb->ss_effects.ssao.ao_deinterleaved = RID(); - rb->ss_effects.ssao.ao_pong = RID(); - rb->ss_effects.ssao.ao_final = RID(); - rb->ss_effects.ssao.importance_map[0] = RID(); - rb->ss_effects.ssao.importance_map[1] = RID(); - - rb->ss_effects.ssao.ao_deinterleaved_slices.clear(); - rb->ss_effects.ssao.ao_pong_slices.clear(); - } - - if (rb->ss_effects.ssil.ssil_final.is_valid()) { - RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final); - RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved); - RD::get_singleton()->free(rb->ss_effects.ssil.pong); - RD::get_singleton()->free(rb->ss_effects.ssil.edges); - RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]); - RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]); - - rb->ss_effects.ssil.ssil_final = RID(); - rb->ss_effects.ssil.deinterleaved = RID(); - rb->ss_effects.ssil.pong = RID(); - rb->ss_effects.ssil.edges = RID(); - rb->ss_effects.ssil.deinterleaved_slices.clear(); - rb->ss_effects.ssil.pong_slices.clear(); - rb->ss_effects.ssil.edges_slices.clear(); - rb->ss_effects.ssil.importance_map[0] = RID(); - rb->ss_effects.ssil.importance_map[1] = RID(); - - RD::get_singleton()->free(rb->ss_effects.last_frame); - rb->ss_effects.last_frame = RID(); - rb->ss_effects.last_frame_slices.clear(); - } - - if (rb->ssr.blur_radius[0].is_valid()) { - RD::get_singleton()->free(rb->ssr.blur_radius[0]); - RD::get_singleton()->free(rb->ssr.blur_radius[1]); - rb->ssr.blur_radius[0] = RID(); - rb->ssr.blur_radius[1] = RID(); - } - - if (rb->ssr.depth_scaled.is_valid()) { - RD::get_singleton()->free(rb->ssr.depth_scaled); - rb->ssr.depth_scaled = RID(); - RD::get_singleton()->free(rb->ssr.normal_scaled); - rb->ssr.normal_scaled = RID(); - } + ss_effects->ssao_free(rb->ss_effects.ssao); + ss_effects->ssil_free(rb->ss_effects.ssil); + ss_effects->ssr_free(rb->ssr); if (rb->taa.history.is_valid()) { RD::get_singleton()->free(rb->taa.history); @@ -1954,7 +1912,7 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { rb->rbgi.free(); } -void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) { +void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const Projection &p_camera) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -1972,7 +1930,9 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri RendererCompositorRD::singleton->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality); } -void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) { +void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive) { + ERR_FAIL_NULL(ss_effects); + RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -1980,7 +1940,7 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb if (!can_use_effects) { //just copy - RendererCompositorRD::singleton->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID()); + copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID(), rb->view_count); return; } @@ -1989,42 +1949,23 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb ERR_FAIL_COND(!env->ssr_enabled); - if (rb->ssr.depth_scaled.is_null()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - tf.width = rb->internal_width / 2; - tf.height = rb->internal_height / 2; - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; - - rb->ssr.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - - rb->ssr.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - - if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = rb->internal_width / 2; - tf.height = rb->internal_height / 2; - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - - rb->ssr.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - rb->ssr.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + Size2i half_size = Size2i(rb->internal_width / 2, rb->internal_height / 2); + if (rb->ssr.output.is_null()) { + ss_effects->ssr_allocate_buffers(rb->ssr, _render_buffers_get_color_format(), ssr_roughness_quality, half_size, rb->view_count); } - - if (rb->blur[0].texture.is_null()) { - _allocate_blur_textures(rb); + RID texture_slices[RendererSceneRender::MAX_RENDER_VIEWS]; + RID depth_slices[RendererSceneRender::MAX_RENDER_VIEWS]; + for (uint32_t v = 0; v < rb->view_count; v++) { + texture_slices[v] = rb->views[v].view_texture; + depth_slices[v] = rb->views[v].view_depth; } - - RendererCompositorRD::singleton->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); - RendererCompositorRD::singleton->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture); + ss_effects->screen_space_reflection(rb->ssr, texture_slices, p_normal_slices, ssr_roughness_quality, p_metallic_slices, p_metallic_mask, depth_slices, half_size, env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, rb->view_count, p_projections, p_eye_offsets); + copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->ssr.output, rb->view_count); } -void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) { +void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection) { + ERR_FAIL_NULL(ss_effects); + RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -2033,102 +1974,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen RENDER_TIMESTAMP("Process SSAO"); - if (rb->ss_effects.ssao.ao_final.is_valid() && ssao_using_half_size != ssao_half_size) { - RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved); - RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong); - RD::get_singleton()->free(rb->ss_effects.ssao.ao_final); - - RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]); - RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]); - - rb->ss_effects.ssao.ao_deinterleaved = RID(); - rb->ss_effects.ssao.ao_pong = RID(); - rb->ss_effects.ssao.ao_final = RID(); - rb->ss_effects.ssao.importance_map[0] = RID(); - rb->ss_effects.ssao.importance_map[1] = RID(); - rb->ss_effects.ssao.ao_deinterleaved_slices.clear(); - rb->ss_effects.ssao.ao_pong_slices.clear(); - } - - int buffer_width; - int buffer_height; - int half_width; - int half_height; - if (ssao_half_size) { - buffer_width = (rb->internal_width + 3) / 4; - buffer_height = (rb->internal_height + 3) / 4; - half_width = (rb->internal_width + 7) / 8; - half_height = (rb->internal_height + 7) / 8; - } else { - buffer_width = (rb->internal_width + 1) / 2; - buffer_height = (rb->internal_height + 1) / 2; - half_width = (rb->internal_width + 3) / 4; - half_height = (rb->internal_height + 3) / 4; - } - bool uniform_sets_are_invalid = false; - if (rb->ss_effects.ssao.ao_deinterleaved.is_null()) { - { - rb->ss_effects.ssao.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssao_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8G8_UNORM; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = buffer_width; - tf.height = buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssao.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_deinterleaved, "SSAO De-interleaved Array"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_deinterleaved, i, 0); - rb->ss_effects.ssao.ao_deinterleaved_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " "); - } - } - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8G8_UNORM; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = buffer_width; - tf.height = buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssao.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_pong, "SSAO De-interleaved Array Pong"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_pong, i, 0); - rb->ss_effects.ssao.ao_pong_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong"); - } - } - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = half_width; - tf.height = half_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssao.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[0], "SSAO Importance Map"); - rb->ss_effects.ssao.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[1], "SSAO Importance Map Pong"); - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = rb->internal_width; - tf.height = rb->internal_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_final, "SSAO Final"); - } - ssao_using_half_size = ssao_half_size; - uniform_sets_are_invalid = true; - } - - EffectsRD::SSAOSettings settings; + RendererRD::SSEffects::SSAOSettings settings; settings.radius = env->ssao_radius; settings.intensity = env->ssao_intensity; settings.power = env->ssao_power; @@ -2143,13 +1989,14 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen settings.fadeout_from = ssao_fadeout_from; settings.fadeout_to = ssao_fadeout_to; settings.full_screen_size = Size2i(rb->internal_width, rb->internal_height); - settings.half_screen_size = Size2i(buffer_width, buffer_height); - settings.quarter_screen_size = Size2i(half_width, half_height); - RendererCompositorRD::singleton->get_effects()->generate_ssao(p_normal_buffer, rb->ss_effects.ssao.depth_texture_view, rb->ss_effects.ssao.ao_deinterleaved, rb->ss_effects.ssao.ao_deinterleaved_slices, rb->ss_effects.ssao.ao_pong, rb->ss_effects.ssao.ao_pong_slices, rb->ss_effects.ssao.ao_final, rb->ss_effects.ssao.importance_map[0], rb->ss_effects.ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssao.gather_uniform_set, rb->ss_effects.ssao.importance_map_uniform_set); + ss_effects->ssao_allocate_buffers(rb->ss_effects.ssao, settings, rb->ss_effects.linear_depth); + ss_effects->generate_ssao(rb->ss_effects.ssao, p_normal_buffer, p_projection, settings); } -void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform) { +void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform) { + ERR_FAIL_NULL(ss_effects); + RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -2158,133 +2005,7 @@ void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environmen RENDER_TIMESTAMP("Process SSIL"); - if (rb->ss_effects.ssil.ssil_final.is_valid() && ssil_using_half_size != ssil_half_size) { - RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final); - RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved); - RD::get_singleton()->free(rb->ss_effects.ssil.pong); - RD::get_singleton()->free(rb->ss_effects.ssil.edges); - RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]); - RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]); - - rb->ss_effects.ssil.ssil_final = RID(); - rb->ss_effects.ssil.deinterleaved = RID(); - rb->ss_effects.ssil.pong = RID(); - rb->ss_effects.ssil.edges = RID(); - rb->ss_effects.ssil.deinterleaved_slices.clear(); - rb->ss_effects.ssil.pong_slices.clear(); - rb->ss_effects.ssil.edges_slices.clear(); - rb->ss_effects.ssil.importance_map[0] = RID(); - rb->ss_effects.ssil.importance_map[1] = RID(); - } - - int buffer_width; - int buffer_height; - int half_width; - int half_height; - if (ssil_half_size) { - buffer_width = (rb->width + 3) / 4; - buffer_height = (rb->height + 3) / 4; - half_width = (rb->width + 7) / 8; - half_height = (rb->height + 7) / 8; - } else { - buffer_width = (rb->width + 1) / 2; - buffer_height = (rb->height + 1) / 2; - half_width = (rb->width + 3) / 4; - half_height = (rb->height + 3) / 4; - } - bool uniform_sets_are_invalid = false; - if (rb->ss_effects.ssil.ssil_final.is_null()) { - { - rb->ss_effects.ssil.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssil_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = rb->width; - tf.height = rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - rb->ss_effects.ssil.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.ssil_final, "SSIL texture"); - RD::get_singleton()->texture_clear(rb->ss_effects.ssil.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1); - if (rb->ss_effects.last_frame.is_null()) { - tf.mipmaps = 6; - rb->ss_effects.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.last_frame, "Last Frame Radiance"); - RD::get_singleton()->texture_clear(rb->ss_effects.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1); - for (uint32_t i = 0; i < 6; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.last_frame, 0, i); - rb->ss_effects.last_frame_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " "); - } - } - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = buffer_width; - tf.height = buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssil.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.deinterleaved, "SSIL deinterleaved buffer"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.deinterleaved, i, 0); - rb->ss_effects.ssil.deinterleaved_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " "); - } - } - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = buffer_width; - tf.height = buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssil.pong = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.pong, "SSIL deinterleaved pong buffer"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.pong, i, 0); - rb->ss_effects.ssil.pong_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " "); - } - } - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = buffer_width; - tf.height = buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssil.edges = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.edges, "SSIL edges buffer"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.edges, i, 0); - rb->ss_effects.ssil.edges_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " "); - } - } - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = half_width; - tf.height = half_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.ssil.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[0], "SSIL Importance Map"); - rb->ss_effects.ssil.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[1], "SSIL Importance Map Pong"); - } - uniform_sets_are_invalid = true; - ssil_using_half_size = ssil_half_size; - } - - EffectsRD::SSILSettings settings; + RendererRD::SSEffects::SSILSettings settings; settings.radius = env->ssil_radius; settings.intensity = env->ssil_intensity; settings.sharpness = env->ssil_sharpness; @@ -2297,17 +2018,16 @@ void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environmen settings.fadeout_from = ssil_fadeout_from; settings.fadeout_to = ssil_fadeout_to; settings.full_screen_size = Size2i(rb->width, rb->height); - settings.half_screen_size = Size2i(buffer_width, buffer_height); - settings.quarter_screen_size = Size2i(half_width, half_height); - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); - CameraMatrix projection = correction * p_projection; + Projection projection = correction * p_projection; Transform3D transform = p_transform; transform.set_origin(Vector3(0.0, 0.0, 0.0)); - CameraMatrix last_frame_projection = rb->ss_effects.last_frame_projection * CameraMatrix(rb->ss_effects.last_frame_transform.affine_inverse()) * CameraMatrix(transform) * projection.inverse(); + Projection last_frame_projection = rb->ss_effects.last_frame_projection * Projection(rb->ss_effects.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse(); - RendererCompositorRD::singleton->get_effects()->screen_space_indirect_lighting(rb->ss_effects.last_frame, rb->ss_effects.ssil.ssil_final, p_normal_buffer, rb->ss_effects.ssil.depth_texture_view, rb->ss_effects.ssil.deinterleaved, rb->ss_effects.ssil.deinterleaved_slices, rb->ss_effects.ssil.pong, rb->ss_effects.ssil.pong_slices, rb->ss_effects.ssil.importance_map[0], rb->ss_effects.ssil.importance_map[1], rb->ss_effects.ssil.edges, rb->ss_effects.ssil.edges_slices, p_projection, last_frame_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssil.gather_uniform_set, rb->ss_effects.ssil.importance_map_uniform_set, rb->ss_effects.ssil.projection_uniform_set); + ss_effects->ssil_allocate_buffers(rb->ss_effects.ssil, settings, rb->ss_effects.linear_depth); + ss_effects->screen_space_indirect_lighting(rb->ss_effects.ssil, p_normal_buffer, p_projection, last_frame_projection, settings); rb->ss_effects.last_frame_projection = projection; rb->ss_effects.last_frame_transform = transform; } @@ -2316,15 +2036,15 @@ void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); - if (rb->ss_effects.last_frame.is_valid()) { - copy_effects->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height)); + if (rb->ss_effects.ssil.last_frame.is_valid()) { + copy_effects->copy_to_rect(rb->texture, rb->ss_effects.ssil.last_frame, Rect2i(0, 0, rb->width, rb->height)); int width = rb->width; int height = rb->height; - for (int i = 0; i < rb->ss_effects.last_frame_slices.size() - 1; i++) { + for (int i = 0; i < rb->ss_effects.ssil.last_frame_slices.size() - 1; i++) { width = MAX(1, width >> 1); height = MAX(1, height >> 1); - copy_effects->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height)); + copy_effects->make_mipmap(rb->ss_effects.ssil.last_frame_slices[i], rb->ss_effects.ssil.last_frame_slices[i + 1], Size2i(width, height)); } } } @@ -3151,8 +2871,13 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p } } + RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(rb->render_target); + if (is_vrs_supported() && vrs_mode != RS::VIEWPORT_VRS_DISABLED) { + vrs->create_vrs_texture(p_internal_width, p_internal_height, p_view_count, rb->vrs_texture, rb->vrs_fb); + } + RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target); - rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count); + rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count, rb->vrs_texture); if (is_clustered_enabled()) { rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture); @@ -3176,7 +2901,7 @@ void RendererSceneRenderRD::sub_surface_scattering_set_scale(float p_scale, floa sss_depth_scale = p_depth_scale; } -void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) { +void RendererSceneRenderRD::positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) { ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum"); if (shadows_quality != p_quality) { @@ -3223,7 +2948,7 @@ void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) { _update_shader_quality_settings(); } -void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) { +void RendererSceneRenderRD::directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) { ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum"); if (directional_shadow_quality != p_quality) { @@ -3465,17 +3190,17 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light_storage->light_directional_get_blend_splits(base); for (int j = 0; j < 4; j++) { Rect2 atlas_rect = li->shadow_transform[j].atlas_rect; - CameraMatrix matrix = li->shadow_transform[j].camera; + Projection matrix = li->shadow_transform[j].camera; float split = li->shadow_transform[MIN(limit, j)].split; - CameraMatrix bias; + Projection bias; bias.set_light_bias(); - CameraMatrix rectm; + Projection rectm; rectm.set_light_atlas_rect(atlas_rect); Transform3D modelview = (inverse_transform * li->shadow_transform[j].transform).inverse(); - CameraMatrix shadow_mtx = rectm * bias * matrix * modelview; + Projection shadow_mtx = rectm * bias * matrix * modelview; light_data.shadow_split_offsets[j] = split; float bias_scale = li->shadow_transform[j].bias_scale; light_data.shadow_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale; @@ -3743,16 +3468,16 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.direction[1] = omni_offset.y * float(rect.size.height); } else if (type == RS::LIGHT_SPOT) { Transform3D modelview = (inverse_transform * light_transform).inverse(); - CameraMatrix bias; + Projection bias; bias.set_light_bias(); - CameraMatrix shadow_mtx = bias * li->shadow_transform[0].camera * modelview; + Projection shadow_mtx = bias * li->shadow_transform[0].camera * modelview; RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrix); if (size > 0.0 && light_data.soft_shadow_scale > 0.0) { // Only enable PCSS-like soft shadows if blurring is enabled. // Otherwise, performance would decrease with no visual difference. - CameraMatrix cm = li->shadow_transform[0].camera; + Projection cm = li->shadow_transform[0].camera; float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle)); light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width; } else { @@ -3963,238 +3688,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const //////////////////////////////////////////////////////////////////////////////// // FOG SHADER -void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) { - //compile - - code = p_code; - valid = false; - ubo_size = 0; - uniforms.clear(); - - if (code.is_empty()) { - return; //just invalid, but no error - } - - ShaderCompiler::GeneratedCode gen_code; - ShaderCompiler::IdentifierActions actions; - actions.entry_point_stages["fog"] = ShaderCompiler::STAGE_COMPUTE; - - uses_time = false; - - actions.usage_flag_pointers["TIME"] = &uses_time; - - actions.uniforms = &uniforms; - - RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); - - Error err = scene_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code); - ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed."); - - if (version.is_null()) { - version = scene_singleton->volumetric_fog.shader.version_create(); - } - - scene_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines); - ERR_FAIL_COND(!scene_singleton->volumetric_fog.shader.version_is_valid(version)); - - ubo_size = gen_code.uniform_total_size; - ubo_offsets = gen_code.uniform_offsets; - texture_uniforms = gen_code.texture_uniforms; - - pipeline = RD::get_singleton()->compute_pipeline_create(scene_singleton->volumetric_fog.shader.version_get_shader(version, 0)); - - valid = true; -} - -void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { - if (!p_texture.is_valid()) { - if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { - default_texture_params[p_name].erase(p_index); - - if (default_texture_params[p_name].is_empty()) { - default_texture_params.erase(p_name); - } - } - } else { - if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = HashMap<int, RID>(); - } - default_texture_params[p_name][p_index] = p_texture; - } -} - -void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - RBMap<int, StringName> order; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - if (E.value.texture_order >= 0) { - order[E.value.texture_order + 100000] = E.key; - } else { - order[E.value.order] = E.key; - } - } - - for (const KeyValue<int, StringName> &E : order) { - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); - pi.name = E.value; - p_param_list->push_back(pi); - } -} - -void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E.value); - p.info.name = E.key; //supply name - p.index = E.value.instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); - p_param_list->push_back(p); - } -} - -bool RendererSceneRenderRD::FogShaderData::is_param_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - -bool RendererSceneRenderRD::FogShaderData::is_animated() const { - return false; -} - -bool RendererSceneRenderRD::FogShaderData::casts_shadows() const { - return false; -} - -Variant RendererSceneRenderRD::FogShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); - } - return Variant(); -} - -RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_source_code() const { - RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); - - return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version); -} - -RendererSceneRenderRD::FogShaderData::~FogShaderData() { - RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); - ERR_FAIL_COND(!scene_singleton); - //pipeline variants will clear themselves if shader is gone - if (version.is_valid()) { - scene_singleton->volumetric_fog.shader.version_free(version); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Fog material - -bool RendererSceneRenderRD::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); - - uniform_set_updated = true; - - return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL); -} - -RendererSceneRenderRD::FogMaterialData::~FogMaterialData() { - free_parameters_uniform_set(uniform_set); -} - -RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() { - FogShaderData *shader_data = memnew(FogShaderData); - return shader_data; -} - -RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() { - return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func(); -}; - -RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) { - FogMaterialData *material_data = memnew(FogMaterialData); - material_data->shader_data = p_shader; - //update will happen later anyway so do nothing. - return material_data; -} - -RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) { - return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); -}; - -//////////////////////////////////////////////////////////////////////////////// -// Volumetric Fog - -void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) { - ERR_FAIL_COND(!rb->volumetric_fog); - - RD::get_singleton()->free(rb->volumetric_fog->prev_light_density_map); - RD::get_singleton()->free(rb->volumetric_fog->light_density_map); - RD::get_singleton()->free(rb->volumetric_fog->fog_map); - RD::get_singleton()->free(rb->volumetric_fog->density_map); - RD::get_singleton()->free(rb->volumetric_fog->light_map); - RD::get_singleton()->free(rb->volumetric_fog->emissive_map); - - if (rb->volumetric_fog->fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) { - RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set); - } - if (rb->volumetric_fog->process_uniform_set_density.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set_density)) { - RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set_density); - } - if (rb->volumetric_fog->process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) { - RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set); - } - if (rb->volumetric_fog->process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set2)) { - RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2); - } - if (rb->volumetric_fog->sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) { - RD::get_singleton()->free(rb->volumetric_fog->sdfgi_uniform_set); - } - if (rb->volumetric_fog->sky_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sky_uniform_set)) { - RD::get_singleton()->free(rb->volumetric_fog->sky_uniform_set); - } - - memdelete(rb->volumetric_fog); - - rb->volumetric_fog = nullptr; -} - -Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) { - Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point); - view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera - Vector3 fog_position = Vector3(0, 0, 0); - - view_position.y = -view_position.y; - fog_position.z = -view_position.z / fog_end; - fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5; - fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5; - fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread)); - fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5); - - fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x); - fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y); - fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z); - - return Vector3i(fog_position); -} - -void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { - RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - +void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -4207,7 +3701,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e if (rb->volumetric_fog) { //validate if (!env || !env->volumetric_fog_enabled || rb->volumetric_fog->width != target_width || rb->volumetric_fog->height != target_height || rb->volumetric_fog->depth != volumetric_fog_depth) { - _volumetric_fog_erase(rb); + memdelete(rb->volumetric_fog); + rb->volumetric_fog = nullptr; } } @@ -4216,684 +3711,38 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e return; } - RENDER_TIMESTAMP("> Volumetric Fog"); - RD::get_singleton()->draw_command_begin_label("Volumetric Fog"); - if (env && env->volumetric_fog_enabled && !rb->volumetric_fog) { //required volumetric fog but not existing, create - rb->volumetric_fog = memnew(VolumetricFog); - rb->volumetric_fog->width = target_width; - rb->volumetric_fog->height = target_height; - rb->volumetric_fog->depth = volumetric_fog_depth; - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = target_width; - tf.height = target_height; - tf.depth = volumetric_fog_depth; - tf.texture_type = RD::TEXTURE_TYPE_3D; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - - rb->volumetric_fog->light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_density_map, "Fog light-density map"); - - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - - rb->volumetric_fog->prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->prev_light_density_map, "Fog previous light-density map"); - RD::get_singleton()->texture_clear(rb->volumetric_fog->prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1); - - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - - rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->fog_map, "Fog map"); - -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - Vector<uint8_t> dm; - dm.resize(target_width * target_height * volumetric_fog_depth * 4); - dm.fill(0); - - rb->volumetric_fog->density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map"); - rb->volumetric_fog->light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map"); - rb->volumetric_fog->emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map"); -#else - tf.format = RD::DATA_FORMAT_R32_UINT; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - rb->volumetric_fog->density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map"); - RD::get_singleton()->texture_clear(rb->volumetric_fog->density_map, Color(0, 0, 0, 0), 0, 1, 0, 1); - rb->volumetric_fog->light_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map"); - RD::get_singleton()->texture_clear(rb->volumetric_fog->light_map, Color(0, 0, 0, 0), 0, 1, 0, 1); - rb->volumetric_fog->emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map"); - RD::get_singleton()->texture_clear(rb->volumetric_fog->emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1); -#endif - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 0; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.append_id(rb->volumetric_fog->fog_map); - uniforms.push_back(u); - } - - rb->volumetric_fog->sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky.sky_shader.default_shader_rd, RendererSceneSkyRD::SKY_SET_FOG); - } - - if (p_fog_volumes.size() > 0) { - RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes"); - - RENDER_TIMESTAMP("Render FogVolumes"); - - VolumetricFogShader::VolumeUBO params; - - Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents(); - Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents(); - float z_near = p_cam_projection.get_z_near(); - float z_far = p_cam_projection.get_z_far(); - float fog_end = env->volumetric_fog_length; - - Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near)); - Vector2 fog_near_size; - if (p_cam_projection.is_orthogonal()) { - fog_near_size = fog_far_size; - } else { - fog_near_size = Vector2(); - } - - params.fog_frustum_size_begin[0] = fog_near_size.x; - params.fog_frustum_size_begin[1] = fog_near_size.y; - - params.fog_frustum_size_end[0] = fog_far_size.x; - params.fog_frustum_size_end[1] = fog_far_size.y; - - params.fog_frustum_end = fog_end; - params.z_near = z_near; - params.z_far = z_far; - params.time = time; - - params.fog_volume_size[0] = rb->volumetric_fog->width; - params.fog_volume_size[1] = rb->volumetric_fog->height; - params.fog_volume_size[2] = rb->volumetric_fog->depth; - - params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection; - params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; - params.detail_spread = env->volumetric_fog_detail_spread; - params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount; - - Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; - RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); - RendererRD::MaterialStorage::store_transform(p_cam_transform, params.transform); - - RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); - - if (rb->volumetric_fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) { - Vector<RD::Uniform> uniforms; - - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 1; - u.append_id(rb->volumetric_fog->emissive_map); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.append_id(volumetric_fog.volume_ubo); - uniforms.push_back(u); - } - - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 3; - u.append_id(rb->volumetric_fog->density_map); - uniforms.push_back(u); - } - - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 4; - u.append_id(rb->volumetric_fog->light_map); - uniforms.push_back(u); - } - - rb->volumetric_fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); - } - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - bool any_uses_time = false; - - for (int i = 0; i < (int)p_fog_volumes.size(); i++) { - FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]); - ERR_FAIL_COND(!fog_volume_instance); - RID fog_volume = fog_volume_instance->volume; - - RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume); - - FogMaterialData *material = nullptr; - - if (fog_material.is_valid()) { - material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); - if (!material || !material->shader_data->valid) { - material = nullptr; - } - } - - if (!material) { - fog_material = volumetric_fog.default_material; - material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); - } - - ERR_FAIL_COND(!material); - - FogShaderData *shader_data = material->shader_data; - - ERR_FAIL_COND(!shader_data); - - any_uses_time |= shader_data->uses_time; - - Vector3i min = Vector3i(); - Vector3i max = Vector3i(); - Vector3i kernel_size = Vector3i(); - - Vector3 position = fog_volume_instance->transform.get_origin(); - RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); - Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_extents(fog_volume); - - if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) { - // Local fog volume. - Vector3i points[8]; - points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); - - min = Vector3i(int32_t(rb->volumetric_fog->width) - 1, int32_t(rb->volumetric_fog->height) - 1, int32_t(rb->volumetric_fog->depth) - 1); - max = Vector3i(1, 1, 1); - - for (int j = 0; j < 8; j++) { - min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z)); - max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z)); - } - - kernel_size = max - min; - } else { - // Volume type global runs on all cells - extents = Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth); - min = Vector3i(0, 0, 0); - kernel_size = Vector3i(int32_t(rb->volumetric_fog->width), int32_t(rb->volumetric_fog->height), int32_t(rb->volumetric_fog->depth)); - } - - if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) { - continue; - } - - volumetric_fog.push_constant.position[0] = position.x; - volumetric_fog.push_constant.position[1] = position.y; - volumetric_fog.push_constant.position[2] = position.z; - volumetric_fog.push_constant.extents[0] = extents.x; - volumetric_fog.push_constant.extents[1] = extents.y; - volumetric_fog.push_constant.extents[2] = extents.z; - volumetric_fog.push_constant.corner[0] = min.x; - volumetric_fog.push_constant.corner[1] = min.y; - volumetric_fog.push_constant.corner[2] = min.z; - volumetric_fog.push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume)); - RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), volumetric_fog.push_constant.transform); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &volumetric_fog.push_constant, sizeof(VolumetricFogShader::FogPushConstant)); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE); - if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set. - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL); - } - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z); - } - if (any_uses_time || env->volumetric_fog_temporal_reprojection) { - RenderingServerDefault::redraw_request(); - } - - RD::get_singleton()->draw_command_end_label(); - - RD::get_singleton()->compute_list_end(); - } - - if (rb->volumetric_fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set_density)) { - //re create uniform set if needed - Vector<RD::Uniform> uniforms; - Vector<RD::Uniform> copy_uniforms; - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); - if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); - } else { - u.append_id(shadow_atlas->depth); - } - - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; - if (directional_shadow.depth.is_valid()) { - u.append_id(directional_shadow.depth); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); - } - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 3; - u.append_id(get_omni_light_buffer()); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 4; - u.append_id(get_spot_light_buffer()); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 5; - u.append_id(get_directional_light_buffer()); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 6; - u.append_id(rb->cluster_builder->get_cluster_buffer()); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 7; - u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 8; - u.append_id(rb->volumetric_fog->light_density_map); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 9; - u.append_id(rb->volumetric_fog->fog_map); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 9; - u.append_id(rb->volumetric_fog->prev_light_density_map); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 10; - u.append_id(shadow_sampler); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 11; - u.append_id(render_buffers_get_voxel_gi_buffer(p_render_buffers)); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 12; - for (int i = 0; i < RendererRD::GI::MAX_VOXEL_GI_INSTANCES; i++) { - u.append_id(rb->rbgi.voxel_gi_textures[i]); - } - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 13; - u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 14; - u.append_id(volumetric_fog.params_ubo); - uniforms.push_back(u); - copy_uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 15; - u.append_id(rb->volumetric_fog->prev_light_density_map); - uniforms.push_back(u); - } - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 16; - u.append_id(rb->volumetric_fog->density_map); - uniforms.push_back(u); - } - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 17; - u.append_id(rb->volumetric_fog->light_map); - uniforms.push_back(u); - } - - { - RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -#else - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -#endif - u.binding = 18; - u.append_id(rb->volumetric_fog->emissive_map); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 19; - RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); - RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID(); - u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture); - uniforms.push_back(u); - } - - rb->volumetric_fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0); - - rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); - - RID aux7 = uniforms.write[7].get_id(0); - RID aux8 = uniforms.write[8].get_id(0); - - uniforms.write[7].set_id(0, aux8); - uniforms.write[8].set_id(0, aux7); - - rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); - - uniforms.remove_at(8); - uniforms.write[7].set_id(0, aux7); - rb->volumetric_fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); - } - - bool using_sdfgi = env->volumetric_fog_gi_inject > 0.0001 && env->sdfgi_enabled && (rb->sdfgi != nullptr); - - if (using_sdfgi) { - if (rb->volumetric_fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) { - Vector<RD::Uniform> uniforms; - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.append_id(gi.sdfgi_ubo); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; - u.append_id(rb->sdfgi->ambient_texture); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; - u.append_id(rb->sdfgi->occlusion_texture); - uniforms.push_back(u); - } - - rb->volumetric_fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1); - } - } - - rb->volumetric_fog->length = env->volumetric_fog_length; - rb->volumetric_fog->spread = env->volumetric_fog_detail_spread; - - VolumetricFogShader::ParamsUBO params; - - Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents(); - Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents(); - float z_near = p_cam_projection.get_z_near(); - float z_far = p_cam_projection.get_z_far(); - float fog_end = env->volumetric_fog_length; - - Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near)); - Vector2 fog_near_size; - if (p_cam_projection.is_orthogonal()) { - fog_near_size = fog_far_size; - } else { - fog_near_size = Vector2(); - } - - params.fog_frustum_size_begin[0] = fog_near_size.x; - params.fog_frustum_size_begin[1] = fog_near_size.y; - - params.fog_frustum_size_end[0] = fog_far_size.x; - params.fog_frustum_size_end[1] = fog_far_size.y; - - params.ambient_inject = env->volumetric_fog_ambient_inject * env->ambient_light_energy; - params.z_far = z_far; - - params.fog_frustum_end = fog_end; - - Color ambient_color = env->ambient_light.srgb_to_linear(); - params.ambient_color[0] = ambient_color.r; - params.ambient_color[1] = ambient_color.g; - params.ambient_color[2] = ambient_color.b; - params.sky_contribution = env->ambient_sky_contribution; - - params.fog_volume_size[0] = rb->volumetric_fog->width; - params.fog_volume_size[1] = rb->volumetric_fog->height; - params.fog_volume_size[2] = rb->volumetric_fog->depth; - - params.directional_light_count = p_directional_light_count; - - Color emission = env->volumetric_fog_emission.srgb_to_linear(); - params.base_emission[0] = emission.r * env->volumetric_fog_emission_energy; - params.base_emission[1] = emission.g * env->volumetric_fog_emission_energy; - params.base_emission[2] = emission.b * env->volumetric_fog_emission_energy; - params.base_density = env->volumetric_fog_density; - - Color base_scattering = env->volumetric_fog_scattering.srgb_to_linear(); - params.base_scattering[0] = base_scattering.r; - params.base_scattering[1] = base_scattering.g; - params.base_scattering[2] = base_scattering.b; - params.phase_g = env->volumetric_fog_anisotropy; - - params.detail_spread = env->volumetric_fog_detail_spread; - params.gi_inject = env->volumetric_fog_gi_inject; - - params.cam_rotation[0] = p_cam_transform.basis[0][0]; - params.cam_rotation[1] = p_cam_transform.basis[1][0]; - params.cam_rotation[2] = p_cam_transform.basis[2][0]; - params.cam_rotation[3] = 0; - params.cam_rotation[4] = p_cam_transform.basis[0][1]; - params.cam_rotation[5] = p_cam_transform.basis[1][1]; - params.cam_rotation[6] = p_cam_transform.basis[2][1]; - params.cam_rotation[7] = 0; - params.cam_rotation[8] = p_cam_transform.basis[0][2]; - params.cam_rotation[9] = p_cam_transform.basis[1][2]; - params.cam_rotation[10] = p_cam_transform.basis[2][2]; - params.cam_rotation[11] = 0; - params.filter_axis = 0; - params.max_voxel_gi_instances = env->volumetric_fog_gi_inject > 0.001 ? p_voxel_gi_count : 0; - params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; - - Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; - RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); - - params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection; - params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount; - - { - uint32_t cluster_size = rb->cluster_builder->get_cluster_size(); - params.cluster_shift = get_shift_from_power_of_2(cluster_size); - - uint32_t cluster_screen_width = (rb->width - 1) / cluster_size + 1; - uint32_t cluster_screen_height = (rb->height - 1) / cluster_size + 1; - params.max_cluster_element_count_div_32 = max_cluster_elements / 32; - params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32); - params.cluster_width = cluster_screen_width; - - params.screen_size[0] = rb->width; - params.screen_size[1] = rb->height; - } - - Basis sky_transform = env->sky_orientation; - sky_transform = sky_transform.inverse() * p_cam_transform.basis; - RendererRD::MaterialStorage::store_transform_3x3(sky_transform, params.radiance_inverse_xform); - - RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog"); - - RENDER_TIMESTAMP("Render Fog"); - RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set_density, 0); - - if (using_sdfgi) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1); + rb->volumetric_fog = memnew(RendererRD::Fog::VolumetricFog(Vector3i(target_width, target_height, volumetric_fog_depth), sky.sky_shader.default_shader_rd)); } - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - // Copy fog to history buffer - if (env->volumetric_fog_temporal_reprojection) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->copy_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth); - RD::get_singleton()->compute_list_add_barrier(compute_list); - } - RD::get_singleton()->draw_command_end_label(); - - if (volumetric_fog_filter_active) { - RD::get_singleton()->draw_command_begin_label("Filter Fog"); - - RENDER_TIMESTAMP("Filter Fog"); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth); - - RD::get_singleton()->compute_list_end(); - //need restart for buffer update - params.filter_axis = 1; - RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms); + if (rb->volumetric_fog) { + RendererRD::Fog::VolumetricFogSettings settings; + settings.rb_size = Vector2i(rb->width, rb->height); + settings.time = time; + settings.is_using_radiance_cubemap_array = is_using_radiance_cubemap_array(); + settings.max_cluster_elements = max_cluster_elements; + settings.volumetric_fog_filter_active = volumetric_fog_filter_active; + + settings.shadow_sampler = shadow_sampler; + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); + settings.shadow_atlas_depth = shadow_atlas ? shadow_atlas->depth : RID(); + settings.voxel_gl_buffer = render_buffers_get_voxel_gi_buffer(p_render_buffers); + settings.omni_light_buffer = get_omni_light_buffer(); + settings.spot_light_buffer = get_spot_light_buffer(); + settings.directional_shadow_depth = directional_shadow.depth; + settings.directional_light_buffer = get_directional_light_buffer(); - compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set2, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth); + settings.vfog = rb->volumetric_fog; + settings.cluster_builder = rb->cluster_builder; + settings.rbgi = &rb->rbgi; + settings.sdfgi = rb->sdfgi; + settings.env = env; + settings.sky = &sky; + settings.gi = &gi; - RD::get_singleton()->compute_list_add_barrier(compute_list); - RD::get_singleton()->draw_command_end_label(); + RendererRD::Fog::get_singleton()->volumetric_fog_update(settings, p_cam_projection, p_cam_transform, p_prev_cam_inv_transform, p_shadow_atlas, p_directional_light_count, p_use_directional_shadows, p_positional_light_count, p_voxel_gi_count, p_fog_volumes); } - - RENDER_TIMESTAMP("Integrate Fog"); - RD::get_singleton()->draw_command_begin_label("Integrate Fog"); - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, 1); - - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER); - - RENDER_TIMESTAMP("< Volumetric Fog"); - RD::get_singleton()->draw_command_end_label(); - RD::get_singleton()->draw_command_end_label(); } bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) { @@ -4929,7 +3778,7 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo } } -void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID *p_normal_roughness_views, RID p_voxel_gi_buffer) { +void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices) { // Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); @@ -5004,7 +3853,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool //start GI if (render_gi) { - gi.process_gi(p_render_data->render_buffers, p_normal_roughness_views, p_voxel_gi_buffer, p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->view_eye_offset, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this); + gi.process_gi(p_render_data->render_buffers, p_normal_roughness_slices, p_voxel_gi_buffer, p_vrs_slices, p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->view_eye_offset, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this); } //Do shadow rendering (in parallel with GI) @@ -5016,7 +3865,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //use a later barrier } - if (p_render_data->render_buffers.is_valid()) { + if (p_render_data->render_buffers.is_valid() && ss_effects) { if (p_use_ssao || p_use_ssil) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); ERR_FAIL_COND(!rb); @@ -5041,17 +3890,17 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool invalidate_uniform_set = true; } - RendererCompositorRD::singleton->get_effects()->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection); + ss_effects->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection); } if (p_use_ssao) { - // TODO make these proper stereo and thus use p_normal_roughness_views correctly - _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_views[0], p_render_data->cam_projection); + // TODO make these proper stereo + _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection); } if (p_use_ssil) { - // TODO make these proper stereo and thus use p_normal_roughness_views correctly - _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_views[0], p_render_data->cam_projection, p_render_data->cam_transform); + // TODO make these proper stereo + _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection, p_render_data->cam_transform); } } @@ -5240,6 +4089,11 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData render_data.cluster_max_elements = current_cluster_builder->get_max_cluster_elements(); } + if (rb != nullptr && rb->vrs_fb.is_valid()) { + // vrs_fb will only be valid if vrs is enabled + vrs->update_vrs_texture(rb->vrs_fb, rb->render_target); + } + _render_scene(&render_data, clear_color); if (p_render_buffers.is_valid()) { @@ -5309,7 +4163,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, bool flip_y = false; - CameraMatrix light_projection; + Projection light_projection; Transform3D light_transform; if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) { @@ -5451,7 +4305,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true); //restore transform so it can be properly used - light_instance_set_shadow_transform(p_light, CameraMatrix(), light_instance->transform, zfar, 0, 0, 0); + light_instance_set_shadow_transform(p_light, Projection(), light_instance->transform, zfar, 0, 0, 0); } } else { @@ -5460,7 +4314,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, } } -void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { _render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region); } @@ -5469,7 +4323,7 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, ERR_FAIL_COND(!particles_storage->particles_collision_is_heightfield(p_collider)); Vector3 extents = particles_storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale(); - CameraMatrix cm; + Projection cm; cm.set_orthogonal(-extents.x, extents.x, -extents.z, extents.z, 0, extents.y * 2.0); Vector3 cam_pos = p_transform.origin; @@ -5494,7 +4348,8 @@ bool RendererSceneRenderRD::free(RID p_rid) { rb->sdfgi = nullptr; } if (rb->volumetric_fog) { - _volumetric_fog_erase(rb); + memdelete(rb->volumetric_fog); + rb->volumetric_fog = nullptr; } if (rb->cluster_builder) { memdelete(rb->cluster_builder); @@ -5569,8 +4424,8 @@ bool RendererSceneRenderRD::free(RID p_rid) { } else if (shadow_atlas_owner.owns(p_rid)) { shadow_atlas_set_size(p_rid, 0); shadow_atlas_owner.free(p_rid); - } else if (fog_volume_instance_owner.owns(p_rid)) { - fog_volume_instance_owner.free(p_rid); + } else if (RendererRD::Fog::get_singleton()->owns_fog_volume_instance(p_rid)) { + RendererRD::Fog::get_singleton()->fog_instance_free(p_rid); } else { return false; } @@ -5736,6 +4591,10 @@ int RendererSceneRenderRD::get_max_directional_lights() const { return cluster.max_directional_lights; } +bool RendererSceneRenderRD::is_vrs_supported() const { + return RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS); +} + bool RendererSceneRenderRD::is_dynamic_gi_supported() const { // usable by default (unless low end = true) return true; @@ -5760,8 +4619,6 @@ RendererSceneRenderRD::RendererSceneRenderRD() { } void RendererSceneRenderRD::init() { - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - max_cluster_elements = get_max_elements(); directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size"); @@ -5812,124 +4669,7 @@ void RendererSceneRenderRD::init() { } if (is_volumetric_supported()) { - { - // Initialize local fog shader - Vector<String> volumetric_fog_modes; - volumetric_fog_modes.push_back(""); - volumetric_fog.shader.initialize(volumetric_fog_modes); - - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs); - volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO)); - } - - { - ShaderCompiler::DefaultIdentifierActions actions; - - actions.renames["TIME"] = "scene_params.time"; - actions.renames["PI"] = _MKSTR(Math_PI); - actions.renames["TAU"] = _MKSTR(Math_TAU); - actions.renames["E"] = _MKSTR(Math_E); - actions.renames["WORLD_POSITION"] = "world.xyz"; - actions.renames["OBJECT_POSITION"] = "params.position"; - actions.renames["UVW"] = "uvw"; - actions.renames["EXTENTS"] = "params.extents"; - actions.renames["ALBEDO"] = "albedo"; - actions.renames["DENSITY"] = "density"; - actions.renames["EMISSION"] = "emission"; - actions.renames["SDF"] = "sdf"; - - actions.usage_defines["SDF"] = "#define SDF_USED\n"; - actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n"; - actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n"; - actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n"; - - actions.sampler_array_name = "material_samplers"; - actions.base_texture_binding_index = 1; - actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL; - actions.base_uniform_string = "material."; - - actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; - actions.default_repeat = ShaderLanguage::REPEAT_DISABLE; - actions.global_buffer_array_variable = "global_variables.data"; - - volumetric_fog.compiler.initialize(actions); - } - - { - // default material and shader for fog shader - volumetric_fog.default_shader = material_storage->shader_allocate(); - material_storage->shader_initialize(volumetric_fog.default_shader); - material_storage->shader_set_code(volumetric_fog.default_shader, R"( -// Default fog shader. - -shader_type fog; - -void fog() { - DENSITY = 1.0; - ALBEDO = vec3(1.0); -} -)"); - volumetric_fog.default_material = material_storage->material_allocate(); - material_storage->material_initialize(volumetric_fog.default_material); - material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader); - - FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG)); - volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0); - - Vector<RD::Uniform> uniforms; - - { - Vector<RID> ids; - ids.resize(12); - RID *ids_ptr = ids.ptrw(); - ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - - RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 2; - u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer()); - uniforms.push_back(u); - } - - volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE); - } - { - String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n"; - defines += "\n#define MAX_SKY_LOD " + itos(get_roughness_layers() - 1) + ".0\n"; - if (is_using_radiance_cubemap_array()) { - defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; - } - Vector<String> volumetric_fog_modes; - volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n"); - volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n"); - volumetric_fog_modes.push_back("\n#define MODE_FILTER\n"); - volumetric_fog_modes.push_back("\n#define MODE_FOG\n"); - volumetric_fog_modes.push_back("\n#define MODE_COPY\n"); - - volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines); - volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create(); - for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) { - volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i)); - } - volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO)); - } + RendererRD::Fog::get_singleton()->init_fog_shader(cluster.max_directional_lights, get_roughness_layers(), is_using_radiance_cubemap_array()); } { @@ -5960,8 +4700,8 @@ void fog() { directional_soft_shadow_kernel = memnew_arr(float, 128); penumbra_shadow_kernel = memnew_arr(float, 128); soft_shadow_kernel = memnew_arr(float, 128); - shadows_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/shadows/soft_shadow_quality")))); - directional_shadow_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_quality")))); + positional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/positional_shadow/soft_shadow_filter_quality")))); + directional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_filter_quality")))); environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth")); environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter")); @@ -5975,11 +4715,13 @@ void fog() { bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage)); copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage)); tone_mapper = memnew(RendererRD::ToneMapper); + vrs = memnew(RendererRD::VRS); + if (can_use_storage) { + ss_effects = memnew(RendererRD::SSEffects); + } } RendererSceneRenderRD::~RendererSceneRenderRD() { - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - if (bokeh_dof) { memdelete(bokeh_dof); } @@ -5989,6 +4731,12 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { if (tone_mapper) { memdelete(tone_mapper); } + if (vrs) { + memdelete(vrs); + } + if (ss_effects) { + memdelete(ss_effects); + } for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) { RD::get_singleton()->free(E.value.cubemap); @@ -6003,11 +4751,7 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { } if (is_volumetric_supported()) { - volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version); - RD::get_singleton()->free(volumetric_fog.volume_ubo); - RD::get_singleton()->free(volumetric_fog.params_ubo); - material_storage->shader_free(volumetric_fog.default_shader); - material_storage->material_free(volumetric_fog.default_material); + RendererRD::Fog::get_singleton()->free_fog_shader(); } memdelete_arr(directional_penumbra_shadow_kernel); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index e8296882c9..cd56b8efb3 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_RENDER_RD_H -#define RENDERING_SERVER_SCENE_RENDER_RD_H +#ifndef RENDERER_SCENE_RENDER_RD_H +#define RENDERER_SCENE_RENDER_RD_H #include "core/templates/local_vector.h" #include "core/templates/rid_owner.h" @@ -37,12 +37,13 @@ #include "servers/rendering/renderer_rd/cluster_builder_rd.h" #include "servers/rendering/renderer_rd/effects/bokeh_dof.h" #include "servers/rendering/renderer_rd/effects/copy_effects.h" +#include "servers/rendering/renderer_rd/effects/ss_effects.h" #include "servers/rendering/renderer_rd/effects/tone_mapper.h" +#include "servers/rendering/renderer_rd/effects/vrs.h" +#include "servers/rendering/renderer_rd/environment/fog.h" #include "servers/rendering/renderer_rd/environment/gi.h" +#include "servers/rendering/renderer_rd/environment/sky.h" #include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" -#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h" -#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h" #include "servers/rendering/renderer_scene.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" @@ -51,19 +52,19 @@ struct RenderDataRD { RID render_buffers; Transform3D cam_transform; - CameraMatrix cam_projection; + Projection cam_projection; Vector2 taa_jitter; bool cam_orthogonal = false; // For stereo rendering uint32_t view_count = 1; Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS]; - CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; + Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; Transform3D prev_cam_transform; - CameraMatrix prev_cam_projection; + Projection prev_cam_projection; Vector2 prev_taa_jitter; - CameraMatrix prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; + Projection prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; float z_near = 0.0; float z_far = 0.0; @@ -97,18 +98,19 @@ struct RenderDataRD { }; class RendererSceneRenderRD : public RendererSceneRender { - friend RendererSceneSkyRD; + friend RendererRD::SkyRD; friend RendererRD::GI; protected: RendererRD::BokehDOF *bokeh_dof = nullptr; RendererRD::CopyEffects *copy_effects = nullptr; RendererRD::ToneMapper *tone_mapper = nullptr; + RendererRD::VRS *vrs = nullptr; double time = 0.0; double time_step = 0.0; struct RenderBufferData { - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) = 0; + virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) = 0; virtual ~RenderBufferData() {} }; virtual RenderBufferData *_create_render_buffer_data() = 0; @@ -120,16 +122,16 @@ protected: virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0; virtual void _render_shadow_begin() = 0; - virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0; + virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0; virtual void _render_shadow_process() = 0; virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0; - virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0; - virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0; + virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0; - void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); + void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); void _debug_draw_cluster(RID p_render_buffers); RenderBufferData *render_buffers_get_data(RID p_render_buffers); @@ -138,10 +140,11 @@ protected: virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0; virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) = 0; - void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection); - void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive); - void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera); - void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform); + void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection); + void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive); + void _process_sss(RID p_render_buffers, const Projection &p_camera); + void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform); + void _copy_framebuffer_to_ssil(RID p_render_buffers); void _process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far); @@ -149,7 +152,7 @@ protected: void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi); - void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID *p_normal_roughness_views, RID p_voxel_gi_buffer); + void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices); void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data); void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data); @@ -161,8 +164,9 @@ protected: PagedArrayPool<GeometryInstance *> cull_argument_pool; PagedArray<GeometryInstance *> cull_argument; //need this to exist + RendererRD::SSEffects *ss_effects = nullptr; RendererRD::GI gi; - RendererSceneSkyRD sky; + RendererRD::SkyRD sky; RendererSceneEnvironmentRD *get_environment(RID p_environment) { if (p_environment.is_valid()) { @@ -207,7 +211,7 @@ private: struct Reflection { RID owner; - RendererSceneSkyRD::ReflectionData data; + RendererRD::SkyRD::ReflectionData data; RID fbs[6]; }; @@ -360,7 +364,7 @@ private: struct LightInstance { struct ShadowTransform { - CameraMatrix camera; + Projection camera; Transform3D transform; float farplane; float split; @@ -402,21 +406,10 @@ private: mutable RID_Owner<LightInstance> light_instance_owner; - /* FOG VOLUMES */ - - struct FogVolumeInstance { - RID volume; - Transform3D transform; - bool active = false; - }; - - mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner; - /* ENVIRONMENT */ RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM; bool ssao_half_size = false; - bool ssao_using_half_size = false; float ssao_adaptive_target = 0.5; int ssao_blur_passes = 2; float ssao_fadeout_from = 50.0; @@ -467,8 +460,6 @@ private: ClusterBuilderSharedDataRD cluster_builder_shared; ClusterBuilderRD *current_cluster_builder = nullptr; - struct VolumetricFog; - struct RenderBuffers { RenderBufferData *data = nullptr; int internal_width = 0; @@ -492,6 +483,8 @@ private: RID depth_texture; //main depth texture RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!! RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling) + RID vrs_texture; // texture for vrs. + RID vrs_fb; // framebuffer to write to our vrs texture // Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images) struct View { @@ -502,8 +495,8 @@ private: Vector<View> views; RendererRD::GI::SDFGI *sdfgi = nullptr; - VolumetricFog *volumetric_fog = nullptr; RendererRD::GI::RenderBuffersGI rbgi; + RendererRD::Fog::VolumetricFog *volumetric_fog = nullptr; ClusterBuilderRD *cluster_builder = nullptr; @@ -557,47 +550,14 @@ private: RID downsample_uniform_set; - RID last_frame; - Vector<RID> last_frame_slices; - - CameraMatrix last_frame_projection; + Projection last_frame_projection; Transform3D last_frame_transform; - struct SSAO { - RID ao_deinterleaved; - Vector<RID> ao_deinterleaved_slices; - RID ao_pong; - Vector<RID> ao_pong_slices; - RID ao_final; - RID importance_map[2]; - RID depth_texture_view; - - RID gather_uniform_set; - RID importance_map_uniform_set; - } ssao; - - struct SSIL { - RID ssil_final; - RID deinterleaved; - Vector<RID> deinterleaved_slices; - RID pong; - Vector<RID> pong_slices; - RID edges; - Vector<RID> edges_slices; - RID importance_map[2]; - RID depth_texture_view; - - RID gather_uniform_set; - RID importance_map_uniform_set; - RID projection_uniform_set; - } ssil; + RendererRD::SSEffects::SSAORenderBuffers ssao; + RendererRD::SSEffects::SSILRenderBuffers ssil; } ss_effects; - struct SSR { - RID normal_scaled; - RID depth_scaled; - RID blur_radius[2]; - } ssr; + RendererRD::SSEffects::SSRRenderBuffers ssr; struct TAA { RID history; @@ -776,203 +736,6 @@ private: bool depth_prepass_used; // this does not seem used anywhere... } render_state; - struct VolumetricFog { - enum { - MAX_TEMPORAL_FRAMES = 16 - }; - - uint32_t width = 0; - uint32_t height = 0; - uint32_t depth = 0; - - float length; - float spread; - - RID light_density_map; - RID prev_light_density_map; - RID fog_map; - RID density_map; - RID light_map; - RID emissive_map; - - RID fog_uniform_set; - RID copy_uniform_set; - RID process_uniform_set_density; - RID process_uniform_set; - RID process_uniform_set2; - RID sdfgi_uniform_set; - RID sky_uniform_set; - - int last_shadow_filter = -1; - }; - - struct VolumetricFogShader { - enum FogSet { - FOG_SET_BASE, - FOG_SET_UNIFORMS, - FOG_SET_MATERIAL, - FOG_SET_MAX, - }; - - struct FogPushConstant { - float position[3]; - float pad; - - float extents[3]; - float pad2; - - int32_t corner[3]; - uint32_t shape; - - float transform[16]; - }; - - struct VolumeUBO { - float fog_frustum_size_begin[2]; - float fog_frustum_size_end[2]; - - float fog_frustum_end; - float z_near; - float z_far; - float time; - - int32_t fog_volume_size[3]; - uint32_t directional_light_count; - - uint32_t use_temporal_reprojection; - uint32_t temporal_frame; - float detail_spread; - float temporal_blend; - - float to_prev_view[16]; - float transform[16]; - }; - - ShaderCompiler compiler; - VolumetricFogShaderRD shader; - FogPushConstant push_constant; - RID volume_ubo; - - RID default_shader; - RID default_material; - RID default_shader_rd; - - RID base_uniform_set; - - RID params_ubo; - - enum { - VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY, - VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI, - VOLUMETRIC_FOG_PROCESS_SHADER_FILTER, - VOLUMETRIC_FOG_PROCESS_SHADER_FOG, - VOLUMETRIC_FOG_PROCESS_SHADER_COPY, - VOLUMETRIC_FOG_PROCESS_SHADER_MAX, - }; - - struct ParamsUBO { - float fog_frustum_size_begin[2]; - float fog_frustum_size_end[2]; - - float fog_frustum_end; - float ambient_inject; - float z_far; - uint32_t filter_axis; - - float ambient_color[3]; - float sky_contribution; - - int32_t fog_volume_size[3]; - uint32_t directional_light_count; - - float base_emission[3]; - float base_density; - - float base_scattering[3]; - float phase_g; - - float detail_spread; - float gi_inject; - uint32_t max_voxel_gi_instances; - uint32_t cluster_type_size; - - float screen_size[2]; - uint32_t cluster_shift; - uint32_t cluster_width; - - uint32_t max_cluster_element_count_div_32; - uint32_t use_temporal_reprojection; - uint32_t temporal_frame; - float temporal_blend; - - float cam_rotation[12]; - float to_prev_view[16]; - float radiance_inverse_xform[12]; - }; - - VolumetricFogProcessShaderRD process_shader; - - RID process_shader_version; - RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX]; - - } volumetric_fog; - - uint32_t volumetric_fog_depth = 128; - uint32_t volumetric_fog_size = 128; - bool volumetric_fog_filter_active = true; - - Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform); - void _volumetric_fog_erase(RenderBuffers *rb); - void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); - - struct FogShaderData : public RendererRD::ShaderData { - bool valid = false; - RID version; - - RID pipeline; - HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; - Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; - - Vector<uint32_t> ubo_offsets; - uint32_t ubo_size = 0; - - String path; - String code; - HashMap<StringName, HashMap<int, RID>> default_texture_params; - - bool uses_time = false; - - virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; - virtual bool is_animated() const; - virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; - virtual RS::ShaderNativeSourceCode get_native_source_code() const; - - FogShaderData() {} - virtual ~FogShaderData(); - }; - - struct FogMaterialData : public RendererRD::MaterialData { - FogShaderData *shader_data = nullptr; - RID uniform_set; - bool uniform_set_updated; - - virtual void set_render_priority(int p_priority) {} - virtual void set_next_pass(RID p_pass) {} - virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~FogMaterialData(); - }; - - RendererRD::ShaderData *_create_fog_shader_func(); - static RendererRD::ShaderData *_create_fog_shader_funcs(); - - RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader); - static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader); - RID shadow_sampler; uint64_t scene_pass = 0; @@ -989,6 +752,14 @@ private: void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr); + /* Volumetric Fog */ + + uint32_t volumetric_fog_size = 128; + uint32_t volumetric_fog_depth = 128; + bool volumetric_fog_filter_active = true; + + void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); + public: virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) = 0; virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0; @@ -1146,7 +917,7 @@ public: virtual RID light_instance_create(RID p_light) override; virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override; virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override; - virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override; + virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override; virtual void light_instance_mark_visible(RID p_light_instance) override; _FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) { @@ -1195,7 +966,7 @@ public: return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size)); } - _FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) { + _FORCE_INLINE_ Projection light_instance_get_shadow_camera(RID p_light_instance, int p_index) { LightInstance *li = light_instance_owner.get_or_null(p_light_instance); return li->shadow_transform[p_index].camera; } @@ -1434,7 +1205,7 @@ public: virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; - virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override; @@ -1454,8 +1225,8 @@ public: RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const; virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override; - virtual void shadows_quality_set(RS::ShadowQuality p_quality) override; - virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) override; + virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; + virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; virtual void decals_set_filter(RS::DecalFilter p_filter) override; virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override; @@ -1503,6 +1274,7 @@ public: virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override; + virtual bool is_vrs_supported() const; virtual bool is_dynamic_gi_supported() const; virtual bool is_clustered_enabled() const; virtual bool is_volumetric_supported() const; @@ -1514,4 +1286,4 @@ public: ~RendererSceneRenderRD(); }; -#endif // RASTERIZER_SCENE_RD_H +#endif // RENDERER_SCENE_RENDER_RD_H diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index 04e05380f1..c9b6d09d4c 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -177,7 +177,7 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c for (const KeyValue<StringName, CharString> &E : p_version->code_sections) { builder.append(String("#define ") + String(E.key) + "_CODE_USED\n"); } -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) builder.append("#define MOLTENVK_USED\n"); #endif } break; @@ -476,7 +476,9 @@ void ShaderRD::_compile_version(Version *p_version) { #if 1 - RendererThreadPool::singleton->thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &ShaderRD::_compile_variant, p_version, variant_defines.size(), -1, true, SNAME("ShaderCompilation")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + #else for (int i = 0; i < variant_defines.size(); i++) { _compile_variant(i, p_version); diff --git a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl index 9787c9879d..1c17eabb56 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl @@ -88,7 +88,7 @@ layout(set = 0, binding = 0) uniform sampler2DArray source_color; layout(set = 1, binding = 0) uniform sampler2DArray source_depth; layout(location = 1) out float depth; #endif /* MODE_TWO_SOURCES */ -#else +#else /* MULTIVIEW */ layout(set = 0, binding = 0) uniform sampler2D source_color; #ifdef MODE_TWO_SOURCES layout(set = 1, binding = 0) uniform sampler2D source_color2; @@ -139,7 +139,7 @@ void main() { //uv.y = 1.0 - uv.y; uv = 1.0 - uv; } -#endif +#endif /* MODE_PANORAMA_TO_DP */ #ifdef MULTIVIEW vec4 color = textureLod(source_color, uv, 0.0); @@ -148,12 +148,13 @@ void main() { depth = textureLod(source_depth, uv, 0.0).r; #endif /* MODE_TWO_SOURCES */ -#else +#else /* MULTIVIEW */ vec4 color = textureLod(source_color, uv, 0.0); #ifdef MODE_TWO_SOURCES color += textureLod(source_color2, uv, 0.0); #endif /* MODE_TWO_SOURCES */ #endif /* MULTIVIEW */ + if (params.force_luminance) { color.rgb = vec3(max(max(color.r, color.g), color.b)); } @@ -163,5 +164,6 @@ void main() { if (params.srgb) { color.rgb = linear_to_srgb(color.rgb); } + frag_color = color; } diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl index a416891ff2..d85ab3af2e 100644 --- a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl @@ -32,12 +32,17 @@ layout(push_constant, std430) uniform Params { bool use_half_res; uint metallic_mask; - mat4 projection; + uint view_index; + uint pad1; + uint pad2; + uint pad3; } params; +#include "screen_space_reflection_inc.glsl" + vec2 view_to_screen(vec3 view_pos, out float w) { - vec4 projected = params.projection * vec4(view_pos, 1.0); + vec4 projected = scene_data.projection[params.view_index] * vec4(view_pos, 1.0); projected.xyz /= projected.w; projected.xy = projected.xy * 0.5 + 0.5; w = projected.w; @@ -46,24 +51,16 @@ vec2 view_to_screen(vec3 view_pos, out float w) { #define M_PI 3.14159265359 -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); - } -} - void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing return; } vec2 pixel_size = 1.0 / vec2(params.screen_size); - vec2 uv = vec2(ssC) * pixel_size; + vec2 uv = vec2(ssC.xy) * pixel_size; uv += pixel_size * 0.5; @@ -77,7 +74,12 @@ void main() { normal = normalize(normal); normal.y = -normal.y; //because this code reads flipped - vec3 view_dir = normalize(vertex); + vec3 view_dir; + if (sc_multiview) { + view_dir = normalize(vertex + scene_data.eye_offset[params.view_index].xyz); + } else { + view_dir = normalize(vertex); + } vec3 ray_dir = normalize(reflect(view_dir, normal)); if (dot(ray_dir, normal) < 0.001) { @@ -154,6 +156,11 @@ void main() { // convert to linear depth depth = imageLoad(source_depth, ivec2(pos - 0.5)).r; + if (sc_multiview) { + depth = depth * 2.0 - 1.0; + depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near)); + depth = -depth; + } z_from = z_to; z_to = z / w; @@ -222,13 +229,16 @@ void main() { blur_radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h); } } + + // Isn't this going to be overwritten after our endif? final_color = imageLoad(source_diffuse, ivec2((final_pos - 0.5) * pixel_size)); imageStore(blur_radius_image, ssC, vec4(blur_radius / 255.0)); //stored in r8 -#endif +#endif // MODE_ROUGH final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend); + //change blend by metallic vec4 metallic_mask = unpackUnorm4x8(params.metallic_mask); final_color.a *= dot(metallic_mask, texelFetch(source_metallic, ssC << 1, 0)); diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl index 20e1712496..a63d60e0b2 100644 --- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl @@ -22,7 +22,7 @@ layout(push_constant, std430) uniform Params { bool orthogonal; float edge_tolerance; int increment; - uint pad; + uint view_index; ivec2 screen_size; bool vertical; @@ -30,6 +30,8 @@ layout(push_constant, std430) uniform Params { } params; +#include "screen_space_reflection_inc.glsl" + #define GAUSS_TABLE_SIZE 15 const float gauss_table[GAUSS_TABLE_SIZE + 1] = float[]( @@ -64,14 +66,6 @@ float gauss_weight(float p_val) { #define M_PI 3.14159265359 -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); - } -} - void do_filter(inout vec4 accum, inout float accum_radius, inout float divisor, ivec2 texcoord, ivec2 increment, vec3 p_pos, vec3 normal, float p_limit_radius) { for (int i = 1; i < params.steps; i++) { float d = float(i * params.increment); @@ -110,7 +104,7 @@ void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing return; } @@ -130,13 +124,13 @@ void main() { ivec2 direction = ivec2(params.increment, 0); #endif float depth = imageLoad(source_depth, ssC).r; - vec3 pos = reconstructCSPosition(vec2(ssC) + 0.5, depth); + vec3 pos = reconstructCSPosition(vec2(ssC.xy) + 0.5, depth); vec3 normal = imageLoad(source_normal, ssC).xyz * 2.0 - 1.0; normal = normalize(normal); normal.y = -normal.y; - do_filter(accum, accum_radius, divisor, ssC, direction, pos, normal, radius); - do_filter(accum, accum_radius, divisor, ssC, -direction, pos, normal, radius); + do_filter(accum, accum_radius, divisor, ssC.xy, direction, pos, normal, radius); + do_filter(accum, accum_radius, divisor, ssC.xy, -direction, pos, normal, radius); if (divisor > 0.0) { accum /= divisor; diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl new file mode 100644 index 0000000000..26405ab040 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl @@ -0,0 +1,28 @@ +layout(constant_id = 0) const bool sc_multiview = false; + +layout(set = 4, binding = 0, std140) uniform SceneData { + mat4x4 projection[2]; + mat4x4 inv_projection[2]; + vec4 eye_offset[2]; +} +scene_data; + +vec3 reconstructCSPosition(vec2 screen_pos, float z) { + if (sc_multiview) { + vec4 pos; + pos.xy = (2.0 * vec2(screen_pos) / vec2(params.screen_size)) - 1.0; + pos.z = z * 2.0 - 1.0; + pos.w = 1.0; + + pos = scene_data.inv_projection[params.view_index] * pos; + pos.xyz /= pos.w; + + return pos.xyz; + } else { + if (params.orthogonal) { + return vec3((screen_pos.xy * params.proj_info.xy + params.proj_info.zw), z); + } else { + return vec3((screen_pos.xy * params.proj_info.xy + params.proj_info.zw) * z, z); + } + } +} diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl index 3f537e273a..a7da0812df 100644 --- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl @@ -6,6 +6,11 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; +/* Specialization Constants (Toggles) */ + +layout(constant_id = 0) const bool sc_multiview = false; + +/* inputs */ layout(set = 0, binding = 0) uniform sampler2D source_ssr; layout(set = 1, binding = 0) uniform sampler2D source_depth; layout(set = 1, binding = 1) uniform sampler2D source_normal; @@ -28,7 +33,7 @@ void main() { // Pixel being shaded ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing + if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing return; } //do not filter, SSR will generate arctifacts if this is done @@ -57,13 +62,19 @@ void main() { normal.xyz += nr.xyz * 2.0 - 1.0; normal.w += nr.w; - d = d * 2.0 - 1.0; - if (params.orthogonal) { - d = ((d + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0; + if (sc_multiview) { + // we're doing a full unproject so we need the value as is. + depth += d; } else { - d = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - d * (params.camera_z_far - params.camera_z_near)); + // unproject our Z value so we can use it directly. + d = d * 2.0 - 1.0; + if (params.orthogonal) { + d = ((d + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0; + } else { + d = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - d * (params.camera_z_far - params.camera_z_near)); + } + depth += -d; } - depth += -d; } color /= 4.0; @@ -71,17 +82,22 @@ void main() { normal.xyz = normalize(normal.xyz / 4.0) * 0.5 + 0.5; normal.w /= 4.0; } else { - color = texelFetch(source_ssr, ssC << 1, 0); - depth = texelFetch(source_depth, ssC << 1, 0).r; - normal = texelFetch(source_normal, ssC << 1, 0); - - depth = depth * 2.0 - 1.0; - if (params.orthogonal) { - depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0; - } else { - depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near)); + ivec2 ofs = ssC << 1; + + color = texelFetch(source_ssr, ofs, 0); + depth = texelFetch(source_depth, ofs, 0).r; + normal = texelFetch(source_normal, ofs, 0); + + if (!sc_multiview) { + // unproject our Z value so we can use it directly. + depth = depth * 2.0 - 1.0; + if (params.orthogonal) { + depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0; + } else { + depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near)); + } + depth = -depth; } - depth = -depth; } imageStore(dest_ssr, ssC, color); diff --git a/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl new file mode 100644 index 0000000000..c62144fdaf --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl @@ -0,0 +1,112 @@ +#[vertex] + +#version 450 + +#VERSION_DEFINES + +#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview) +#extension GL_EXT_multiview : enable +#endif + +#ifdef USE_MULTIVIEW +#ifdef has_VK_KHR_multiview +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +// !BAS! This needs to become an input once we implement our fallback! +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#else // USE_MULTIVIEW +// Set to zero, not supported in non stereo +#define ViewIndex 0 +#endif //USE_MULTIVIEW + +#ifdef USE_MULTIVIEW +layout(location = 0) out vec3 uv_interp; +#else // USE_MULTIVIEW +layout(location = 0) out vec2 uv_interp; +#endif //USE_MULTIVIEW + +void main() { + vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); + +#ifdef USE_MULTIVIEW + uv_interp = vec3(base_arr[gl_VertexIndex], ViewIndex); + + gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0); +#else + uv_interp = base_arr[gl_VertexIndex]; + + gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); +#endif +} + +#[fragment] + +#version 450 + +#VERSION_DEFINES + +#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview) +#extension GL_EXT_multiview : enable +#endif + +#ifdef USE_MULTIVIEW +#ifdef has_VK_KHR_multiview +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +// !BAS! This needs to become an input once we implement our fallback! +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#else // USE_MULTIVIEW +// Set to zero, not supported in non stereo +#define ViewIndex 0 +#endif //USE_MULTIVIEW + +#ifdef USE_MULTIVIEW +layout(location = 0) in vec3 uv_interp; +#else // USE_MULTIVIEW +layout(location = 0) in vec2 uv_interp; +#endif //USE_MULTIVIEW + +#ifdef USE_MULTIVIEW +layout(set = 0, binding = 0) uniform sampler2DArray specular; +#else // USE_MULTIVIEW +layout(set = 0, binding = 0) uniform sampler2D specular; +#endif //USE_MULTIVIEW + +#ifdef MODE_SSR + +#ifdef USE_MULTIVIEW +layout(set = 1, binding = 0) uniform sampler2DArray ssr; +#else // USE_MULTIVIEW +layout(set = 1, binding = 0) uniform sampler2D ssr; +#endif //USE_MULTIVIEW + +#endif + +#ifdef MODE_MERGE + +#ifdef USE_MULTIVIEW +layout(set = 2, binding = 0) uniform sampler2DArray diffuse; +#else // USE_MULTIVIEW +layout(set = 2, binding = 0) uniform sampler2D diffuse; +#endif //USE_MULTIVIEW + +#endif + +layout(location = 0) out vec4 frag_color; + +void main() { + frag_color.rgb = texture(specular, uv_interp).rgb; + frag_color.a = 0.0; +#ifdef MODE_SSR + + vec4 ssr_color = texture(ssr, uv_interp); + frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a); +#endif + +#ifdef MODE_MERGE + frag_color += texture(diffuse, uv_interp); +#endif + //added using additive blend +} diff --git a/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl index 134aae5ce7..134aae5ce7 100644 --- a/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssao.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl index 2a87e273bc..2a87e273bc 100644 --- a/servers/rendering/renderer_rd/shaders/ssao.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl index f42734c46d..f42734c46d 100644 --- a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl index 04f98964e8..04f98964e8 100644 --- a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl index f6a9a92fac..f6a9a92fac 100644 --- a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssil.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl index 513791dfbf..513791dfbf 100644 --- a/servers/rendering/renderer_rd/shaders/ssil.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl index 47c56571f6..47c56571f6 100644 --- a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl index 6b6b02739d..6b6b02739d 100644 --- a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl index 9e86ac0cf0..9e86ac0cf0 100644 --- a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl new file mode 100644 index 0000000000..5ef83c0b44 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl @@ -0,0 +1,72 @@ +#[vertex] + +#version 450 + +#VERSION_DEFINES + +#ifdef MULTIVIEW +#ifdef has_VK_KHR_multiview +#extension GL_EXT_multiview : enable +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#endif //MULTIVIEW + +#ifdef MULTIVIEW +layout(location = 0) out vec3 uv_interp; +#else +layout(location = 0) out vec2 uv_interp; +#endif + +void main() { + vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); + uv_interp.xy = base_arr[gl_VertexIndex]; +#ifdef MULTIVIEW + uv_interp.z = ViewIndex; +#endif + + gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0); +} + +#[fragment] + +#version 450 + +#VERSION_DEFINES + +#ifdef MULTIVIEW +#ifdef has_VK_KHR_multiview +#extension GL_EXT_multiview : enable +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#endif //MULTIVIEW + +#ifdef MULTIVIEW +layout(location = 0) in vec3 uv_interp; +layout(set = 0, binding = 0) uniform sampler2DArray source_color; +#else /* MULTIVIEW */ +layout(location = 0) in vec2 uv_interp; +layout(set = 0, binding = 0) uniform sampler2D source_color; +#endif /* MULTIVIEW */ + +layout(location = 0) out uint frag_color; + +void main() { +#ifdef MULTIVIEW + vec3 uv = uv_interp; +#else + vec2 uv = uv_interp; +#endif + +#ifdef MULTIVIEW + vec4 color = textureLod(source_color, uv, 0.0); +#else /* MULTIVIEW */ + vec4 color = textureLod(source_color, uv, 0.0); +#endif /* MULTIVIEW */ + + // See if we can change the sampler to one that returns int... + frag_color = uint(color.r * 256.0); +} diff --git a/servers/rendering/renderer_rd/shaders/environment/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl index f687d50a2d..6ea8cb1377 100644 --- a/servers/rendering/renderer_rd/shaders/environment/gi.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl @@ -8,6 +8,12 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #define M_PI 3.141592 +/* Specialization Constants (Toggles) */ + +layout(constant_id = 0) const bool sc_half_res = false; +layout(constant_id = 1) const bool sc_use_full_projection_matrix = false; +layout(constant_id = 2) const bool sc_use_vrs = false; + #define SDFGI_MAX_CASCADES 8 //set 0 for SDFGI and render buffers @@ -97,18 +103,20 @@ layout(set = 0, binding = 18, std140) uniform SceneData { } scene_data; +layout(r8ui, set = 0, binding = 19) uniform restrict readonly uimage2D vrs_buffer; + layout(push_constant, std430) uniform Params { - uint view_index; uint max_voxel_gi_instances; bool high_quality_vct; bool orthogonal; + uint view_index; vec4 proj_info; float z_near; float z_far; - float pad1; float pad2; + float pad3; } params; @@ -140,34 +148,34 @@ vec4 blend_color(vec4 src, vec4 dst) { } vec3 reconstruct_position(ivec2 screen_pos) { -#ifdef USE_MULTIVIEW - vec4 pos; - pos.xy = (2.0 * vec2(screen_pos) / vec2(scene_data.screen_size)) - 1.0; - pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r * 2.0 - 1.0; - pos.w = 1.0; + if (sc_use_full_projection_matrix) { + vec4 pos; + pos.xy = (2.0 * vec2(screen_pos) / vec2(scene_data.screen_size)) - 1.0; + pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r * 2.0 - 1.0; + pos.w = 1.0; - pos = scene_data.inv_projection[params.view_index] * pos; + pos = scene_data.inv_projection[params.view_index] * pos; - return pos.xyz / pos.w; -#else - vec3 pos; - pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r; - - pos.z = pos.z * 2.0 - 1.0; - if (params.orthogonal) { - pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + return pos.xyz / pos.w; } else { - pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near)); - } - pos.z = -pos.z; + vec3 pos; + pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r; + + pos.z = pos.z * 2.0 - 1.0; + if (params.orthogonal) { + pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near)); + } + pos.z = -pos.z; - pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw; - if (!params.orthogonal) { - pos.xy *= pos.z; - } + pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw; + if (!params.orthogonal) { + pos.xy *= pos.z; + } - return pos; -#endif + return pos; + } } void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) { @@ -587,7 +595,6 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 vec4 fetch_normal_and_roughness(ivec2 pos) { vec4 normal_roughness = texelFetch(sampler2D(normal_roughness_buffer, linear_sampler), pos, 0); - normal_roughness.xyz = normalize(normal_roughness.xyz * 2.0 - 1.0); return normal_roughness; } @@ -600,7 +607,7 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref if (normal.length() > 0.5) { //valid normal, can do GI float roughness = normal_roughness.w; - vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[params.view_index].xyz)); + vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[gl_GlobalInvocationID.z].xyz)); vertex = mat3(scene_data.cam_transform) * vertex; normal = normalize(mat3(scene_data.cam_transform) * normal); vec3 reflection = normalize(reflect(-view, normal)); @@ -648,9 +655,35 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref void main() { ivec2 pos = ivec2(gl_GlobalInvocationID.xy); -#ifdef MODE_HALF_RES - pos <<= 1; -#endif + uint vrs_x, vrs_y; + if (sc_use_vrs) { + ivec2 vrs_pos; + + // Currently we use a 16x16 texel, possibly some day make this configurable. + if (sc_half_res) { + vrs_pos = pos >> 3; + } else { + vrs_pos = pos >> 4; + } + + uint vrs_texel = imageLoad(vrs_buffer, vrs_pos).r; + // note, valid values for vrs_x and vrs_y are 1, 2 and 4. + vrs_x = 1 << ((vrs_texel >> 2) & 3); + vrs_y = 1 << (vrs_texel & 3); + + if (mod(pos.x, vrs_x) != 0) { + return; + } + + if (mod(pos.y, vrs_y) != 0) { + return; + } + } + + if (sc_half_res) { + pos <<= 1; + } + if (any(greaterThanEqual(pos, scene_data.screen_size))) { //too large, do nothing return; } @@ -663,10 +696,69 @@ void main() { process_gi(pos, vertex, ambient_light, reflection_light); -#ifdef MODE_HALF_RES - pos >>= 1; -#endif + if (sc_half_res) { + pos >>= 1; + } imageStore(ambient_buffer, pos, ambient_light); imageStore(reflection_buffer, pos, reflection_light); + + if (sc_use_vrs) { + if (vrs_x > 1) { + imageStore(ambient_buffer, pos + ivec2(1, 0), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 0), reflection_light); + } + + if (vrs_x > 2) { + imageStore(ambient_buffer, pos + ivec2(2, 0), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 0), reflection_light); + + imageStore(ambient_buffer, pos + ivec2(3, 0), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 0), reflection_light); + } + + if (vrs_y > 1) { + imageStore(ambient_buffer, pos + ivec2(0, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(0, 1), reflection_light); + } + + if (vrs_y > 1 && vrs_x > 1) { + imageStore(ambient_buffer, pos + ivec2(1, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 1), reflection_light); + } + + if (vrs_y > 1 && vrs_x > 2) { + imageStore(ambient_buffer, pos + ivec2(2, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 1), reflection_light); + + imageStore(ambient_buffer, pos + ivec2(3, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 1), reflection_light); + } + + if (vrs_y > 2) { + imageStore(ambient_buffer, pos + ivec2(0, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(0, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(0, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(0, 3), reflection_light); + } + + if (vrs_y > 2 && vrs_x > 1) { + imageStore(ambient_buffer, pos + ivec2(1, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(1, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 3), reflection_light); + } + + if (vrs_y > 2 && vrs_x > 2) { + imageStore(ambient_buffer, pos + ivec2(2, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(2, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 3), reflection_light); + + imageStore(ambient_buffer, pos + ivec2(3, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(3, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 3), reflection_light); + } + } } diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl index 5b4594da99..5b4594da99 100644 --- a/servers/rendering/renderer_rd/shaders/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl index eee609fb48..fb3c725b1f 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl @@ -21,8 +21,8 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; #define DENSITY_SCALE 1024.0 -#include "cluster_data_inc.glsl" -#include "light_data_inc.glsl" +#include "../cluster_data_inc.glsl" +#include "../light_data_inc.glsl" #define M_PI 3.14159265359 diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl index fdbd7d3e35..e74cfad65c 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl @@ -19,8 +19,8 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #endif -#include "cluster_data_inc.glsl" -#include "light_data_inc.glsl" +#include "../cluster_data_inc.glsl" +#include "../light_data_inc.glsl" #define M_PI 3.14159265359 diff --git a/servers/rendering/renderer_rd/shaders/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/specular_merge.glsl deleted file mode 100644 index 3579c35cce..0000000000 --- a/servers/rendering/renderer_rd/shaders/specular_merge.glsl +++ /dev/null @@ -1,53 +0,0 @@ -#[vertex] - -#version 450 - -#VERSION_DEFINES - -layout(location = 0) out vec2 uv_interp; - -void main() { - vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); - uv_interp = base_arr[gl_VertexIndex]; - - gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); -} - -#[fragment] - -#version 450 - -#VERSION_DEFINES - -layout(location = 0) in vec2 uv_interp; - -layout(set = 0, binding = 0) uniform sampler2D specular; - -#ifdef MODE_SSR - -layout(set = 1, binding = 0) uniform sampler2D ssr; - -#endif - -#ifdef MODE_MERGE - -layout(set = 2, binding = 0) uniform sampler2D diffuse; - -#endif - -layout(location = 0) out vec4 frag_color; - -void main() { - frag_color.rgb = texture(specular, uv_interp).rgb; - frag_color.a = 0.0; -#ifdef MODE_SSR - - vec4 ssr_color = texture(ssr, uv_interp); - frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a); -#endif - -#ifdef MODE_MERGE - frag_color += texture(diffuse, uv_interp); -#endif - //added using additive blend -} diff --git a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl index a1a77b95aa..b0a0839836 100644 --- a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl +++ b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl @@ -29,7 +29,8 @@ #VERSION_DEFINES -// Based on Spartan Engine's TAA implementation https://github.com/PanosK92/SpartanEngine/blob/master/Data/shaders/temporal_antialiasing.hlsl +// Based on Spartan Engine's TAA implementation (without TAA upscale). +// <https://github.com/PanosK92/SpartanEngine/blob/a8338d0609b85dc32f3732a5c27fb4463816a3b9/Data/shaders/temporal_antialiasing.hlsl> #define USE_SUBGROUPS @@ -188,7 +189,7 @@ vec3 sample_catmull_rom_9(sampler2D stex, vec2 uv, vec2 resolution) { // Source: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1 // License: https://gist.github.com/TheRealMJP/bc503b0b87b643d3505d41eab8b332ae - // We're going to sample a a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding + // We're going to sample a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding // down the sample location to get the exact center of our "starting" texel. The starting texel will be at // location [1, 1] in the grid, where [0, 0] is the top left corner. vec2 sample_pos = uv * resolution; diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index fb25e4da7e..2fb8f92fff 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -368,4 +368,4 @@ public: } // namespace RendererRD -#endif // !LIGHT_STORAGE_RD_H +#endif // LIGHT_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index fcd25852eb..23d05de942 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -172,75 +172,96 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_IVEC2: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 2 * p_array_size; - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored + } else { + Vector2i v = value; + gui[0] = v.x; + gui[1] = v.y; } } break; case ShaderLanguage::TYPE_IVEC3: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 3 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored } - gui[j + 3] = 0; // ignored + } else { + Vector3i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; } } break; case ShaderLanguage::TYPE_IVEC4: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i += 4) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; + if (p_array_size <= 0) { + p_array_size = 1; } + int count = 4 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0; i < count; i += 4) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } + } + } else { + Vector4i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } } break; case ShaderLanguage::TYPE_UINT: { @@ -267,75 +288,96 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_UVEC2: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; + if (p_array_size <= 0) { + p_array_size = 1; + } + int count = 2 * p_array_size; - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored + } else { + Vector2i v = value; + gui[0] = v.x; + gui[1] = v.y; } } break; case ShaderLanguage::TYPE_UVEC3: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; + if (p_array_size <= 0) { + p_array_size = 1; } - gui[j + 3] = 0; // ignored + int count = 3 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored + } + } else { + Vector3i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; } } break; case ShaderLanguage::TYPE_UVEC4: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i++) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; + if (p_array_size <= 0) { + p_array_size = 1; } + int count = 4 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0; i < count; i++) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } + } + } else { + Vector4i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } } break; case ShaderLanguage::TYPE_FLOAT: { @@ -514,13 +556,20 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[1] = v.y; gui[2] = v.z; gui[3] = v.w; - } else { + } else if (value.get_type() == Variant::PLANE) { Plane v = value; gui[0] = v.normal.x; gui[1] = v.normal.y; gui[2] = v.normal.z; gui[3] = v.d; + } else { + Vector4 v = value; + + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } } } break; @@ -670,7 +719,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[i + 15] = 1; } } - } else { + } else if (value.get_type() == Variant::TRANSFORM3D) { Transform3D v = value; gui[0] = v.basis.rows[0][0]; gui[1] = v.basis.rows[1][0]; @@ -691,6 +740,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[13] = v.origin.y; gui[14] = v.origin.z; gui[15] = 1; + } else { + Projection v = value; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + gui[i * 4 + j] = v.matrix[i][j]; + } + } } } break; default: { @@ -2341,6 +2397,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { } if (shader->data) { + shader->data->set_path_hint(shader->path_hint); shader->data->set_code(p_code); } @@ -2351,6 +2408,16 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { } } +void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) { + Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND(!shader); + + shader->path_hint = p_path; + if (shader->data) { + shader->data->set_path_hint(p_path); + } +} + String MaterialStorage::shader_get_code(RID p_shader) const { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND_V(!shader, String()); diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index e35d5e7669..d5c9980150 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -31,7 +31,7 @@ #ifndef MATERIAL_STORAGE_RD_H #define MATERIAL_STORAGE_RD_H -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/templates/local_vector.h" #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" @@ -57,6 +57,7 @@ enum ShaderType { struct ShaderData { virtual void set_code(const String &p_Code) = 0; + virtual void set_path_hint(const String &p_hint) = 0; virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0; @@ -77,6 +78,7 @@ struct Material; struct Shader { ShaderData *data = nullptr; String code; + String path_hint; ShaderType type; HashMap<StringName, HashMap<int, RID>> default_texture_parameter; HashSet<Material *> owners; @@ -300,7 +302,7 @@ public: p_array[11] = p_mtx.origin.z; } - static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { + static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { p_array[i * 4 + j] = p_mtx.matrix[i][j]; @@ -364,6 +366,7 @@ public: virtual void shader_free(RID p_rid) override; virtual void shader_set_code(RID p_shader, const String &p_code) override; + virtual void shader_set_path_hint(RID p_shader, const String &p_path) override; virtual String shader_get_code(RID p_shader) const override; virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; @@ -421,4 +424,4 @@ public: } // namespace RendererRD -#endif // !MATERIAL_STORAGE_RD_H +#endif // MATERIAL_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 9cdda6bfca..396fe9b6a6 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -703,4 +703,4 @@ public: } // namespace RendererRD -#endif // !MESH_STORAGE_RD_H +#endif // MESH_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 5200e0d318..75977c5bc9 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -1512,6 +1512,9 @@ bool ParticlesStorage::particles_is_inactive(RID p_particles) const { /* Particles SHADER */ +void ParticlesStorage::ParticlesShaderData::set_path_hint(const String &p_path) { + path = p_path; +} void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) { ParticlesStorage *particles_storage = ParticlesStorage::get_singleton(); //compile @@ -1609,7 +1612,22 @@ void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index 70ac6f0349..75f995deeb 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -363,6 +363,7 @@ private: uint32_t userdata_count = 0; virtual void set_code(const String &p_Code); + virtual void set_path_hint(const String &p_hint); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; @@ -561,4 +562,4 @@ public: } // namespace RendererRD -#endif // !PARTICLES_STORAGE_RD_H +#endif // PARTICLES_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 1109357a74..abf364b8b4 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -191,7 +191,7 @@ TextureStorage::TextureStorage() { } } - { //create default cubemap + { //create default black cubemap array RD::TextureFormat tformat; tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -219,7 +219,35 @@ TextureStorage::TextureStorage() { } } - { //create default cubemap array + { //create default white cubemap array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default black cubemap RD::TextureFormat tformat; tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -247,7 +275,7 @@ TextureStorage::TextureStorage() { } } - { //create default cubemap white array + { //create default white cubemap RD::TextureFormat tformat; tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -349,7 +377,6 @@ TextureStorage::TextureStorage() { Vector<uint8_t> pv; pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { pv.set(i * 4 + 0, 0); pv.set(i * 4 + 1, 0); @@ -358,7 +385,6 @@ TextureStorage::TextureStorage() { } { - //take the chance and initialize decal atlas to something Vector<Vector<uint8_t>> vpv; vpv.push_back(pv); decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); @@ -366,6 +392,29 @@ TextureStorage::TextureStorage() { } } + { //create default VRS + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8_UINT; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 1; + tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + + Vector<uint8_t> pv; + pv.resize(4 * 4); + for (int i = 0; i < 4 * 4; i++) { + pv.set(i, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_VRS] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + { Vector<String> sdf_modes; sdf_modes.push_back("\n#define MODE_LOAD\n"); @@ -2751,3 +2800,31 @@ void TextureStorage::render_target_set_backbuffer_uniform_set(RID p_render_targe ERR_FAIL_COND(!rt); rt->backbuffer_uniform_set = p_uniform_set; } + +void TextureStorage::render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + rt->vrs_mode = p_mode; +} + +void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + rt->vrs_texture = p_texture; +} + +RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RS::VIEWPORT_VRS_DISABLED); + + return rt->vrs_mode; +} + +RID TextureStorage::render_target_get_vrs_texture(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->vrs_texture; +} diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 7a96e6c6ed..1a5a3dd023 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -48,10 +48,12 @@ enum DefaultRDTexture { DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, + DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE, DEFAULT_RD_TEXTURE_3D_WHITE, DEFAULT_RD_TEXTURE_3D_BLACK, DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, DEFAULT_RD_TEXTURE_2D_UINT, + DEFAULT_RD_TEXTURE_VRS, DEFAULT_RD_TEXTURE_MAX }; @@ -229,6 +231,10 @@ struct RenderTarget { RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT; Size2i process_size; + // VRS + RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED; + RID vrs_texture; + //texture generated for this owner (nor RD). RID texture; bool was_used; @@ -549,6 +555,12 @@ public: virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override; bool render_target_is_sdf_enabled(RID p_render_target) const; + virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override; + virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override; + + RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const; + RID render_target_get_vrs_texture(RID p_render_target) const; + Size2 render_target_get_size(RID p_render_target); RID render_target_get_rd_framebuffer(RID p_render_target); RID render_target_get_rd_texture(RID p_render_target); @@ -564,4 +576,4 @@ public: } // namespace RendererRD -#endif // !_TEXTURE_STORAGE_RD_H +#endif // TEXTURE_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.h b/servers/rendering/renderer_rd/storage_rd/utilities.h index 979e984546..a80eb8510e 100644 --- a/servers/rendering/renderer_rd/storage_rd/utilities.h +++ b/servers/rendering/renderer_rd/storage_rd/utilities.h @@ -119,4 +119,4 @@ public: } // namespace RendererRD -#endif // !UTILITIES_RD_H +#endif // UTILITIES_RD_H diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.h b/servers/rendering/renderer_rd/uniform_set_cache_rd.h index af22a48716..abf110730b 100644 --- a/servers/rendering/renderer_rd/uniform_set_cache_rd.h +++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef UNIFORM_SET_CACHE_H -#define UNIFORM_SET_CACHE_H +#ifndef UNIFORM_SET_CACHE_RD_H +#define UNIFORM_SET_CACHE_RD_H #include "core/templates/local_vector.h" #include "core/templates/paged_allocator.h" @@ -220,4 +220,4 @@ public: ~UniformSetCacheRD(); }; -#endif // UNIFORMSETCACHE_H +#endif // UNIFORM_SET_CACHE_RD_H |