diff options
Diffstat (limited to 'servers/rendering')
57 files changed, 5341 insertions, 3952 deletions
diff --git a/servers/rendering/dummy/environment/fog.h b/servers/rendering/dummy/environment/fog.h index 623f94b95f..047b8e133d 100644 --- a/servers/rendering/dummy/environment/fog.h +++ b/servers/rendering/dummy/environment/fog.h @@ -41,7 +41,7 @@ public: virtual RID fog_volume_allocate() override { return RID(); } virtual void fog_volume_initialize(RID p_rid) override {} - virtual void fog_free(RID p_rid) override {} + virtual void fog_volume_free(RID p_rid) override {} virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {} virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {} diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h index e41373ed37..bc8f7c523b 100644 --- a/servers/rendering/dummy/rasterizer_scene_dummy.h +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -93,17 +93,6 @@ public: uint32_t geometry_instance_get_pair_mask() override { return 0; } - /* SHADOW ATLAS API */ - - RID shadow_atlas_create() override { return RID(); } - void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {} - void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {} - bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; } - - void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {} - int get_directional_light_shadow_size(RID p_light_intance) override { return 0; } - void set_directional_shadow_count(int p_count) override {} - /* SDFGI UPDATE */ void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} @@ -143,36 +132,12 @@ public: void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override {} void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override {} - RID light_instance_create(RID p_light) override { return RID(); } - void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {} - void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {} - 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 {} - void light_instance_mark_visible(RID p_light_instance) override {} - RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); } void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {} void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {} RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); } Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); } - RID reflection_atlas_create() override { return RID(); } - int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; } - void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {} - - RID reflection_probe_instance_create(RID p_probe) override { return RID(); } - void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {} - void reflection_probe_release_atlas_index(RID p_instance) override {} - bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; } - bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; } - bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; } - bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; } - - RID decal_instance_create(RID p_decal) override { return RID(); } - void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {} - - RID lightmap_instance_create(RID p_lightmap) override { return RID(); } - void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {} - RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); } void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {} bool voxel_gi_needs_update(RID p_probe) const override { return false; } diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h index 79f484d513..13c342d823 100644 --- a/servers/rendering/dummy/storage/light_storage.h +++ b/servers/rendering/dummy/storage/light_storage.h @@ -81,6 +81,15 @@ public: virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; } virtual uint64_t light_get_version(RID p_light) const override { return 0; } + /* LIGHT INSTANCE API */ + + RID light_instance_create(RID p_light) override { return RID(); } + void light_instance_free(RID p_light) override {} + void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {} + void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {} + 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 {} + void light_instance_mark_visible(RID p_light_instance) override {} + /* PROBE API */ virtual RID reflection_probe_allocate() override { return RID(); } virtual void reflection_probe_initialize(RID p_rid) override {} @@ -110,7 +119,26 @@ public: virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; } virtual bool reflection_probe_renders_shadows(RID p_probe) const override { return false; } + /* REFLECTION ATLAS */ + + virtual RID reflection_atlas_create() override { return RID(); } + virtual void reflection_atlas_free(RID p_ref_atlas) override {} + virtual int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; } + virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {} + + /* REFLECTION PROBE INSTANCE */ + + virtual RID reflection_probe_instance_create(RID p_probe) override { return RID(); } + virtual void reflection_probe_instance_free(RID p_instance) override {} + virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {} + virtual void reflection_probe_release_atlas_index(RID p_instance) override {} + virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; } + virtual bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; } + virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; } + virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; } + /* LIGHTMAP CAPTURE */ + virtual RID lightmap_allocate() override { return RID(); } virtual void lightmap_initialize(RID p_rid) override {} virtual void lightmap_free(RID p_rid) override {} @@ -129,6 +157,25 @@ public: virtual bool lightmap_is_interior(RID p_lightmap) const override { return false; } virtual void lightmap_set_probe_capture_update_speed(float p_speed) override {} virtual float lightmap_get_probe_capture_update_speed() const override { return 0; } + + /* LIGHTMAP INSTANCE */ + + RID lightmap_instance_create(RID p_lightmap) override { return RID(); } + void lightmap_instance_free(RID p_lightmap) override {} + void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {} + + /* SHADOW ATLAS API */ + virtual RID shadow_atlas_create() override { return RID(); } + virtual void shadow_atlas_free(RID p_atlas) override {} + virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {} + virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {} + virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; } + + virtual void shadow_atlas_update(RID p_atlas) override {} + + virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {} + virtual int get_directional_light_shadow_size(RID p_light_intance) override { return 0; } + virtual void set_directional_shadow_count(int p_count) override {} }; } // namespace RendererDummy diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index c15b656d06..98acd5ad74 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -146,19 +146,28 @@ public: virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} + /* DECAL INSTANCE */ + + virtual RID decal_instance_create(RID p_decal) override { return RID(); } + virtual void decal_instance_free(RID p_decal_instance) override {} + virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {} + /* RENDER TARGET */ virtual RID render_target_create() override { return RID(); } virtual void render_target_free(RID p_rid) override {} virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override {} + virtual Point2i render_target_get_position(RID p_render_target) const override { return Point2i(); } virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {} - virtual RID render_target_get_texture(RID p_render_target) override { return RID(); } - virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {} + virtual Size2i render_target_get_size(RID p_render_target) const override { return Size2i(); } virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override {} + virtual bool render_target_get_transparent(RID p_render_target) const override { return false; } virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override {} - virtual bool render_target_was_used(RID p_render_target) override { return false; } + virtual bool render_target_get_direct_to_screen(RID p_render_target) const override { return false; } + virtual bool render_target_was_used(RID p_render_target) const override { return false; } virtual void render_target_set_as_unused(RID p_render_target) override {} virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override {} + virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override { return RS::VIEWPORT_MSAA_DISABLED; } virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {} virtual bool render_target_is_clear_requested(RID p_render_target) override { return false; } @@ -170,8 +179,19 @@ public: virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); } virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {} - 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{}; + virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override {} + virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_DISABLED; } + virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {} + virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); } + + virtual void render_target_set_override_color(RID p_render_target, RID p_texture) override {} + virtual RID render_target_get_override_color(RID p_render_target) const override { return RID(); } + virtual void render_target_set_override_depth(RID p_render_target, RID p_texture) override {} + virtual RID render_target_get_override_depth(RID p_render_target) const override { return RID(); } + virtual void render_target_set_override_velocity(RID p_render_target, RID p_texture) override {} + virtual RID render_target_get_override_velocity(RID p_render_target) const override { return RID(); } + + virtual RID render_target_get_texture(RID p_render_target) override { return RID(); } }; } // namespace RendererDummy diff --git a/servers/rendering/environment/renderer_fog.h b/servers/rendering/environment/renderer_fog.h index c55021e1a1..8f38d5745e 100644 --- a/servers/rendering/environment/renderer_fog.h +++ b/servers/rendering/environment/renderer_fog.h @@ -41,7 +41,7 @@ public: virtual RID fog_volume_allocate() = 0; virtual void fog_volume_initialize(RID p_rid) = 0; - virtual void fog_free(RID p_rid) = 0; + virtual void fog_volume_free(RID p_rid) = 0; virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) = 0; virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) = 0; diff --git a/servers/rendering/renderer_rd/effects/fsr.cpp b/servers/rendering/renderer_rd/effects/fsr.cpp index 5fde24a926..92b34ede0e 100644 --- a/servers/rendering/renderer_rd/effects/fsr.cpp +++ b/servers/rendering/renderer_rd/effects/fsr.cpp @@ -29,7 +29,8 @@ /*************************************************************************/ #include "fsr.h" -#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" +#include "../storage_rd/material_storage.h" +#include "../uniform_set_cache_rd.h" using namespace RendererRD; diff --git a/servers/rendering/renderer_rd/effects/fsr.h b/servers/rendering/renderer_rd/effects/fsr.h index 1adfba527a..69088e526a 100644 --- a/servers/rendering/renderer_rd/effects/fsr.h +++ b/servers/rendering/renderer_rd/effects/fsr.h @@ -31,11 +31,10 @@ #ifndef FSR_RD_H #define FSR_RD_H -#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" -#include "servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl.gen.h" -#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" +#include "../pipeline_cache_rd.h" +#include "../shaders/effects/fsr_upscale.glsl.gen.h" +#include "../storage_rd/render_scene_buffers_rd.h" #include "servers/rendering/renderer_scene_render.h" - #include "servers/rendering_server.h" namespace RendererRD { diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index 582c5abbdd..4bc6cd6143 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -30,6 +30,7 @@ #include "ss_effects.h" +#include "core/config/project_settings.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/render_scene_buffers_rd.h" @@ -42,7 +43,7 @@ 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]; + p_array[i * 4 + j] = p_mtx.columns[i][j]; } } } @@ -50,8 +51,8 @@ static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) SSEffects::SSEffects() { singleton = this; + // Initialize depth buffer for screen space 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"); @@ -100,6 +101,7 @@ SSEffects::SSEffects() { } // Initialize Screen Space Indirect Lighting (SSIL) + ssil_set_quality(RS::EnvironmentSSILQuality(int(GLOBAL_GET("rendering/environment/ssil/quality"))), GLOBAL_GET("rendering/environment/ssil/half_size"), GLOBAL_GET("rendering/environment/ssil/adaptive_target"), GLOBAL_GET("rendering/environment/ssil/blur_passes"), GLOBAL_GET("rendering/environment/ssil/fadeout_from"), GLOBAL_GET("rendering/environment/ssil/fadeout_to")); { Vector<String> ssil_modes; @@ -175,9 +177,10 @@ SSEffects::SSEffects() { } } - { - // Initialize Screen Space Ambient Occlusion (SSAO) + // Initialize Screen Space Ambient Occlusion (SSAO) + ssao_set_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to")); + { RD::SamplerState sampler; sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST; sampler.min_filter = RD::SAMPLER_FILTER_NEAREST; @@ -276,9 +279,10 @@ SSEffects::SSEffects() { ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler); } - { - // Screen Space Reflections + // Screen Space Reflections + ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/environment/screen_space_reflection/roughness_quality"))); + { Vector<RD::PipelineSpecializationConstant> specialization_constants; { @@ -336,6 +340,10 @@ SSEffects::SSEffects() { } // Subsurface scattering + sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality"))); + sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale"); + sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale"); + { Vector<String> sss_modes; sss_modes.push_back("\n#define USE_11_SAMPLES\n"); @@ -403,7 +411,7 @@ SSEffects::~SSEffects() { /* 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) { +void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, bool p_invalidate_uniform_set, 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(); @@ -413,9 +421,9 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ 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; + bool use_mips = ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || 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) { + if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { downsample_mode = SS_EFFECTS_DOWNSAMPLE_HALF; } else if (use_mips) { downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP; @@ -424,10 +432,10 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ bool use_half_size = false; bool use_full_mips = false; - if (p_ssao_half_size && p_ssil_half_size) { + if (ssao_half_size && ssil_half_size) { downsample_mode++; use_half_size = true; - } else if (p_ssao_half_size != p_ssil_half_size) { + } else if (ssao_half_size != ssil_half_size) { if (use_mips) { downsample_mode = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS; use_full_mips = true; @@ -480,8 +488,8 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ 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]; + float depth_linearize_mul = -p_projection.columns[3][2]; + float depth_linearize_add = p_projection.columns[2][2]; if (depth_linearize_mul * depth_linearize_add < 0) { depth_linearize_add = -depth_linearize_add; } @@ -526,12 +534,21 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ /* SSIL */ +void SSEffects::ssil_set_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { + ssil_quality = p_quality; + ssil_half_size = p_half_size; + ssil_adaptive_target = p_adaptive_target; + ssil_blur_passes = p_blur_passes; + ssil_fadeout_from = p_fadeout_from; + ssil_fadeout_to = p_fadeout_to; +} + 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) { + if ((ssil_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); @@ -539,7 +556,7 @@ void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> 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))) { + if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { continue; } @@ -554,7 +571,7 @@ void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> 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)); + Size2i size = Size2i(p_settings.full_screen_size.x >> (ssil_half_size ? 2 : 1), p_settings.full_screen_size.y >> (ssil_half_size ? 2 : 1)); RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1); } @@ -562,11 +579,11 @@ void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> } 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) { + if (p_ssil_buffers.half_size != ssil_half_size) { ssil_free(p_ssil_buffers); } - if (p_settings.half_size) { + if (ssil_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; @@ -580,7 +597,7 @@ void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const S 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); + p_ssil_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, ssil_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); } { RD::TextureFormat tf; @@ -665,7 +682,7 @@ void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const S 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; + p_ssil_buffers.half_size = ssil_half_size; } } @@ -696,8 +713,8 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers 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]; + float tan_half_fov_x = 1.0 / p_projection.columns[0][0]; + float tan_half_fov_y = 1.0 / p_projection.columns[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; @@ -711,26 +728,26 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers 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) { + if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) { radius_near_limit *= 1.50f; - if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { + if (ssil_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.fade_out_mul = -1.0 / (ssil_fadeout_to - ssil_fadeout_from); + ssil.gather_push_constant.fade_out_add = ssil_fadeout_from / (ssil_fadeout_to - ssil_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.adaptive_sample_limit = ssil_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; + ssil.gather_push_constant.quality = MAX(0, ssil_quality - 1); + ssil.gather_push_constant.size_multiplier = ssil_half_size ? 2 : 1; if (p_ssil_buffers.projection_uniform_set.is_null()) { Vector<RD::Uniform> uniforms; @@ -806,7 +823,7 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers 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) { + if (ssil_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; @@ -865,13 +882,13 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers 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; + int blur_passes = ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? ssil_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) { + if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW) { blur_pipeline = SSIL_BLUR_PASS_SMART; if (pass < blur_passes - 2) { blur_pipeline = SSIL_BLUR_PASS_WIDE; @@ -879,13 +896,13 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers } for (int i = 0; i < 4; i++) { - if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + if ((ssil_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) { + if (ssil_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 { @@ -896,7 +913,7 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers 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) { + if (ssil_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 { @@ -913,11 +930,11 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers 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)); + int x_groups = (p_settings.full_screen_size.x >> (ssil_half_size ? 2 : 1)); + int y_groups = (p_settings.full_screen_size.y >> (ssil_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) { + if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW) { RD::get_singleton()->compute_list_add_barrier(compute_list); } } @@ -931,12 +948,12 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_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); + ssil.interleave_push_constant.size_modifier = uint32_t(ssil_half_size ? 4 : 2); int interleave_pipeline = SSIL_INTERLEAVE_HALF; - if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) { + if (ssil_quality == RS::ENV_SSIL_QUALITY_LOW) { interleave_pipeline = SSIL_INTERLEAVE; - } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) { + } else if (ssil_quality >= RS::ENV_SSIL_QUALITY_MEDIUM) { interleave_pipeline = SSIL_INTERLEAVE_SMART; } @@ -947,7 +964,7 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers 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) { + if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW && ssil_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 { @@ -1003,19 +1020,28 @@ void SSEffects::ssil_free(SSILRenderBuffers &p_ssil_buffers) { /* SSAO */ +void SSEffects::ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { + ssao_quality = p_quality; + ssao_half_size = p_half_size; + ssao_adaptive_target = p_adaptive_target; + ssao_blur_passes = p_blur_passes; + ssao_fadeout_from = p_fadeout_from; + ssao_fadeout_to = p_fadeout_to; +} + 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) { + if ((ssao_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))) { + if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { continue; } @@ -1029,7 +1055,7 @@ void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> 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)); + Size2i size = Size2i(p_settings.full_screen_size.x >> (ssao_half_size ? 2 : 1), p_settings.full_screen_size.y >> (ssao_half_size ? 2 : 1)); RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1); } @@ -1037,11 +1063,11 @@ void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> } 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) { + if (p_ssao_buffers.half_size != ssao_half_size) { ssao_free(p_ssao_buffers); } - if (p_settings.half_size) { + if (ssao_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; @@ -1055,7 +1081,7 @@ void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const S 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); + p_ssao_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, ssao_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); } { RD::TextureFormat tf; @@ -1111,7 +1137,7 @@ void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const S 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; + p_ssao_buffers.half_size = ssao_half_size; } } @@ -1138,8 +1164,8 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu 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]; + float tan_half_fov_x = 1.0 / p_projection.columns[0][0]; + float tan_half_fov_y = 1.0 / p_projection.columns[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; @@ -1151,10 +1177,10 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu 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) { + if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) { radius_near_limit *= 1.50f; - if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { + if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { ssao.gather_push_constant.radius *= 0.8f; } } @@ -1162,18 +1188,18 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu 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.fade_out_mul = -1.0 / (ssao_fadeout_to - ssao_fadeout_from); + ssao.gather_push_constant.fade_out_add = ssao_fadeout_from / (ssao_fadeout_to - ssao_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.adaptive_sample_limit = ssao_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; + ssao.gather_push_constant.quality = MAX(0, ssao_quality - 1); + ssao.gather_push_constant.size_multiplier = ssao_half_size ? 2 : 1; if (p_ssao_buffers.gather_uniform_set.is_null()) { Vector<RD::Uniform> uniforms; @@ -1231,7 +1257,7 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu 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) { + if (ssao_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; @@ -1299,13 +1325,13 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu 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; + int blur_passes = ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? ssao_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) { + if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { blur_pipeline = SSAO_BLUR_PASS_SMART; if (pass < blur_passes - 2) { blur_pipeline = SSAO_BLUR_PASS_WIDE; @@ -1315,13 +1341,13 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu } for (int i = 0; i < 4; i++) { - if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + if ((ssao_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) { + if (ssao_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 { @@ -1332,7 +1358,7 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu 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) { + if (ssao_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 { @@ -1345,11 +1371,11 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu } 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)); + Size2i size(p_settings.full_screen_size.x >> (ssao_half_size ? 2 : 1), p_settings.full_screen_size.y >> (ssao_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) { + if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { RD::get_singleton()->compute_list_add_barrier(compute_list); } } @@ -1364,14 +1390,14 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu 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); + ssao.interleave_push_constant.size_modifier = uint32_t(ssao_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) { + if (ssao_quality == RS::ENV_SSAO_QUALITY_LOW) { interleave_pipeline = SSAO_INTERLEAVE; - } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) { + } else if (ssao_quality >= RS::ENV_SSAO_QUALITY_MEDIUM) { interleave_pipeline = SSAO_INTERLEAVE_SMART; } @@ -1380,7 +1406,7 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu 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) { + if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW && ssao_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 { @@ -1425,7 +1451,11 @@ void SSEffects::ssao_free(SSAORenderBuffers &p_ssao_buffers) { /* 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) { +void SSEffects::ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) { + ssr_roughness_quality = p_quality; +} + +void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, 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()) { @@ -1446,7 +1476,7 @@ void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const Rend 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()) { + if (ssr_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; @@ -1490,7 +1520,7 @@ void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const Rend } } -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 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 SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, 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(); @@ -1581,12 +1611,12 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R 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.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].columns[0][0]); + push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].columns[1][1]); + push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0]; + push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1]; - ScreenSpaceReflectionMode mode = (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL; + ScreenSpaceReflectionMode mode = (ssr_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]); @@ -1598,7 +1628,7 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R 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) { + if (ssr_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); @@ -1619,7 +1649,7 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R RD::get_singleton()->draw_command_end_label(); } - if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { + if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { RD::get_singleton()->draw_command_begin_label("SSR filter"); //blur @@ -1629,15 +1659,15 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R push_constant.view_index = v; push_constant.orthogonal = p_projections[v].is_orthogonal(); push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(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.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].columns[0][0]); + push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].columns[1][1]); + push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0]; + push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1]; push_constant.vertical = 0; - if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) { + if (ssr_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) { + } else if (ssr_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) { push_constant.steps = p_max_steps / 2; push_constant.increment = 2; } else { @@ -1740,7 +1770,20 @@ void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) { /* Subsurface scattering */ -void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) { +void SSEffects::sss_set_quality(RS::SubSurfaceScatteringQuality p_quality) { + sss_quality = p_quality; +} + +RS::SubSurfaceScatteringQuality SSEffects::sss_get_quality() const { + return sss_quality; +} + +void SSEffects::sss_set_scale(float p_scale, float p_depth_scale) { + sss_scale = p_scale; + sss_depth_scale = p_depth_scale; +} + +void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -1769,11 +1812,11 @@ void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffer sss.push_constant.screen_size[0] = p_screen_size.x; sss.push_constant.screen_size[1] = p_screen_size.y; sss.push_constant.vertical = false; - sss.push_constant.scale = p_scale; - sss.push_constant.depth_scale = p_depth_scale; + sss.push_constant.scale = sss_scale; + sss.push_constant.depth_scale = sss_depth_scale; - RID shader = sss.shader.version_get_shader(sss.shader_version, p_quality - 1); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]); + RID shader = sss.shader.version_get_shader(sss.shader_version, sss_quality - 1); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[sss_quality - 1]); RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse })); RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse })); diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h index d50319c46f..7c264b4d76 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.h +++ b/servers/rendering/renderer_rd/effects/ss_effects.h @@ -64,9 +64,10 @@ public: /* 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); + void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, bool p_invalidate_uniform_set, Size2i p_full_screen_size, const Projection &p_projection); /* SSIL */ + void ssil_set_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to); struct SSILRenderBuffers { bool half_size = false; @@ -99,13 +100,6 @@ public: 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(); }; @@ -114,6 +108,7 @@ public: void ssil_free(SSILRenderBuffers &p_ssil_buffers); /* SSAO */ + void ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to); struct SSAORenderBuffers { bool half_size = false; @@ -142,13 +137,6 @@ public: 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(); }; @@ -157,6 +145,7 @@ public: void ssao_free(SSAORenderBuffers &p_ssao_buffers); /* Screen Space Reflection */ + void ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality); struct SSRRenderBuffers { RID normal_scaled; @@ -167,14 +156,40 @@ public: 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 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_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, 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, const RID *p_metallic_slices, 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); /* subsurface scattering */ - void sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality); + void sss_set_quality(RS::SubSurfaceScatteringQuality p_quality); + RS::SubSurfaceScatteringQuality sss_get_quality() const; + void sss_set_scale(float p_scale, float p_depth_scale); + + void sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size); private: + /* Settings */ + + RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM; + bool ssao_half_size = false; + float ssao_adaptive_target = 0.5; + int ssao_blur_passes = 2; + float ssao_fadeout_from = 50.0; + float ssao_fadeout_to = 300.0; + + RS::EnvironmentSSILQuality ssil_quality = RS::ENV_SSIL_QUALITY_MEDIUM; + bool ssil_half_size = false; + float ssil_adaptive_target = 0.5; + int ssil_blur_passes = 4; + float ssil_fadeout_from = 50.0; + float ssil_fadeout_to = 300.0; + + RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW; + + RS::SubSurfaceScatteringQuality sss_quality = RS::SUB_SURFACE_SCATTERING_QUALITY_MEDIUM; + float sss_scale = 0.05; + float sss_depth_scale = 0.01; + /* SS Downsampler */ struct SSEffectsDownsamplePushConstant { diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 3390e9cf64..74082906c4 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -57,12 +57,19 @@ void Fog::fog_volume_initialize(RID p_rid) { fog_volume_owner.initialize_rid(p_rid, FogVolume()); } -void Fog::fog_free(RID p_rid) { +void Fog::fog_volume_free(RID p_rid) { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid); fog_volume->dependency.deleted_notify(p_rid); fog_volume_owner.free(p_rid); } +Dependency *Fog::fog_volume_get_dependency(RID p_fog_volume) const { + FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); + ERR_FAIL_NULL_V(fog_volume, nullptr); + + return &fog_volume->dependency; +} + void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); ERR_FAIL_COND(!fog_volume); @@ -136,7 +143,7 @@ Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const { 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); + 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, true); } Fog::FogMaterialData::~FogMaterialData() { diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index 9ecd5699dc..0ade995758 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -46,7 +46,9 @@ namespace RendererRD { class Fog : public RendererFog { -public: +private: + static Fog *singleton; + /* FOG VOLUMES */ struct FogVolume { @@ -58,16 +60,14 @@ public: Dependency dependency; }; + mutable RID_Owner<FogVolume, true> fog_volume_owner; + 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 */ @@ -240,12 +240,12 @@ public: /* FOG VOLUMES */ - FogVolume *get_fog_volume(RID p_rid) { return fog_volume_owner.get_or_null(p_rid); }; bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); }; virtual RID fog_volume_allocate() override; virtual void fog_volume_initialize(RID p_rid) override; - virtual void fog_free(RID p_rid) override; + virtual void fog_volume_free(RID p_rid) override; + Dependency *fog_volume_get_dependency(RID p_fog_volume) const; virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override; virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override; @@ -257,12 +257,35 @@ public: /* 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); + void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) { + Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + ERR_FAIL_COND(!fvi); + fvi->transform = p_transform; + } + + void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) { + Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + ERR_FAIL_COND(!fvi); + fvi->active = p_active; + } + + RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const { + Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + ERR_FAIL_COND_V(!fvi, RID()); + return fvi->volume; + } + + Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const { + Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + ERR_FAIL_COND_V(!fvi, Vector3()); + return fvi->transform.get_origin(); + } + /* Volumetric FOG */ class VolumetricFog : public RenderBufferCustomDataRD { GDCLASS(VolumetricFog, RenderBufferCustomDataRD) diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index ced0f6380f..9b6be0b422 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -1634,7 +1634,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection Projection inv_projection = p_projections[v].inverse(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 3; j++) { - push_constant.inv_projection[j][i] = inv_projection.matrix[i][j]; + push_constant.inv_projection[j][i] = inv_projection.columns[i][j]; } } @@ -1644,8 +1644,8 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection RD::get_singleton()->compute_list_end(); } - Size2 rtsize = texture_storage->render_target_get_size(p_render_target); - 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); + Size2i rtsize = texture_storage->render_target_get_size(p_render_target); + copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2i(Point2i(), 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 Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { @@ -1798,7 +1798,8 @@ void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, con RD::get_singleton()->draw_list_end(); } -void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render) { +void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); /* Update general SDFGI Buffer */ SDFGIData sdfgi_data; @@ -1881,40 +1882,43 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r SDFGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS]; uint32_t idx = 0; - for (uint32_t j = 0; j < (uint32_t)p_scene_render->render_state.sdfgi_update_data->directional_lights->size(); j++) { + for (uint32_t j = 0; j < (uint32_t)p_render_data->sdfgi_update_data->directional_lights->size(); j++) { if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) { break; } - RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->directional_lights->get(j)); - ERR_CONTINUE(!li); + RID light_instance = p_render_data->sdfgi_update_data->directional_lights->get(j); + ERR_CONTINUE(!light_storage->owns_light_instance(light_instance)); - if (RSG::light_storage->light_directional_get_sky_mode(li->light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { + RID light = light_storage->light_instance_get_base_light(light_instance); + Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance); + + if (RSG::light_storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { continue; } - Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z); + Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z); dir.y *= y_mult; dir.normalize(); lights[idx].direction[0] = dir.x; lights[idx].direction[1] = dir.y; lights[idx].direction[2] = dir.z; - Color color = RSG::light_storage->light_get_color(li->light); + Color color = RSG::light_storage->light_get_color(light); color = color.srgb_to_linear(); lights[idx].color[0] = color.r; lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; lights[idx].type = RS::LIGHT_DIRECTIONAL; - lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); - if (p_scene_render->is_using_physical_light_units()) { - lights[idx].energy *= RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INTENSITY); + lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { + lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); } if (p_render_data->camera_attributes.is_valid()) { lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); } - lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); + lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light); idx++; } @@ -1923,45 +1927,49 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cascade.position)) * cascade.cell_size; cascade_aabb.size = Vector3(1, 1, 1) * cascade_size * cascade.cell_size; - for (uint32_t j = 0; j < p_scene_render->render_state.sdfgi_update_data->positional_light_count; j++) { + for (uint32_t j = 0; j < p_render_data->sdfgi_update_data->positional_light_count; j++) { if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) { break; } - RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->positional_light_instances[j]); - ERR_CONTINUE(!li); + RID light_instance = p_render_data->sdfgi_update_data->positional_light_instances[j]; + ERR_CONTINUE(!light_storage->owns_light_instance(light_instance)); + + RID light = light_storage->light_instance_get_base_light(light_instance); + AABB light_aabb = light_storage->light_instance_get_base_aabb(light_instance); + Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance); - uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light); + uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(light); if (i > max_sdfgi_cascade) { continue; } - if (!cascade_aabb.intersects(li->aabb)) { + if (!cascade_aabb.intersects(light_aabb)) { continue; } - Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z); + Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z); //faster to not do this here //dir.y *= y_mult; //dir.normalize(); lights[idx].direction[0] = dir.x; lights[idx].direction[1] = dir.y; lights[idx].direction[2] = dir.z; - Vector3 pos = li->transform.origin; + Vector3 pos = light_transform.origin; pos.y *= y_mult; lights[idx].position[0] = pos.x; lights[idx].position[1] = pos.y; lights[idx].position[2] = pos.z; - Color color = RSG::light_storage->light_get_color(li->light); + Color color = RSG::light_storage->light_get_color(light); color = color.srgb_to_linear(); lights[idx].color[0] = color.r; lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; - lights[idx].type = RSG::light_storage->light_get_type(li->light); + lights[idx].type = RSG::light_storage->light_get_type(light); - lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); - if (p_scene_render->is_using_physical_light_units()) { - lights[idx].energy *= RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INTENSITY); + lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { + lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); // Convert from Luminous Power to Luminous Intensity if (lights[idx].type == RS::LIGHT_OMNI) { @@ -1977,11 +1985,11 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); } - lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); - lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); - lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); - lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); - lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); + lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light); + lights[idx].attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); + lights[idx].radius = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE); + lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); + lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION); idx++; } @@ -1994,7 +2002,7 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r } } -void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization) { +void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, float p_exposure_normalization) { //print_line("rendering region " + itos(p_region)); ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but... AABB bounds; @@ -2015,7 +2023,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_ } //print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(cascades[cascade].cell_size)); - p_scene_render->_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, render_albedo, render_emission, render_emission_aniso, render_geom_facing, p_exposure_normalization); + RendererSceneRenderRD::get_singleton()->_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, render_albedo, render_emission, render_emission_aniso, render_geom_facing, p_exposure_normalization); if (cascade_next != cascade) { RD::get_singleton()->draw_command_begin_label("SDFGI Pre-Process Cascade"); @@ -2353,9 +2361,11 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_ } } -void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) { +void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result) { ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but... + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lights"); update_cascades(); @@ -2381,21 +2391,25 @@ void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderScen break; } - RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_positional_light_cull_result[i][j]); - ERR_CONTINUE(!li); + RID light_instance = p_positional_light_cull_result[i][j]; + ERR_CONTINUE(!light_storage->owns_light_instance(light_instance)); + + RID light = light_storage->light_instance_get_base_light(light_instance); + AABB light_aabb = light_storage->light_instance_get_base_aabb(light_instance); + Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance); - uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light); + uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(light); if (p_cascade_indices[i] > max_sdfgi_cascade) { continue; } - if (!cascade_aabb.intersects(li->aabb)) { + if (!cascade_aabb.intersects(light_aabb)) { continue; } - lights[idx].type = RSG::light_storage->light_get_type(li->light); + lights[idx].type = RSG::light_storage->light_get_type(light); - Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z); + Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z); if (lights[idx].type == RS::LIGHT_DIRECTIONAL) { dir.y *= y_mult; //only makes sense for directional dir.normalize(); @@ -2403,20 +2417,20 @@ void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderScen lights[idx].direction[0] = dir.x; lights[idx].direction[1] = dir.y; lights[idx].direction[2] = dir.z; - Vector3 pos = li->transform.origin; + Vector3 pos = light_transform.origin; pos.y *= y_mult; lights[idx].position[0] = pos.x; lights[idx].position[1] = pos.y; lights[idx].position[2] = pos.z; - Color color = RSG::light_storage->light_get_color(li->light); + Color color = RSG::light_storage->light_get_color(light); color = color.srgb_to_linear(); lights[idx].color[0] = color.r; lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; - lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); - if (p_scene_render->is_using_physical_light_units()) { - lights[idx].energy *= RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INTENSITY); + lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { + lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); // Convert from Luminous Power to Luminous Intensity if (lights[idx].type == RS::LIGHT_OMNI) { @@ -2432,11 +2446,11 @@ void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderScen lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); } - lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); - lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); - lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); - lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); - lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); + lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light); + lights[idx].attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); + lights[idx].radius = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE); + lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); + lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION); idx++; } @@ -2492,7 +2506,8 @@ void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderScen //////////////////////////////////////////////////////////////////////////////// // VoxelGIInstance -void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { +void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); uint32_t data_version = gi->voxel_gi_get_data_version(probe); @@ -2834,7 +2849,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID last_probe_data_version = data_version; p_update_light_instances = true; //just in case - p_scene_render->_base_uniforms_changed(); + RendererSceneRenderRD::get_singleton()->base_uniforms_changed(); } // UDPDATE TIME @@ -2857,7 +2872,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID for (uint32_t i = 0; i < light_count; i++) { VoxelGILight &l = gi->voxel_gi_lights[i]; RID light_instance = p_light_instances[i]; - RID light = p_scene_render->light_instance_get_base_light(light_instance); + RID light = light_storage->light_instance_get_base_light(light_instance); l.type = RSG::light_storage->light_get_type(light); if (l.type == RS::LIGHT_DIRECTIONAL && RSG::light_storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { @@ -2868,7 +2883,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID l.attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); l.energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); - if (p_scene_render->is_using_physical_light_units()) { + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { l.energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); l.energy *= gi->voxel_gi_get_baked_exposure_normalization(probe); @@ -2892,7 +2907,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID l.cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); l.inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION); - Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance); + Transform3D xform = light_storage->light_instance_get_base_transform(light_instance); Vector3 pos = to_probe_xform.xform(xform.origin); Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_column(2)).normalized(); @@ -3087,17 +3102,17 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID 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) { - p_scene_render->cull_argument.push_back(nullptr); + if (RendererSceneRenderRD::get_singleton()->cull_argument.size() == 0) { + RendererSceneRenderRD::get_singleton()->cull_argument.push_back(nullptr); } - p_scene_render->cull_argument[0] = instance; + RendererSceneRenderRD::get_singleton()->cull_argument[0] = instance; float exposure_normalization = 1.0; - if (p_scene_render->is_using_physical_light_units()) { + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { exposure_normalization = gi->voxel_gi_get_baked_exposure_normalization(probe); } - p_scene_render->_render_material(to_world_xform * xform, cm, true, p_scene_render->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size), exposure_normalization); + RendererSceneRenderRD::get_singleton()->_render_material(to_world_xform * xform, cm, true, RendererSceneRenderRD::get_singleton()->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size), exposure_normalization); VoxelGIDynamicPushConstant push_constant; memset(&push_constant, 0, sizeof(VoxelGIDynamicPushConstant)); @@ -3270,7 +3285,7 @@ void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, c for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { - push_constant.projection[i * 4 + j] = cam_transform.matrix[i][j]; + push_constant.projection[i * 4 + j] = cam_transform.columns[i][j]; } } @@ -3591,7 +3606,7 @@ Ref<GI::SDFGI> GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint return sdfgi; } -void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> 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 GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used) { ERR_FAIL_COND(p_render_buffers.is_null()); RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); @@ -3805,10 +3820,10 @@ void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_nor 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 / (internal_size.x * p_projections[0].matrix[0][0]); - push_constant.proj_info[1] = -2.0f / (internal_size.y * 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.proj_info[0] = -2.0f / (internal_size.x * p_projections[0].columns[0][0]); + push_constant.proj_info[1] = -2.0f / (internal_size.y * p_projections[0].columns[1][1]); + push_constant.proj_info[2] = (1.0f - p_projections[0].columns[0][2]) / p_projections[0].columns[0][0]; + push_constant.proj_info[3] = (1.0f + p_projections[0].columns[1][2]) / p_projections[0].columns[1][1]; bool use_sdfgi = p_render_buffers->has_custom_data(RB_SCOPE_SDFGI); bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0; @@ -4051,11 +4066,11 @@ bool GI::voxel_gi_needs_update(RID p_probe) const { return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe); } -void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { +void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_COND(!voxel_gi); - voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render); + voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects); } 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) { diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index e567c67a3b..2182ca6a20 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -145,7 +145,7 @@ public: Transform3D transform; - void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); + void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects); 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); void free_resources(); }; @@ -687,9 +687,9 @@ public: 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(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization); - void render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render); + void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data); + void render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, float p_exposure_normalization); + void render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result); }; RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16; @@ -812,13 +812,13 @@ public: Ref<SDFGI> create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); - void setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> 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 setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used); void process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, 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); 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<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects); 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); }; diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 307af99e91..4ff2a66975 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -268,7 +268,7 @@ bool SkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant 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->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL); + 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, true); } SkyRD::SkyMaterialData::~SkyMaterialData() { @@ -300,10 +300,10 @@ void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineC for (uint32_t v = 0; v < p_view_count; v++) { // We only need key components of our projection matrix - sky_push_constant.projections[v][0] = p_projections[v].matrix[2][0]; - sky_push_constant.projections[v][1] = p_projections[v].matrix[0][0]; - sky_push_constant.projections[v][2] = p_projections[v].matrix[2][1]; - sky_push_constant.projections[v][3] = p_projections[v].matrix[1][1]; + sky_push_constant.projections[v][0] = p_projections[v].columns[2][0]; + sky_push_constant.projections[v][1] = p_projections[v].columns[0][0]; + sky_push_constant.projections[v][2] = p_projections[v].columns[2][1]; + sky_push_constant.projections[v][3] = p_projections[v].columns[1][1]; } sky_push_constant.position[0] = p_position.x; sky_push_constant.position[1] = p_position.y; @@ -1200,18 +1200,17 @@ void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const P // This can't be done in RenderSceneRenderRD::_setup lights because that needs to be called // after the depth prepass, but this runs before the depth prepass for (int i = 0; i < (int)p_lights.size(); i++) { - RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_lights[i]); - if (!li) { + if (!light_storage->owns_light_instance(p_lights[i])) { continue; } - RID base = li->light; + RID base = light_storage->light_instance_get_base_light(p_lights[i]); ERR_CONTINUE(base.is_null()); RS::LightType type = light_storage->light_get_type(base); if (type == RS::LIGHT_DIRECTIONAL && light_storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) { SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count]; - Transform3D light_transform = li->transform; + Transform3D light_transform = light_storage->light_instance_get_base_transform(p_lights[i]); Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); sky_light_data.direction[0] = world_direction.x; 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 35953a7120..69d444aeeb 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -110,9 +110,29 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::free_data() { render_buffers->clear_context(RB_SCOPE_FORWARD_CLUSTERED); } + if (cluster_builder) { + memdelete(cluster_builder); + cluster_builder = nullptr; + } + if (!render_sdfgi_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_sdfgi_uniform_set)) { RD::get_singleton()->free(render_sdfgi_uniform_set); } + + if (ss_effects_data.linear_depth.is_valid()) { + RD::get_singleton()->free(ss_effects_data.linear_depth); + ss_effects_data.linear_depth = RID(); + ss_effects_data.linear_depth_slices.clear(); + } + + if (ss_effects_data.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects_data.downsample_uniform_set)) { + RD::get_singleton()->free(ss_effects_data.downsample_uniform_set); + ss_effects_data.downsample_uniform_set = RID(); + } + + RenderForwardClustered::get_singleton()->get_ss_effects()->ssao_free(ss_effects_data.ssao); + RenderForwardClustered::get_singleton()->get_ss_effects()->ssil_free(ss_effects_data.ssil); + RenderForwardClustered::get_singleton()->get_ss_effects()->ssr_free(ss_effects_data.ssr); } void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RenderSceneBuffersRD *p_render_buffers) { @@ -146,6 +166,14 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RenderS p_render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples); } + + if (cluster_builder == nullptr) { + cluster_builder = memnew(ClusterBuilderRD); + } + cluster_builder->set_shared(RenderForwardClustered::get_singleton()->get_cluster_builder_shared()); + + RID sampler = RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + cluster_builder->setup(p_render_buffers->get_internal_size(), p_render_buffers->get_max_cluster_elements(), p_render_buffers->get_depth_texture(), sampler, p_render_buffers->get_internal_texture()); } RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_only_fb() { @@ -276,7 +304,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p SceneState::PushConstant push_constant; - if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL) { + if constexpr (p_pass_mode == PASS_MODE_DEPTH_MATERIAL) { push_constant.uv_offset = Math::make_half_float(p_params->uv_offset.y) << 16; push_constant.uv_offset |= Math::make_half_float(p_params->uv_offset.x); } else { @@ -355,7 +383,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p uint32_t pipeline_color_pass_flags = 0; uint32_t pipeline_specialization = 0; - if (p_pass_mode == PASS_MODE_COLOR) { + if constexpr (p_pass_mode == PASS_MODE_COLOR) { if (element_info.uses_softshadow) { pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_SOFT_SHADOWS; } @@ -580,9 +608,11 @@ 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) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + Ref<RenderSceneBuffersRD> rd = p_render_data->render_buffers; RID env = is_environment(p_render_data->environment) ? p_render_data->environment : RID(); - RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID(); + RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID(); // May do this earlier in RenderSceneRenderRD::render_scene if (p_index >= (int)scene_state.uniform_buffers.size()) { @@ -714,6 +744,14 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i instance_data.lightmap_uv_scale[2] = inst->lightmap_uv_scale.size.x; instance_data.lightmap_uv_scale[3] = inst->lightmap_uv_scale.size.y; +#ifdef REAL_T_IS_DOUBLE + // Split the origin into two components, the float approximation and the missing precision + // In the shader we will combine these back together to restore the lost precision. + RendererRD::MaterialStorage::split_double(inst->transform.origin.x, &instance_data.transform[12], &instance_data.transform[3]); + RendererRD::MaterialStorage::split_double(inst->transform.origin.y, &instance_data.transform[13], &instance_data.transform[7]); + RendererRD::MaterialStorage::split_double(inst->transform.origin.z, &instance_data.transform[14], &instance_data.transform[11]); +#endif + bool cant_repeat = instance_data.flags & INSTANCE_DATA_FLAG_MULTIMESH || inst->mesh_instance.is_valid(); if (prev_surface != nullptr && !cant_repeat && prev_surface->sort.sort_key1 == surface->sort.sort_key1 && prev_surface->sort.sort_key2 == surface->sort.sort_key2 && repeats < RenderElementInfo::MAX_REPEATS) { @@ -1022,26 +1060,28 @@ void RenderForwardClustered::_setup_voxelgis(const PagedArray<RID> &p_voxelgis) } void RenderForwardClustered::_setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + scene_state.lightmaps_used = 0; for (int i = 0; i < (int)p_lightmaps.size(); i++) { if (i >= (int)scene_state.max_lightmaps) { break; } - RID lightmap = lightmap_instance_get_lightmap(p_lightmaps[i]); + RID lightmap = light_storage->lightmap_instance_get_lightmap(p_lightmaps[i]); - Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis; + Basis to_lm = light_storage->lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis; to_lm = to_lm.inverse().transposed(); //will transform normals RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform); scene_state.lightmaps[i].exposure_normalization = 1.0; if (p_render_data->camera_attributes.is_valid()) { - float baked_exposure = RendererRD::LightStorage::get_singleton()->lightmap_get_baked_exposure_normalization(lightmap); + float baked_exposure = light_storage->lightmap_get_baked_exposure_normalization(lightmap); float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); scene_state.lightmaps[i].exposure_normalization = enf / baked_exposure; } scene_state.lightmap_ids[i] = p_lightmaps[i]; - scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap); + scene_state.lightmap_has_sh[i] = light_storage->lightmap_uses_spherical_harmonics(lightmap); scene_state.lightmaps_used++; } @@ -1050,7 +1090,452 @@ void RenderForwardClustered::_setup_lightmaps(const RenderDataRD *p_render_data, } } +/* SDFGI */ + +void RenderForwardClustered::_update_sdfgi(RenderDataRD *p_render_data) { + Ref<RenderSceneBuffersRD> rb; + if (p_render_data && p_render_data->render_buffers.is_valid()) { + rb = p_render_data->render_buffers; + } + + if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_SDFGI)) { + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + float exposure_normalization = 1.0; + + if (p_render_data->camera_attributes.is_valid()) { + exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); + } + for (int i = 0; i < p_render_data->render_sdfgi_region_count; i++) { + sdfgi->render_region(rb, p_render_data->render_sdfgi_regions[i].region, p_render_data->render_sdfgi_regions[i].instances, exposure_normalization); + } + if (p_render_data->sdfgi_update_data->update_static) { + sdfgi->render_static_lights(p_render_data, rb, p_render_data->sdfgi_update_data->static_cascade_count, p_render_data->sdfgi_update_data->static_cascade_indices, p_render_data->sdfgi_update_data->static_positional_lights); + } + } +} + +/* Debug */ + +void RenderForwardClustered::_debug_draw_cluster(Ref<RenderSceneBuffersRD> p_render_buffers) { + if (p_render_buffers.is_valid() && current_cluster_builder != nullptr) { + RS::ViewportDebugDraw dd = get_debug_draw_mode(); + + if (dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) { + ClusterBuilderRD::ElementType elem_type = ClusterBuilderRD::ELEMENT_TYPE_MAX; + switch (dd) { + case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS: + elem_type = ClusterBuilderRD::ELEMENT_TYPE_OMNI_LIGHT; + break; + case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS: + elem_type = ClusterBuilderRD::ELEMENT_TYPE_SPOT_LIGHT; + break; + case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS: + elem_type = ClusterBuilderRD::ELEMENT_TYPE_DECAL; + break; + case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES: + elem_type = ClusterBuilderRD::ELEMENT_TYPE_REFLECTION_PROBE; + break; + default: { + } + } + current_cluster_builder->debug(elem_type); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// FOG SHADER + +void RenderForwardClustered::_update_volumetric_fog(Ref<RenderSceneBuffersRD> 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(p_render_buffers.is_null()); + + Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); + + ERR_FAIL_COND(!p_render_buffers->has_custom_data(RB_SCOPE_GI)); + Ref<RendererRD::GI::RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI); + + Ref<RendererRD::GI::SDFGI> sdfgi; + if (p_render_buffers->has_custom_data(RB_SCOPE_SDFGI)) { + sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI); + } + + Size2i size = p_render_buffers->get_internal_size(); + float ratio = float(size.x) / float((size.x + size.y) / 2); + uint32_t target_width = uint32_t(float(get_volumetric_fog_size()) * ratio); + uint32_t target_height = uint32_t(float(get_volumetric_fog_size()) / ratio); + + if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { + Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); + //validate + if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment) || fog->width != target_width || fog->height != target_height || fog->depth != get_volumetric_fog_depth()) { + p_render_buffers->set_custom_data(RB_SCOPE_FOG, Ref<RenderBufferCustomDataRD>()); + } + } + + if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment)) { + //no reason to enable or update, bye + return; + } + + if (p_environment.is_valid() && environment_get_volumetric_fog_enabled(p_environment) && !p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { + //required volumetric fog but not existing, create + Ref<RendererRD::Fog::VolumetricFog> fog; + + fog.instantiate(); + fog->init(Vector3i(target_width, target_height, get_volumetric_fog_depth()), sky.sky_shader.default_shader_rd); + + p_render_buffers->set_custom_data(RB_SCOPE_FOG, fog); + } + + if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { + Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); + + RendererRD::Fog::VolumetricFogSettings settings; + settings.rb_size = size; + settings.time = time; + settings.is_using_radiance_cubemap_array = is_using_radiance_cubemap_array(); + settings.max_cluster_elements = RendererRD::LightStorage::get_singleton()->get_max_cluster_elements(); + settings.volumetric_fog_filter_active = get_volumetric_fog_filter_active(); + + settings.shadow_sampler = shadow_sampler; + settings.shadow_atlas_depth = RendererRD::LightStorage::get_singleton()->owns_shadow_atlas(p_shadow_atlas) ? RendererRD::LightStorage::get_singleton()->shadow_atlas_get_texture(p_shadow_atlas) : RID(); + settings.voxel_gi_buffer = rbgi->get_voxel_gi_buffer(); + settings.omni_light_buffer = RendererRD::LightStorage::get_singleton()->get_omni_light_buffer(); + settings.spot_light_buffer = RendererRD::LightStorage::get_singleton()->get_spot_light_buffer(); + settings.directional_shadow_depth = RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture(); + settings.directional_light_buffer = RendererRD::LightStorage::get_singleton()->get_directional_light_buffer(); + + settings.vfog = fog; + settings.cluster_builder = rb_data->cluster_builder; + settings.rbgi = rbgi; + settings.sdfgi = sdfgi; + settings.env = p_environment; + settings.sky = &sky; + settings.gi = &gi; + + 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); + } +} + +/* Lighting */ + +void RenderForwardClustered::setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents) { + if (current_cluster_builder != nullptr) { + current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, p_transform, p_half_extents); + } +} + +void RenderForwardClustered::setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) { + if (current_cluster_builder != nullptr) { + current_cluster_builder->add_light(p_type == RS::LIGHT_SPOT ? ClusterBuilderRD::LIGHT_TYPE_SPOT : ClusterBuilderRD::LIGHT_TYPE_OMNI, p_transform, p_radius, p_spot_aperture); + } +} + +void RenderForwardClustered::setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents) { + if (current_cluster_builder != nullptr) { + current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, p_transform, p_half_extents); + } +} + +/* Render scene */ + +void RenderForwardClustered::_process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection) { + ERR_FAIL_NULL(ss_effects); + ERR_FAIL_COND(p_render_buffers.is_null()); + ERR_FAIL_COND(p_environment.is_null()); + + Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); + ERR_FAIL_COND(rb_data.is_null()); + + RENDER_TIMESTAMP("Process SSAO"); + + RendererRD::SSEffects::SSAOSettings settings; + settings.radius = environment_get_ssao_radius(p_environment); + settings.intensity = environment_get_ssao_intensity(p_environment); + settings.power = environment_get_ssao_power(p_environment); + settings.detail = environment_get_ssao_detail(p_environment); + settings.horizon = environment_get_ssao_horizon(p_environment); + settings.sharpness = environment_get_ssao_sharpness(p_environment); + settings.full_screen_size = p_render_buffers->get_internal_size(); + + ss_effects->ssao_allocate_buffers(rb_data->ss_effects_data.ssao, settings, rb_data->ss_effects_data.linear_depth); + ss_effects->generate_ssao(rb_data->ss_effects_data.ssao, p_normal_buffer, p_projection, settings); +} + +void RenderForwardClustered::_process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform) { + ERR_FAIL_NULL(ss_effects); + ERR_FAIL_COND(p_render_buffers.is_null()); + ERR_FAIL_COND(p_environment.is_null()); + + Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); + ERR_FAIL_COND(rb_data.is_null()); + + RENDER_TIMESTAMP("Process SSIL"); + + RendererRD::SSEffects::SSILSettings settings; + settings.radius = environment_get_ssil_radius(p_environment); + settings.intensity = environment_get_ssil_intensity(p_environment); + settings.sharpness = environment_get_ssil_sharpness(p_environment); + settings.normal_rejection = environment_get_ssil_normal_rejection(p_environment); + settings.full_screen_size = p_render_buffers->get_internal_size(); + + Projection correction; + correction.set_depth_correction(true); + Projection projection = correction * p_projection; + Transform3D transform = p_transform; + transform.set_origin(Vector3(0.0, 0.0, 0.0)); + Projection last_frame_projection = rb_data->ss_effects_data.last_frame_projection * Projection(rb_data->ss_effects_data.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse(); + + ss_effects->ssil_allocate_buffers(rb_data->ss_effects_data.ssil, settings, rb_data->ss_effects_data.linear_depth); + ss_effects->screen_space_indirect_lighting(rb_data->ss_effects_data.ssil, p_normal_buffer, p_projection, last_frame_projection, settings); + rb_data->ss_effects_data.last_frame_projection = projection; + rb_data->ss_effects_data.last_frame_transform = transform; +} + +void RenderForwardClustered::_copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers) { + ERR_FAIL_COND(p_render_buffers.is_null()); + + Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); + ERR_FAIL_COND(rb_data.is_null()); + + if (rb_data->ss_effects_data.ssil.last_frame.is_valid()) { + Size2i size = p_render_buffers->get_internal_size(); + RID texture = p_render_buffers->get_internal_texture(); + copy_effects->copy_to_rect(texture, rb_data->ss_effects_data.ssil.last_frame, Rect2i(0, 0, size.x, size.y)); + + int width = size.x; + int height = size.y; + for (int i = 0; i < rb_data->ss_effects_data.ssil.last_frame_slices.size() - 1; i++) { + width = MAX(1, width >> 1); + height = MAX(1, height >> 1); + copy_effects->make_mipmap(rb_data->ss_effects_data.ssil.last_frame_slices[i], rb_data->ss_effects_data.ssil.last_frame_slices[i + 1], Size2i(width, height)); + } + } +} + +void RenderForwardClustered::_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) { + // 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(); + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; + Ref<RenderBufferDataForwardClustered> rb_data; + if (rb.is_valid()) { + rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); + } + + if (rb.is_valid() && p_use_gi && rb->has_custom_data(RB_SCOPE_SDFGI)) { + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + sdfgi->store_probes(); + } + + p_render_data->cube_shadows.clear(); + p_render_data->shadows.clear(); + p_render_data->directional_shadows.clear(); + + Plane camera_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin); + float lod_distance_multiplier = p_render_data->scene_data->cam_projection.get_lod_multiplier(); + { + for (int i = 0; i < p_render_data->render_shadow_count; i++) { + RID li = p_render_data->render_shadows[i].light; + RID base = light_storage->light_instance_get_base_light(li); + + if (light_storage->light_get_type(base) == RS::LIGHT_DIRECTIONAL) { + p_render_data->directional_shadows.push_back(i); + } else if (light_storage->light_get_type(base) == RS::LIGHT_OMNI && light_storage->light_omni_get_shadow_mode(base) == RS::LIGHT_OMNI_SHADOW_CUBE) { + p_render_data->cube_shadows.push_back(i); + } else { + p_render_data->shadows.push_back(i); + } + } + + //cube shadows are rendered in their own way + for (uint32_t i = 0; i < p_render_data->cube_shadows.size(); i++) { + _render_shadow_pass(p_render_data->render_shadows[p_render_data->cube_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->cube_shadows[i]].pass, p_render_data->render_shadows[p_render_data->cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info); + } + + if (p_render_data->directional_shadows.size()) { + //open the pass for directional shadows + light_storage->update_directional_shadow_atlas(); + RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE); + RD::get_singleton()->draw_list_end(); + } + } + + // Render GI + + bool render_shadows = p_render_data->directional_shadows.size() || p_render_data->shadows.size(); + bool render_gi = rb.is_valid() && p_use_gi; + + if (render_shadows && render_gi) { + RENDER_TIMESTAMP("Render GI + Render Shadows (Parallel)"); + } else if (render_shadows) { + RENDER_TIMESTAMP("Render Shadows"); + } else if (render_gi) { + RENDER_TIMESTAMP("Render GI"); + } + + //prepare shadow rendering + if (render_shadows) { + _render_shadow_begin(); + + //render directional shadows + for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) { + _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info); + } + //render positional shadows + for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) { + _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info); + } + + _render_shadow_process(); + } + + //start GI + if (render_gi) { + gi.process_gi(rb, p_normal_roughness_slices, p_voxel_gi_buffer, p_render_data->environment, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances); + } + + //Do shadow rendering (in parallel with GI) + if (render_shadows) { + _render_shadow_end(RD::BARRIER_MASK_NO_BARRIER); + } + + if (render_gi) { + RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //use a later barrier + } + + if (rb_data.is_valid() && ss_effects) { + if (p_use_ssao || p_use_ssil) { + Size2i size = rb->get_internal_size(); + + bool invalidate_uniform_set = false; + if (rb_data->ss_effects_data.linear_depth.is_null()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16_SFLOAT; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = (size.x + 1) / 2; + tf.height = (size.y + 1) / 2; + tf.mipmaps = 5; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + rb_data->ss_effects_data.linear_depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(rb_data->ss_effects_data.linear_depth, "SS Effects Depth"); + for (uint32_t i = 0; i < tf.mipmaps; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb_data->ss_effects_data.linear_depth, 0, i, 1, RD::TEXTURE_SLICE_2D_ARRAY); + rb_data->ss_effects_data.linear_depth_slices.push_back(slice); + RD::get_singleton()->set_resource_name(slice, "SS Effects Depth Mip " + itos(i) + " "); + } + invalidate_uniform_set = true; + } + + RID depth_texture = rb->get_depth_texture(); + ss_effects->downsample_depth(depth_texture, rb_data->ss_effects_data.linear_depth_slices, invalidate_uniform_set, size, p_render_data->scene_data->cam_projection); + } + + if (p_use_ssao) { + // TODO make these proper stereo + _process_ssao(rb, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection); + } + + if (p_use_ssil) { + // TODO make these proper stereo + _process_ssil(rb, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform); + } + } + + //full barrier here, we need raster, transfer and compute and it depends from the previous work + RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL); + + if (current_cluster_builder) { + current_cluster_builder->begin(p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, !p_render_data->reflection_probe.is_valid()); + } + + bool using_shadows = true; + + if (p_render_data->reflection_probe.is_valid()) { + if (!RSG::light_storage->reflection_probe_renders_shadows(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { + using_shadows = false; + } + } else { + //do not render reflections when rendering a reflection probe + light_storage->update_reflection_probe_buffer(p_render_data, *p_render_data->reflection_probes, p_render_data->scene_data->cam_transform.affine_inverse(), p_render_data->environment); + } + + uint32_t directional_light_count = 0; + uint32_t positional_light_count = 0; + light_storage->update_light_buffers(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows); + texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform.affine_inverse()); + + p_render_data->directional_light_count = directional_light_count; + + if (current_cluster_builder) { + current_cluster_builder->bake_cluster(); + } + + if (rb.is_valid()) { + bool directional_shadows = RendererRD::LightStorage::get_singleton()->has_directional_shadows(directional_light_count); + _update_volumetric_fog(rb, p_render_data->environment, p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform, p_render_data->scene_data->prev_cam_transform.affine_inverse(), p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, p_render_data->voxel_gi_count, *p_render_data->fog_volumes); + } +} + +void RenderForwardClustered::_process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive) { + ERR_FAIL_NULL(ss_effects); + ERR_FAIL_COND(p_render_buffers.is_null()); + + Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); + ERR_FAIL_COND(rb_data.is_null()); + + Size2i internal_size = p_render_buffers->get_internal_size(); + bool can_use_effects = internal_size.x >= 8 && internal_size.y >= 8; + uint32_t view_count = p_render_buffers->get_view_count(); + + if (!can_use_effects) { + //just copy + copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), RID(), view_count); + return; + } + + ERR_FAIL_COND(p_environment.is_null()); + ERR_FAIL_COND(!environment_get_ssr_enabled(p_environment)); + + Size2i half_size = Size2i(internal_size.x / 2, internal_size.y / 2); + if (rb_data->ss_effects_data.ssr.output.is_null()) { + ss_effects->ssr_allocate_buffers(rb_data->ss_effects_data.ssr, _render_buffers_get_color_format(), half_size, view_count); + } + RID texture_slices[RendererSceneRender::MAX_RENDER_VIEWS]; + RID depth_slices[RendererSceneRender::MAX_RENDER_VIEWS]; + for (uint32_t v = 0; v < view_count; v++) { + texture_slices[v] = p_render_buffers->get_internal_texture(v); + depth_slices[v] = p_render_buffers->get_depth_texture(v); + } + ss_effects->screen_space_reflection(rb_data->ss_effects_data.ssr, texture_slices, p_normal_slices, p_metallic_slices, depth_slices, half_size, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), view_count, p_projections, p_eye_offsets); + copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), rb_data->ss_effects_data.ssr.output, view_count); +} + +void RenderForwardClustered::_process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera) { + ERR_FAIL_COND(p_render_buffers.is_null()); + + Size2i internal_size = p_render_buffers->get_internal_size(); + bool can_use_effects = internal_size.x >= 8 && internal_size.y >= 8; + + if (!can_use_effects) { + //just copy + return; + } + + p_render_buffers->allocate_blur_textures(); + + for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) { + RID internal_texture = p_render_buffers->get_internal_texture(v); + RID depth_texture = p_render_buffers->get_depth_texture(v); + ss_effects->sub_surface_scattering(p_render_buffers, internal_texture, depth_texture, p_camera, internal_size); + } +} + void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + Ref<RenderSceneBuffersRD> rb; Ref<RenderBufferDataForwardClustered> rb_data; if (p_render_data && p_render_data->render_buffers.is_valid()) { @@ -1062,6 +1547,54 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co //first of all, make a new render pass //fill up ubo + RENDER_TIMESTAMP("Prepare 3D Scene"); + + // sdfgi first + _update_sdfgi(p_render_data); + + // assign render indices to voxel_gi_instances + for (uint32_t i = 0; i < (uint32_t)p_render_data->voxel_gi_instances->size(); i++) { + RID voxel_gi_instance = (*p_render_data->voxel_gi_instances)[i]; + gi.voxel_gi_instance_set_render_index(voxel_gi_instance, i); + } + + // obtain cluster builder + if (rb_data.is_valid()) { + current_cluster_builder = rb_data->cluster_builder; + } else if (light_storage->owns_reflection_probe_instance(p_render_data->reflection_probe)) { + current_cluster_builder = light_storage->reflection_probe_instance_get_cluster_builder(p_render_data->reflection_probe, &cluster_builder_shared); + + if (p_render_data->camera_attributes.is_valid()) { + light_storage->reflection_probe_set_baked_exposure(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe), RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes)); + } + } else { + ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash + current_cluster_builder = nullptr; + } + + p_render_data->voxel_gi_count = 0; + + if (rb.is_valid()) { + if (rb->has_custom_data(RB_SCOPE_SDFGI)) { + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + if (sdfgi.is_valid()) { + sdfgi->update_cascades(); + sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data); + sdfgi->update_light(); + } + } + + gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count); + } + + if (current_cluster_builder != nullptr) { + p_render_data->cluster_buffer = current_cluster_builder->get_cluster_buffer(); + p_render_data->cluster_size = current_cluster_builder->get_cluster_size(); + p_render_data->cluster_max_elements = current_cluster_builder->get_max_cluster_elements(); + } + + _update_vrs(rb); + RENDER_TIMESTAMP("Setup 3D Scene"); // check if we need motion vectors @@ -1145,15 +1678,15 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags); color_only_framebuffer = rb_data->get_color_only_fb(); } else if (p_render_data->reflection_probe.is_valid()) { - uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe); + uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); screen_size.x = resolution; screen_size.y = resolution; - color_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + color_framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); color_only_framebuffer = color_framebuffer; - depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + depth_framebuffer = light_storage->reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); - if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { + if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { p_render_data->environment = RID(); //no environment on interiors } @@ -1180,7 +1713,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_end_label(); - bool using_sss = rb_data.is_valid() && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; + bool using_sss = rb_data.is_valid() && scene_state.used_sss && ss_effects->sss_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; if (using_sss && !using_separate_specular) { using_separate_specular = true; @@ -1530,6 +2063,229 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _render_buffers_post_process_and_tonemap(p_render_data); } + + if (rb.is_valid()) { + _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex); + + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb->has_custom_data(RB_SCOPE_SDFGI)) { + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + Vector<RID> view_rids; + + // SDFGI renders at internal resolution, need to check if our debug correctly supports outputting upscaled. + Size2i size = rb->get_internal_size(); + RID source_texture = rb->get_internal_texture(); + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + view_rids.push_back(rb->get_internal_texture(v)); + } + + sdfgi->debug_draw(p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, size.x, size.y, rb->get_render_target(), source_texture, view_rids); + } + } +} + +void RenderForwardClustered::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + ERR_FAIL_COND(p_render_buffers.is_null()); + + Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); + ERR_FAIL_COND(rb_data.is_null()); + + RendererSceneRenderRD::_render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occlusion_buffer); + + RID render_target = p_render_buffers->get_render_target(); + + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb_data->ss_effects_data.ssao.ao_final.is_valid()) { + Size2i rtsize = texture_storage->render_target_get_size(render_target); + copy_effects->copy_to_fb_rect(rb_data->ss_effects_data.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, true); + } + + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb_data->ss_effects_data.ssil.ssil_final.is_valid()) { + Size2i rtsize = texture_storage->render_target_get_size(render_target); + copy_effects->copy_to_fb_rect(rb_data->ss_effects_data.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); + } + + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) { + Size2i rtsize = texture_storage->render_target_get_size(render_target); + RID ambient_texture = p_render_buffers->get_texture(RB_SCOPE_GI, RB_TEX_AMBIENT); + RID reflection_texture = p_render_buffers->get_texture(RB_SCOPE_GI, RB_TEX_REFLECTION); + copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture, p_render_buffers->get_view_count() > 1); + } +} + +void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + + ERR_FAIL_COND(!light_storage->owns_light_instance(p_light)); + + RID base = light_storage->light_instance_get_base_light(p_light); + + Rect2i atlas_rect; + uint32_t atlas_size = 1; + RID atlas_fb; + + bool using_dual_paraboloid = false; + bool using_dual_paraboloid_flip = false; + Vector2i dual_paraboloid_offset; + RID render_fb; + RID render_texture; + float zfar; + + bool use_pancake = false; + bool render_cubemap = false; + bool finalize_cubemap = false; + + bool flip_y = false; + + Projection light_projection; + Transform3D light_transform; + + if (light_storage->light_get_type(base) == RS::LIGHT_DIRECTIONAL) { + //set pssm stuff + uint64_t last_scene_shadow_pass = light_storage->light_instance_get_shadow_pass(p_light); + if (last_scene_shadow_pass != get_scene_pass()) { + light_storage->light_instance_set_directional_rect(p_light, light_storage->get_directional_shadow_rect()); + light_storage->directional_shadow_increase_current_light(); + light_storage->light_instance_set_shadow_pass(p_light, get_scene_pass()); + } + + use_pancake = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0; + light_projection = light_storage->light_instance_get_shadow_camera(p_light, p_pass); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, p_pass); + + atlas_rect = light_storage->light_instance_get_directional_rect(p_light); + + if (light_storage->light_directional_get_shadow_mode(base) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + atlas_rect.size.width /= 2; + atlas_rect.size.height /= 2; + + if (p_pass == 1) { + atlas_rect.position.x += atlas_rect.size.width; + } else if (p_pass == 2) { + atlas_rect.position.y += atlas_rect.size.height; + } else if (p_pass == 3) { + atlas_rect.position += atlas_rect.size; + } + } else if (light_storage->light_directional_get_shadow_mode(base) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { + atlas_rect.size.height /= 2; + + if (p_pass == 0) { + } else { + atlas_rect.position.y += atlas_rect.size.height; + } + } + + float directional_shadow_size = light_storage->directional_shadow_get_size(); + Rect2 atlas_rect_norm = atlas_rect; + atlas_rect_norm.position /= directional_shadow_size; + atlas_rect_norm.size /= directional_shadow_size; + light_storage->light_instance_set_directional_shadow_atlas_rect(p_light, p_pass, atlas_rect_norm); + + zfar = RSG::light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE); + + render_fb = light_storage->direction_shadow_get_fb(); + render_texture = RID(); + flip_y = true; + + } else { + //set from shadow atlas + + ERR_FAIL_COND(!light_storage->owns_shadow_atlas(p_shadow_atlas)); + ERR_FAIL_COND(!light_storage->shadow_atlas_owns_light_instance(p_shadow_atlas, p_light)); + + RSG::light_storage->shadow_atlas_update(p_shadow_atlas); + + uint32_t key = light_storage->shadow_atlas_get_light_instance_key(p_shadow_atlas, p_light); + + uint32_t quadrant = (key >> RendererRD::LightStorage::QUADRANT_SHIFT) & 0x3; + uint32_t shadow = key & RendererRD::LightStorage::SHADOW_INDEX_MASK; + uint32_t subdivision = light_storage->shadow_atlas_get_quadrant_subdivision(p_shadow_atlas, quadrant); + + ERR_FAIL_INDEX((int)shadow, light_storage->shadow_atlas_get_quadrant_shadow_size(p_shadow_atlas, quadrant)); + + uint32_t shadow_atlas_size = light_storage->shadow_atlas_get_size(p_shadow_atlas); + uint32_t quadrant_size = shadow_atlas_size >> 1; + + atlas_rect.position.x = (quadrant & 1) * quadrant_size; + atlas_rect.position.y = (quadrant >> 1) * quadrant_size; + + uint32_t shadow_size = (quadrant_size / subdivision); + atlas_rect.position.x += (shadow % subdivision) * shadow_size; + atlas_rect.position.y += (shadow / subdivision) * shadow_size; + + atlas_rect.size.width = shadow_size; + atlas_rect.size.height = shadow_size; + + zfar = light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE); + + if (light_storage->light_get_type(base) == RS::LIGHT_OMNI) { + bool wrap = (shadow + 1) % subdivision == 0; + dual_paraboloid_offset = wrap ? Vector2i(1 - subdivision, 1) : Vector2i(1, 0); + + if (light_storage->light_omni_get_shadow_mode(base) == RS::LIGHT_OMNI_SHADOW_CUBE) { + render_texture = light_storage->get_cubemap(shadow_size / 2); + render_fb = light_storage->get_cubemap_fb(shadow_size / 2, p_pass); + + light_projection = light_storage->light_instance_get_shadow_camera(p_light, p_pass); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, p_pass); + render_cubemap = true; + finalize_cubemap = p_pass == 5; + atlas_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas); + + atlas_size = shadow_atlas_size; + + if (p_pass == 0) { + _render_shadow_begin(); + } + + } else { + atlas_rect.position.x += 1; + atlas_rect.position.y += 1; + atlas_rect.size.x -= 2; + atlas_rect.size.y -= 2; + + atlas_rect.position += p_pass * atlas_rect.size * dual_paraboloid_offset; + + light_projection = light_storage->light_instance_get_shadow_camera(p_light, 0); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, 0); + + using_dual_paraboloid = true; + using_dual_paraboloid_flip = p_pass == 1; + render_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas); + flip_y = true; + } + + } else if (light_storage->light_get_type(base) == RS::LIGHT_SPOT) { + light_projection = light_storage->light_instance_get_shadow_camera(p_light, 0); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, 0); + + render_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas); + + flip_y = true; + } + } + + if (render_cubemap) { + //rendering to cubemap + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info); + if (finalize_cubemap) { + _render_shadow_process(); + _render_shadow_end(); + //reblit + Rect2 atlas_rect_norm = atlas_rect; + atlas_rect_norm.position /= float(atlas_size); + atlas_rect_norm.size /= float(atlas_size); + 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(), false); + atlas_rect_norm.position += Vector2(dual_paraboloid_offset) * atlas_rect_norm.size; + 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_storage->light_instance_set_shadow_transform(p_light, Projection(), light_storage->light_instance_get_base_transform(p_light), zfar, 0, 0, 0); + } + + } else { + //render shadow + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info); + } } void RenderForwardClustered::_render_shadow_begin() { @@ -1886,7 +2642,7 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu RD::get_singleton()->draw_command_end_label(); } -void RenderForwardClustered::_base_uniforms_changed() { +void RenderForwardClustered::base_uniforms_changed() { if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); } @@ -2002,14 +2758,14 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_omni_light_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_omni_light_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_spot_light_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_spot_light_buffer()); uniforms.push_back(u); } @@ -2017,14 +2773,14 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_reflection_probe_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_reflection_probe_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.append_id(get_directional_light_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_directional_light_buffer()); uniforms.push_back(u); } { @@ -2061,7 +2817,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_decal_buffer()); + u.append_id(RendererRD::TextureStorage::get_singleton()->get_decal_buffer()); uniforms.push_back(u); } @@ -2139,7 +2895,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend uniforms.push_back(u); } { - RID ref_texture = (p_render_data && p_render_data->reflection_atlas.is_valid()) ? reflection_atlas_get_texture(p_render_data->reflection_atlas) : RID(); + RID ref_texture = (p_render_data && p_render_data->reflection_atlas.is_valid()) ? light_storage->reflection_atlas_get_texture(p_render_data->reflection_atlas) : RID(); RD::Uniform u; u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -2156,7 +2912,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID texture; if (p_render_data && p_render_data->shadow_atlas.is_valid()) { - texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); + texture = RendererRD::LightStorage::get_singleton()->shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); @@ -2168,8 +2924,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { - u.append_id(directional_shadow_get_texture()); + if (p_use_directional_shadow_atlas && RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture().is_valid()) { + u.append_id(RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture()); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH)); } @@ -2183,7 +2939,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { - RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); + RID base = light_storage->lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); RID texture = light_storage->lightmap_get_texture(base); RID rd_texture = texture_storage->texture_get_rd_texture(texture); u.append_id(rd_texture); @@ -2259,7 +3015,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID aot = rb_data.is_valid() ? rb->get_ao_texture() : RID(); + RID aot = rb_data.is_valid() ? rb_data->get_ao_texture() : RID(); RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); @@ -2345,7 +3101,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 20; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID ssil = rb_data.is_valid() ? rb->get_ssil_texture() : RID(); + RID ssil = rb_data.is_valid() ? rb_data->get_ssil_texture() : RID(); RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); @@ -2504,6 +3260,26 @@ RID RenderForwardClustered::_render_buffers_get_velocity_texture(Ref<RenderScene return p_render_buffers->get_velocity_buffer(p_render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED); } +void RenderForwardClustered::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { + ss_effects->ssao_set_quality(p_quality, p_half_size, p_adaptive_target, p_blur_passes, p_fadeout_from, p_fadeout_to); +} + +void RenderForwardClustered::environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { + ss_effects->ssil_set_quality(p_quality, p_half_size, p_adaptive_target, p_blur_passes, p_fadeout_from, p_fadeout_to); +} + +void RenderForwardClustered::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) { + ss_effects->ssr_set_roughness_quality(p_quality); +} + +void RenderForwardClustered::sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) { + ss_effects->sss_set_quality(p_quality); +} + +void RenderForwardClustered::sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) { + ss_effects->sss_set_scale(p_scale, p_depth_scale); +} + RenderForwardClustered *RenderForwardClustered::singleton = nullptr; void RenderForwardClustered::GeometryInstanceForwardClustered::_mark_dirty() { @@ -2823,7 +3599,7 @@ void RenderForwardClustered::_geometry_instance_update(RenderGeometryInstance *p ginstance->store_transform_cache = store_transform; ginstance->can_sdfgi = false; - if (!lightmap_instance_is_valid(ginstance->lightmap_instance)) { + if (!RendererRD::LightStorage::get_singleton()->lightmap_instance_is_valid(ginstance->lightmap_instance)) { if (ginstance->voxel_gi_instances[0].is_null() && (ginstance->data->use_baked_light || ginstance->data->use_dynamic_gi)) { ginstance->can_sdfgi = true; } @@ -3005,7 +3781,7 @@ void RenderForwardClustered::_update_shader_quality_settings() { scene_shader.set_default_specialization_constants(spec_constants); - _base_uniforms_changed(); //also need this + base_uniforms_changed(); //also need this } RenderForwardClustered::RenderForwardClustered() { @@ -3039,19 +3815,40 @@ RenderForwardClustered::RenderForwardClustered() { { defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n"; } +#ifdef REAL_T_IS_DOUBLE + { + defines += "\n#define USE_DOUBLE_PRECISION \n"; + } +#endif scene_shader.init(defines); } + /* shadow sampler */ + { + RD::SamplerState sampler; + sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler.min_filter = RD::SAMPLER_FILTER_NEAREST; + sampler.enable_compare = true; + sampler.compare_op = RD::COMPARE_OP_LESS; + shadow_sampler = RD::get_singleton()->sampler_create(sampler); + } + render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances"); _update_shader_quality_settings(); resolve_effects = memnew(RendererRD::Resolve()); taa = memnew(RendererRD::TAA); + ss_effects = memnew(RendererRD::SSEffects); } RenderForwardClustered::~RenderForwardClustered() { + if (ss_effects != nullptr) { + memdelete(ss_effects); + ss_effects = nullptr; + } + if (taa != nullptr) { memdelete(taa); taa = nullptr; @@ -3062,7 +3859,8 @@ RenderForwardClustered::~RenderForwardClustered() { resolve_effects = nullptr; } - directional_shadow_atlas_set_size(0); + RD::get_singleton()->free(shadow_sampler); + RSG::light_storage->directional_shadow_atlas_set_size(0); { for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) { 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 cde241f231..55f1ef01af 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -32,7 +32,9 @@ #define RENDER_FORWARD_CLUSTERED_H #include "core/templates/paged_allocator.h" +#include "servers/rendering/renderer_rd/cluster_builder_rd.h" #include "servers/rendering/renderer_rd/effects/resolve.h" +#include "servers/rendering/renderer_rd/effects/ss_effects.h" #include "servers/rendering/renderer_rd/effects/taa.h" #include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" @@ -99,7 +101,21 @@ class RenderForwardClustered : public RendererSceneRenderRD { RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1; public: - //for rendering, may be MSAAd + ClusterBuilderRD *cluster_builder = nullptr; + + struct SSEffectsData { + RID linear_depth; + Vector<RID> linear_depth_slices; + + RID downsample_uniform_set; + + Projection last_frame_projection; + Transform3D last_frame_transform; + + RendererRD::SSEffects::SSAORenderBuffers ssao; + RendererRD::SSEffects::SSILRenderBuffers ssil; + RendererRD::SSEffects::SSRRenderBuffers ssr; + } ss_effects_data; enum DepthFrameBufferType { DEPTH_FB, @@ -139,6 +155,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID get_depth_fb(DepthFrameBufferType p_type = DEPTH_FB); RID get_specular_only_fb(); + RID get_ao_texture() const { return ss_effects_data.ssao.ao_final; } + RID get_ssil_texture() const { return ss_effects_data.ssil.ssil_final; } + virtual void configure(RenderSceneBuffersRD *p_render_buffers) override; virtual void free_data() override; }; @@ -149,10 +168,6 @@ class RenderForwardClustered : public RendererSceneRenderRD { uint64_t lightmap_texture_array_version = 0xFFFFFFFF; - virtual void _base_uniforms_changed() override; - virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; - virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; - bool base_uniform_set_updated = false; void _update_render_base_uniform_set(); RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture); @@ -230,6 +245,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { float sh[9 * 4]; }; + // When changing any of these enums, remember to change the corresponding enums in the shader files as well. enum { INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4, INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5, @@ -557,16 +573,61 @@ class RenderForwardClustered : public RendererSceneRenderRD { virtual void _update_shader_quality_settings() override; + /* Effects */ + RendererRD::Resolve *resolve_effects = nullptr; RendererRD::TAA *taa = nullptr; + RendererRD::SSEffects *ss_effects = nullptr; + + /* Cluster builder */ + + ClusterBuilderSharedDataRD cluster_builder_shared; + ClusterBuilderRD *current_cluster_builder = nullptr; + + /* SDFGI */ + void _update_sdfgi(RenderDataRD *p_render_data); + + /* Volumetric fog */ + RID shadow_sampler; + + void _update_volumetric_fog(Ref<RenderSceneBuffersRD> 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); + + /* Render shadows */ + + void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &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, RenderingMethod::RenderInfo *p_render_info = nullptr); + void _render_shadow_begin(); + void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &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, RenderingMethod::RenderInfo *p_render_info = nullptr); + void _render_shadow_process(); + void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL); + + /* Render Scene */ + void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection); + void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform); + void _copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers); + 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); + void _process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive); + void _process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera); + + /* Debug */ + void _debug_draw_cluster(Ref<RenderSceneBuffersRD> p_render_buffers); protected: - virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; + /* setup */ + + virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; + virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; + + virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; + virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; + virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override; - virtual void _render_shadow_begin() override; - virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &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, RenderingMethod::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 sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override; + virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override; + + /* Rendering */ + + virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; + virtual void _render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) override; virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override; virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; @@ -576,6 +637,15 @@ protected: public: static RenderForwardClustered *get_singleton() { return singleton; } + ClusterBuilderSharedDataRD *get_cluster_builder_shared() { return &cluster_builder_shared; } + RendererRD::SSEffects *get_ss_effects() { return ss_effects; } + + /* callback from updating our lighting UBOs, used to populate cluster builder */ + virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents) override; + virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) override; + virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents) override; + + virtual void base_uniforms_changed() override; _FORCE_INLINE_ virtual void update_uniform_sets() override { base_uniform_set_updated = true; _update_render_base_uniform_set(); 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 75ccf1add5..c01919a606 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 @@ -509,7 +509,7 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) { bool SceneShaderForwardClustered::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton; - 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, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER); + 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, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, true, RD::BARRIER_MASK_RASTER); } SceneShaderForwardClustered::MaterialData::~MaterialData() { @@ -621,10 +621,10 @@ void SceneShaderForwardClustered::init(const String p_defines) { //shader compiler ShaderCompiler::DefaultIdentifierActions actions; - actions.renames["MODEL_MATRIX"] = "model_matrix"; + actions.renames["MODEL_MATRIX"] = "read_model_matrix"; actions.renames["MODEL_NORMAL_MATRIX"] = "model_normal_matrix"; actions.renames["VIEW_MATRIX"] = "scene_data.view_matrix"; - actions.renames["INV_VIEW_MATRIX"] = "scene_data.inv_view_matrix"; + actions.renames["INV_VIEW_MATRIX"] = "inv_view_matrix"; actions.renames["PROJECTION_MATRIX"] = "projection_matrix"; actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; actions.renames["MODELVIEW_MATRIX"] = "modelview"; @@ -757,6 +757,8 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.usage_defines["RADIANCE"] = "#define CUSTOM_RADIANCE_USED\n"; actions.usage_defines["IRRADIANCE"] = "#define CUSTOM_IRRADIANCE_USED\n"; + actions.usage_defines["MODEL_MATRIX"] = "#define MODEL_MATRIX_USED\n"; + actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; 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 6c1b69148c..2b2090f8ed 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -39,7 +39,7 @@ using namespace RendererSceneRenderImplementation; -RenderForwardMobile::ForwardID RenderForwardMobile::_allocate_forward_id(ForwardIDType p_type) { +RendererRD::ForwardID RenderForwardMobile::ForwardIDStorageMobile::allocate_forward_id(RendererRD::ForwardIDType p_type) { int32_t index = -1; for (uint32_t i = 0; i < forward_id_allocators[p_type].allocations.size(); i++) { if (forward_id_allocators[p_type].allocations[i] == false) { @@ -58,15 +58,66 @@ RenderForwardMobile::ForwardID RenderForwardMobile::_allocate_forward_id(Forward return index; } -void RenderForwardMobile::_free_forward_id(ForwardIDType p_type, ForwardID p_id) { - ERR_FAIL_INDEX(p_id, (ForwardID)forward_id_allocators[p_type].allocations.size()); +void RenderForwardMobile::ForwardIDStorageMobile::free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) { + ERR_FAIL_INDEX(p_id, (RendererRD::ForwardID)forward_id_allocators[p_type].allocations.size()); forward_id_allocators[p_type].allocations[p_id] = false; } -void RenderForwardMobile::_map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) { +void RenderForwardMobile::ForwardIDStorageMobile::map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) { forward_id_allocators[p_type].map[p_id] = p_index; } +void RenderForwardMobile::ForwardIDStorageMobile::fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance) { + // first zero out our indices + + p_push_constant->omni_lights[0] = 0xFFFF; + p_push_constant->omni_lights[1] = 0xFFFF; + + p_push_constant->spot_lights[0] = 0xFFFF; + p_push_constant->spot_lights[1] = 0xFFFF; + + p_push_constant->decals[0] = 0xFFFF; + p_push_constant->decals[1] = 0xFFFF; + + p_push_constant->reflection_probes[0] = 0xFFFF; + p_push_constant->reflection_probes[1] = 0xFFFF; + + if (p_instance->omni_light_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS; + } + if (p_instance->spot_light_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_SPOT_LIGHTS; + } + if (p_instance->reflection_probe_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_REFLECTION_PROBES; + } + if (p_instance->decals_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_DECALS; + } + + for (uint32_t i = 0; i < MAX_RDL_CULL; i++) { + uint32_t ofs = i < 4 ? 0 : 1; + uint32_t shift = (i & 0x3) << 3; + uint32_t mask = ~(0xFF << shift); + if (i < p_instance->omni_light_count) { + p_push_constant->omni_lights[ofs] &= mask; + p_push_constant->omni_lights[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT].map[p_instance->omni_lights[i]]) << shift; + } + if (i < p_instance->spot_light_count) { + p_push_constant->spot_lights[ofs] &= mask; + p_push_constant->spot_lights[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT].map[p_instance->spot_lights[i]]) << shift; + } + if (i < p_instance->decals_count) { + p_push_constant->decals[ofs] &= mask; + p_push_constant->decals[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_DECAL].map[p_instance->decals[i]]) << shift; + } + if (i < p_instance->reflection_probe_count) { + p_push_constant->reflection_probes[ofs] &= mask; + p_push_constant->reflection_probes[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]]) << shift; + } + } +} + /* Render buffer */ void RenderForwardMobile::RenderBufferDataForwardMobile::free_data() { @@ -300,6 +351,7 @@ bool RenderForwardMobile::_render_buffers_can_be_storage() { } RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); //there should always be enough uniform buffers for render passes, otherwise bugs @@ -340,7 +392,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ } { - RID ref_texture = (p_render_data && p_render_data->reflection_atlas.is_valid()) ? reflection_atlas_get_texture(p_render_data->reflection_atlas) : RID(); + RID ref_texture = (p_render_data && p_render_data->reflection_atlas.is_valid()) ? light_storage->reflection_atlas_get_texture(p_render_data->reflection_atlas) : RID(); RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -358,7 +410,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID texture; if (p_render_data && p_render_data->shadow_atlas.is_valid()) { - texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); + texture = light_storage->shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); @@ -370,8 +422,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { - u.append_id(directional_shadow_get_texture()); + if (p_use_directional_shadow_atlas && light_storage->directional_shadow_get_texture().is_valid()) { + u.append_id(light_storage->directional_shadow_get_texture()); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH)); } @@ -387,8 +439,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { - RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); - RID texture = RendererRD::LightStorage::get_singleton()->lightmap_get_texture(base); + RID base = light_storage->lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); + RID texture = light_storage->lightmap_get_texture(base); RID rd_texture = texture_storage->texture_get_rd_texture(texture); u.append_id(rd_texture); } else { @@ -467,6 +519,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ } void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + // This probably needs to change... scene_state.lightmaps_used = 0; for (int i = 0; i < (int)p_lightmaps.size(); i++) { @@ -474,20 +528,20 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co break; } - RID lightmap = lightmap_instance_get_lightmap(p_lightmaps[i]); + RID lightmap = light_storage->lightmap_instance_get_lightmap(p_lightmaps[i]); - Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis; + Basis to_lm = light_storage->lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis; to_lm = to_lm.inverse().transposed(); //will transform normals RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform); scene_state.lightmaps[i].exposure_normalization = 1.0; if (p_render_data->camera_attributes.is_valid()) { - float baked_exposure = RendererRD::LightStorage::get_singleton()->lightmap_get_baked_exposure_normalization(lightmap); + float baked_exposure = light_storage->lightmap_get_baked_exposure_normalization(lightmap); float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); scene_state.lightmaps[i].exposure_normalization = enf / baked_exposure; } scene_state.lightmap_ids[i] = p_lightmaps[i]; - scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap); + scene_state.lightmap_has_sh[i] = light_storage->lightmap_uses_spherical_harmonics(lightmap); scene_state.lightmaps_used++; } @@ -496,12 +550,103 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co } } +void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + + p_render_data->cube_shadows.clear(); + p_render_data->shadows.clear(); + p_render_data->directional_shadows.clear(); + + Plane camera_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin); + float lod_distance_multiplier = p_render_data->scene_data->cam_projection.get_lod_multiplier(); + { + for (int i = 0; i < p_render_data->render_shadow_count; i++) { + RID li = p_render_data->render_shadows[i].light; + RID base = light_storage->light_instance_get_base_light(li); + + if (light_storage->light_get_type(base) == RS::LIGHT_DIRECTIONAL) { + p_render_data->directional_shadows.push_back(i); + } else if (light_storage->light_get_type(base) == RS::LIGHT_OMNI && light_storage->light_omni_get_shadow_mode(base) == RS::LIGHT_OMNI_SHADOW_CUBE) { + p_render_data->cube_shadows.push_back(i); + } else { + p_render_data->shadows.push_back(i); + } + } + + //cube shadows are rendered in their own way + for (uint32_t i = 0; i < p_render_data->cube_shadows.size(); i++) { + _render_shadow_pass(p_render_data->render_shadows[p_render_data->cube_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->cube_shadows[i]].pass, p_render_data->render_shadows[p_render_data->cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info); + } + + if (p_render_data->directional_shadows.size()) { + //open the pass for directional shadows + light_storage->update_directional_shadow_atlas(); + RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE); + RD::get_singleton()->draw_list_end(); + } + } + + bool render_shadows = p_render_data->directional_shadows.size() || p_render_data->shadows.size(); + + if (render_shadows) { + RENDER_TIMESTAMP("Render Shadows"); + } + + //prepare shadow rendering + if (render_shadows) { + _render_shadow_begin(); + + //render directional shadows + for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) { + _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info); + } + //render positional shadows + for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) { + _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info); + } + + _render_shadow_process(); + + _render_shadow_end(RD::BARRIER_MASK_NO_BARRIER); + } + + //full barrier here, we need raster, transfer and compute and it depends from the previous work + RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL); + + bool using_shadows = true; + + if (p_render_data->reflection_probe.is_valid()) { + if (!RSG::light_storage->reflection_probe_renders_shadows(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { + using_shadows = false; + } + } else { + //do not render reflections when rendering a reflection probe + light_storage->update_reflection_probe_buffer(p_render_data, *p_render_data->reflection_probes, p_render_data->scene_data->cam_transform.affine_inverse(), p_render_data->environment); + } + + uint32_t directional_light_count = 0; + uint32_t positional_light_count = 0; + light_storage->update_light_buffers(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows); + texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform.affine_inverse()); + + p_render_data->directional_light_count = directional_light_count; +} + void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + + Ref<RenderSceneBuffersRD> rb; Ref<RenderBufferDataForwardMobile> rb_data; if (p_render_data->render_buffers.is_valid()) { - rb_data = p_render_data->render_buffers->get_custom_data(RB_SCOPE_MOBILE); + rb = p_render_data->render_buffers; + rb_data = rb->get_custom_data(RB_SCOPE_MOBILE); } + RENDER_TIMESTAMP("Prepare 3D Scene"); + + _update_vrs(rb); + RENDER_TIMESTAMP("Setup 3D Scene"); /* TODO @@ -532,9 +677,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color bool using_subpass_transparent = true; bool using_subpass_post_process = true; - bool using_ssr = false; // I don't think we support this in our mobile renderer so probably should phase it out - bool using_sss = false; // I don't think we support this in our mobile renderer so probably should phase it out - // fill our render lists early so we can find out if we use various features _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR); render_list[RENDER_LIST_OPAQUE].sort_by_key(); @@ -559,7 +701,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color using_subpass_post_process = false; } - if (using_ssr || using_sss || scene_state.used_screen_texture || scene_state.used_depth_texture) { + if (scene_state.used_screen_texture || scene_state.used_depth_texture) { // can't use our last two subpasses using_subpass_transparent = false; using_subpass_post_process = false; @@ -576,13 +718,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_TWO_SUBPASSES); } } else if (p_render_data->reflection_probe.is_valid()) { - uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe); + uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); screen_size.x = resolution; screen_size.y = resolution; - framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); - if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { + if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { p_render_data->environment = RID(); //no environment on interiors } @@ -713,8 +855,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers } - RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS]; - _pre_opaque_render(p_render_data, false, false, false, nullrids, RID()); + _pre_opaque_render(p_render_data); uint32_t spec_constant_base_flags = 0; @@ -758,8 +899,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, true); - bool can_continue_color = !using_subpass_transparent && !scene_state.used_screen_texture && !using_ssr && !using_sss; - bool can_continue_depth = !using_subpass_transparent && !scene_state.used_depth_texture && !using_ssr && !using_sss; + bool can_continue_color = !using_subpass_transparent && !scene_state.used_screen_texture; + bool can_continue_depth = !using_subpass_transparent && !scene_state.used_depth_texture; { // regular forward for now @@ -917,10 +1058,190 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (rb_data.is_valid()) { _disable_clear_request(p_render_data); } + + if (rb.is_valid()) { + _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex); + } } /* these are being called from RendererSceneRenderRD::_pre_opaque_render */ +void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + + ERR_FAIL_COND(!light_storage->owns_light_instance(p_light)); + + RID base = light_storage->light_instance_get_base_light(p_light); + + Rect2i atlas_rect; + uint32_t atlas_size = 1; + RID atlas_fb; + + bool using_dual_paraboloid = false; + bool using_dual_paraboloid_flip = false; + Vector2i dual_paraboloid_offset; + RID render_fb; + RID render_texture; + float zfar; + + bool use_pancake = false; + bool render_cubemap = false; + bool finalize_cubemap = false; + + bool flip_y = false; + + Projection light_projection; + Transform3D light_transform; + + if (light_storage->light_get_type(base) == RS::LIGHT_DIRECTIONAL) { + //set pssm stuff + uint64_t last_scene_shadow_pass = light_storage->light_instance_get_shadow_pass(p_light); + if (last_scene_shadow_pass != get_scene_pass()) { + light_storage->light_instance_set_directional_rect(p_light, light_storage->get_directional_shadow_rect()); + light_storage->directional_shadow_increase_current_light(); + light_storage->light_instance_set_shadow_pass(p_light, get_scene_pass()); + } + + use_pancake = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0; + light_projection = light_storage->light_instance_get_shadow_camera(p_light, p_pass); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, p_pass); + + atlas_rect = light_storage->light_instance_get_directional_rect(p_light); + + if (light_storage->light_directional_get_shadow_mode(base) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + atlas_rect.size.width /= 2; + atlas_rect.size.height /= 2; + + if (p_pass == 1) { + atlas_rect.position.x += atlas_rect.size.width; + } else if (p_pass == 2) { + atlas_rect.position.y += atlas_rect.size.height; + } else if (p_pass == 3) { + atlas_rect.position += atlas_rect.size; + } + } else if (light_storage->light_directional_get_shadow_mode(base) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { + atlas_rect.size.height /= 2; + + if (p_pass == 0) { + } else { + atlas_rect.position.y += atlas_rect.size.height; + } + } + + float directional_shadow_size = light_storage->directional_shadow_get_size(); + Rect2 atlas_rect_norm = atlas_rect; + atlas_rect_norm.position /= directional_shadow_size; + atlas_rect_norm.size /= directional_shadow_size; + light_storage->light_instance_set_directional_shadow_atlas_rect(p_light, p_pass, atlas_rect_norm); + + zfar = RSG::light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE); + + render_fb = light_storage->direction_shadow_get_fb(); + render_texture = RID(); + flip_y = true; + + } else { + //set from shadow atlas + + ERR_FAIL_COND(!light_storage->owns_shadow_atlas(p_shadow_atlas)); + ERR_FAIL_COND(!light_storage->shadow_atlas_owns_light_instance(p_shadow_atlas, p_light)); + + RSG::light_storage->shadow_atlas_update(p_shadow_atlas); + + uint32_t key = light_storage->shadow_atlas_get_light_instance_key(p_shadow_atlas, p_light); + + uint32_t quadrant = (key >> RendererRD::LightStorage::QUADRANT_SHIFT) & 0x3; + uint32_t shadow = key & RendererRD::LightStorage::SHADOW_INDEX_MASK; + uint32_t subdivision = light_storage->shadow_atlas_get_quadrant_subdivision(p_shadow_atlas, quadrant); + + ERR_FAIL_INDEX((int)shadow, light_storage->shadow_atlas_get_quadrant_shadow_size(p_shadow_atlas, quadrant)); + + uint32_t shadow_atlas_size = light_storage->shadow_atlas_get_size(p_shadow_atlas); + uint32_t quadrant_size = shadow_atlas_size >> 1; + + atlas_rect.position.x = (quadrant & 1) * quadrant_size; + atlas_rect.position.y = (quadrant >> 1) * quadrant_size; + + uint32_t shadow_size = (quadrant_size / subdivision); + atlas_rect.position.x += (shadow % subdivision) * shadow_size; + atlas_rect.position.y += (shadow / subdivision) * shadow_size; + + atlas_rect.size.width = shadow_size; + atlas_rect.size.height = shadow_size; + + zfar = light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE); + + if (light_storage->light_get_type(base) == RS::LIGHT_OMNI) { + bool wrap = (shadow + 1) % subdivision == 0; + dual_paraboloid_offset = wrap ? Vector2i(1 - subdivision, 1) : Vector2i(1, 0); + + if (light_storage->light_omni_get_shadow_mode(base) == RS::LIGHT_OMNI_SHADOW_CUBE) { + render_texture = light_storage->get_cubemap(shadow_size / 2); + render_fb = light_storage->get_cubemap_fb(shadow_size / 2, p_pass); + + light_projection = light_storage->light_instance_get_shadow_camera(p_light, p_pass); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, p_pass); + render_cubemap = true; + finalize_cubemap = p_pass == 5; + atlas_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas); + + atlas_size = shadow_atlas_size; + + if (p_pass == 0) { + _render_shadow_begin(); + } + + } else { + atlas_rect.position.x += 1; + atlas_rect.position.y += 1; + atlas_rect.size.x -= 2; + atlas_rect.size.y -= 2; + + atlas_rect.position += p_pass * atlas_rect.size * dual_paraboloid_offset; + + light_projection = light_storage->light_instance_get_shadow_camera(p_light, 0); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, 0); + + using_dual_paraboloid = true; + using_dual_paraboloid_flip = p_pass == 1; + render_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas); + flip_y = true; + } + + } else if (light_storage->light_get_type(base) == RS::LIGHT_SPOT) { + light_projection = light_storage->light_instance_get_shadow_camera(p_light, 0); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, 0); + + render_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas); + + flip_y = true; + } + } + + if (render_cubemap) { + //rendering to cubemap + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info); + if (finalize_cubemap) { + _render_shadow_process(); + _render_shadow_end(); + //reblit + Rect2 atlas_rect_norm = atlas_rect; + atlas_rect_norm.position /= float(atlas_size); + atlas_rect_norm.size /= float(atlas_size); + 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(), false); + atlas_rect_norm.position += Vector2(dual_paraboloid_offset) * atlas_rect_norm.size; + 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_storage->light_instance_set_shadow_transform(p_light, Projection(), light_storage->light_instance_get_base_transform(p_light), zfar, 0, 0, 0); + } + + } else { + //render shadow + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info); + } +} + void RenderForwardMobile::_render_shadow_begin() { scene_state.shadow_passes.clear(); RD::get_singleton()->draw_command_begin_label("Shadow Setup"); @@ -1146,7 +1467,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *> } void RenderForwardMobile::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) { - // we don't do GI in low end.. + // we don't do SDFGI in low end.. } void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) { @@ -1189,7 +1510,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const RD::get_singleton()->draw_command_end_label(); } -void RenderForwardMobile::_base_uniforms_changed() { +void RenderForwardMobile::base_uniforms_changed() { if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); } @@ -1305,14 +1626,14 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_omni_light_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_omni_light_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_spot_light_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_spot_light_buffer()); uniforms.push_back(u); } @@ -1320,14 +1641,14 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_reflection_probe_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_reflection_probe_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.append_id(get_directional_light_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_directional_light_buffer()); uniforms.push_back(u); } { @@ -1364,7 +1685,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_decal_buffer()); + u.append_id(RendererRD::TextureStorage::get_singleton()->get_decal_buffer()); uniforms.push_back(u); } @@ -1584,7 +1905,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const void RenderForwardMobile::_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) { Ref<RenderSceneBuffersRD> rd = p_render_data->render_buffers; RID env = is_environment(p_render_data->environment) ? p_render_data->environment : RID(); - RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID(); + RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? RendererRD::LightStorage::get_singleton()->reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID(); // May do this earlier in RenderSceneRenderRD::render_scene if (p_index >= (int)scene_state.uniform_buffers.size()) { @@ -1665,57 +1986,6 @@ void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_para } } -void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance) { - // first zero out our indices - - p_push_constant->omni_lights[0] = 0xFFFF; - p_push_constant->omni_lights[1] = 0xFFFF; - - p_push_constant->spot_lights[0] = 0xFFFF; - p_push_constant->spot_lights[1] = 0xFFFF; - - p_push_constant->decals[0] = 0xFFFF; - p_push_constant->decals[1] = 0xFFFF; - - p_push_constant->reflection_probes[0] = 0xFFFF; - p_push_constant->reflection_probes[1] = 0xFFFF; - - if (p_instance->omni_light_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS; - } - if (p_instance->spot_light_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_SPOT_LIGHTS; - } - if (p_instance->reflection_probe_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_REFLECTION_PROBES; - } - if (p_instance->decals_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_DECALS; - } - - for (uint32_t i = 0; i < MAX_RDL_CULL; i++) { - uint32_t ofs = i < 4 ? 0 : 1; - uint32_t shift = (i & 0x3) << 3; - uint32_t mask = ~(0xFF << shift); - if (i < p_instance->omni_light_count) { - p_push_constant->omni_lights[ofs] &= mask; - p_push_constant->omni_lights[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_OMNI_LIGHT].map[p_instance->omni_lights[i]]) << shift; - } - if (i < p_instance->spot_light_count) { - p_push_constant->spot_lights[ofs] &= mask; - p_push_constant->spot_lights[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_SPOT_LIGHT].map[p_instance->spot_lights[i]]) << shift; - } - if (i < p_instance->decals_count) { - p_push_constant->decals[ofs] &= mask; - p_push_constant->decals[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_DECAL].map[p_instance->decals[i]]) << shift; - } - if (i < p_instance->reflection_probe_count) { - p_push_constant->reflection_probes[ofs] &= mask; - p_push_constant->reflection_probes[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]]) << shift; - } - } -} - template <RenderForwardMobile::PassMode p_pass_mode> void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); @@ -1757,6 +2027,14 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr RendererRD::MaterialStorage::store_transform(Transform3D(), push_constant.transform); } +#ifdef REAL_T_IS_DOUBLE + // Split the origin into two components, the float approximation and the missing precision + // In the shader we will combine these back together to restore the lost precision. + RendererRD::MaterialStorage::split_double(inst->transform.origin.x, &push_constant.transform[12], &push_constant.transform[3]); + RendererRD::MaterialStorage::split_double(inst->transform.origin.y, &push_constant.transform[13], &push_constant.transform[7]); + RendererRD::MaterialStorage::split_double(inst->transform.origin.z, &push_constant.transform[14], &push_constant.transform[11]); +#endif + push_constant.flags = inst->flags_cache; push_constant.gi_offset = inst->gi_offset_cache; push_constant.layer_mask = inst->layer_mask; @@ -1789,7 +2067,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr if (inst->use_soft_shadow) { base_spec_constants |= 1 << SPEC_CONSTANT_USING_SOFT_SHADOWS; } - _fill_push_constant_instance_indices(&push_constant, base_spec_constants, inst); + forward_id_storage_mobile->fill_push_constant_instance_indices(&push_constant, base_spec_constants, inst); #ifdef DEBUG_ENABLED if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) { @@ -1981,17 +2259,17 @@ void RenderForwardMobile::GeometryInstanceForwardMobile::pair_light_instances(co spot_light_count = 0; for (uint32_t i = 0; i < p_light_instance_count; i++) { - RS::LightType type = RenderForwardMobile::get_singleton()->light_instance_get_type(p_light_instances[i]); + RS::LightType type = RendererRD::LightStorage::get_singleton()->light_instance_get_type(p_light_instances[i]); switch (type) { case RS::LIGHT_OMNI: { if (omni_light_count < (uint32_t)MAX_RDL_CULL) { - omni_lights[omni_light_count] = RenderForwardMobile::get_singleton()->light_instance_get_forward_id(p_light_instances[i]); + omni_lights[omni_light_count] = RendererRD::LightStorage::get_singleton()->light_instance_get_forward_id(p_light_instances[i]); omni_light_count++; } } break; case RS::LIGHT_SPOT: { if (spot_light_count < (uint32_t)MAX_RDL_CULL) { - spot_lights[spot_light_count] = RenderForwardMobile::get_singleton()->light_instance_get_forward_id(p_light_instances[i]); + spot_lights[spot_light_count] = RendererRD::LightStorage::get_singleton()->light_instance_get_forward_id(p_light_instances[i]); spot_light_count++; } } break; @@ -2004,14 +2282,14 @@ void RenderForwardMobile::GeometryInstanceForwardMobile::pair_light_instances(co void RenderForwardMobile::GeometryInstanceForwardMobile::pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { reflection_probe_count = p_reflection_probe_instance_count < (uint32_t)MAX_RDL_CULL ? p_reflection_probe_instance_count : (uint32_t)MAX_RDL_CULL; for (uint32_t i = 0; i < reflection_probe_count; i++) { - reflection_probes[i] = RenderForwardMobile::get_singleton()->reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]); + reflection_probes[i] = RendererRD::LightStorage::get_singleton()->reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]); } } void RenderForwardMobile::GeometryInstanceForwardMobile::pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) { decals_count = p_decal_instance_count < (uint32_t)MAX_RDL_CULL ? p_decal_instance_count : (uint32_t)MAX_RDL_CULL; for (uint32_t i = 0; i < decals_count; i++) { - decals[i] = RenderForwardMobile::get_singleton()->decal_instance_get_forward_id(p_decal_instances[i]); + decals[i] = RendererRD::TextureStorage::get_singleton()->decal_instance_get_forward_id(p_decal_instances[i]); } } @@ -2379,10 +2657,6 @@ bool RenderForwardMobile::is_dynamic_gi_supported() const { return false; } -bool RenderForwardMobile::is_clustered_enabled() const { - return false; -} - bool RenderForwardMobile::is_volumetric_supported() const { return false; } @@ -2438,7 +2712,7 @@ void RenderForwardMobile::_update_shader_quality_settings() { scene_shader.set_default_specialization_constants(spec_constants); - _base_uniforms_changed(); //also need this + base_uniforms_changed(); //also need this } RenderForwardMobile::RenderForwardMobile() { @@ -2472,6 +2746,11 @@ RenderForwardMobile::RenderForwardMobile() { { defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n"; } +#ifdef REAL_T_IS_DOUBLE + { + defines += "\n#define USE_DOUBLE_PRECISION \n"; + } +#endif scene_shader.init(defines); @@ -2482,7 +2761,7 @@ RenderForwardMobile::RenderForwardMobile() { } RenderForwardMobile::~RenderForwardMobile() { - directional_shadow_atlas_set_size(0); + RSG::light_storage->directional_shadow_atlas_set_size(0); //clear base uniform set if still valid for (uint32_t i = 0; i < render_pass_uniform_sets.size(); i++) { 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 1b31d2749d..415bd79ad6 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -44,19 +44,12 @@ namespace RendererSceneRenderImplementation { class RenderForwardMobile : public RendererSceneRenderRD { friend SceneShaderForwardMobile; - struct ForwardIDAllocator { - LocalVector<bool> allocations; - LocalVector<uint8_t> map; - }; - - ForwardIDAllocator forward_id_allocators[FORWARD_ID_MAX]; +protected: + struct GeometryInstanceSurfaceDataCache; - virtual ForwardID _allocate_forward_id(ForwardIDType p_type) override; - virtual void _free_forward_id(ForwardIDType p_type, ForwardID p_id) override; - virtual void _map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) override; - virtual bool _uses_forward_ids() const override { return true; } +private: + static RenderForwardMobile *singleton; -protected: /* Scene Shader */ enum { @@ -157,8 +150,6 @@ protected: // PASS_MODE_SDF, }; - class GeometryInstanceForwardMobile; - struct GeometryInstanceSurfaceDataCache; struct RenderElementInfo; struct RenderListParameters { @@ -201,36 +192,27 @@ protected: } }; - virtual float _render_buffers_get_luminance_multiplier() override; - virtual RD::DataFormat _render_buffers_get_color_format() override; - virtual bool _render_buffers_can_be_storage() override; + /* Render shadows */ - RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0); - virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; + void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &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, RenderingMethod::RenderInfo *p_render_info = nullptr); + void _render_shadow_begin(); + void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &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, RenderingMethod::RenderInfo *p_render_info = nullptr); + void _render_shadow_process(); + void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL); - virtual void _render_shadow_begin() override; - virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &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, RenderingMethod::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; + /* Render Scene */ - virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override; - virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; - virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override; - virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override; + RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0); + void _pre_opaque_render(RenderDataRD *p_render_data); uint64_t lightmap_texture_array_version = 0xFFFFFFFF; - virtual void _base_uniforms_changed() override; void _update_render_base_uniform_set(); - virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; - virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false); void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1); // void _update_instance_data_buffer(RenderListType p_render_list); - static RenderForwardMobile *singleton; - void _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 = false, bool p_pancake_shadows = false, int p_index = 0); void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform); @@ -369,9 +351,29 @@ protected: RenderList render_list[RENDER_LIST_MAX]; +protected: + /* setup */ + virtual void _update_shader_quality_settings() override; + + virtual float _render_buffers_get_luminance_multiplier() override; + virtual RD::DataFormat _render_buffers_get_color_format() override; + virtual bool _render_buffers_can_be_storage() override; + + virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; + virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; + + virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override{}; + virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override{}; + virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override{}; + + virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override{}; + virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override{}; + /* Geometry instance */ - // check which ones of these apply, probably all except GI and SDFGI + class GeometryInstanceForwardMobile; + + // When changing any of these enums, remember to change the corresponding enums in the shader files as well. enum { INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4, INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5, @@ -484,13 +486,13 @@ protected: // culled light info uint32_t reflection_probe_count = 0; - ForwardID reflection_probes[MAX_RDL_CULL]; + RendererRD::ForwardID reflection_probes[MAX_RDL_CULL]; uint32_t omni_light_count = 0; - ForwardID omni_lights[MAX_RDL_CULL]; + RendererRD::ForwardID omni_lights[MAX_RDL_CULL]; uint32_t spot_light_count = 0; - ForwardID spot_lights[MAX_RDL_CULL]; + RendererRD::ForwardID spot_lights[MAX_RDL_CULL]; uint32_t decals_count = 0; - ForwardID decals[MAX_RDL_CULL]; + RendererRD::ForwardID decals[MAX_RDL_CULL]; GeometryInstanceSurfaceDataCache *surface_caches = nullptr; @@ -513,9 +515,41 @@ protected: virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override; }; - _FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance); + /* Rendering */ - void _update_shader_quality_settings() override; + virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; + + virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override; + virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override; + virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override; + + /* Forward ID */ + + class ForwardIDStorageMobile : public RendererRD::ForwardIDStorage { + public: + struct ForwardIDAllocator { + LocalVector<bool> allocations; + LocalVector<uint8_t> map; + }; + + ForwardIDAllocator forward_id_allocators[RendererRD::FORWARD_ID_MAX]; + + public: + virtual RendererRD::ForwardID allocate_forward_id(RendererRD::ForwardIDType p_type) override; + virtual void free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) override; + virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) override; + virtual bool uses_forward_ids() const override { return true; } + + void fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance); + }; + + ForwardIDStorageMobile *forward_id_storage_mobile = nullptr; + + virtual RendererRD::ForwardIDStorage *create_forward_id_storage() override { + forward_id_storage_mobile = memnew(ForwardIDStorageMobile); + return forward_id_storage_mobile; + } public: static RenderForwardMobile *get_singleton() { return singleton; } @@ -544,8 +578,9 @@ public: virtual bool free(RID p_rid) override; + virtual void base_uniforms_changed() override; + virtual bool is_dynamic_gi_supported() const override; - virtual bool is_clustered_enabled() const override; virtual bool is_volumetric_supported() const override; virtual uint32_t get_max_elements() const override; 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 383ed9247d..71fb3ee4f5 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 @@ -464,7 +464,7 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) { bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton; - 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, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER); + 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, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, RD::BARRIER_MASK_RASTER); } SceneShaderForwardMobile::MaterialData::~MaterialData() { @@ -521,10 +521,10 @@ void SceneShaderForwardMobile::init(const String p_defines) { //shader compiler ShaderCompiler::DefaultIdentifierActions actions; - actions.renames["MODEL_MATRIX"] = "model_matrix"; + actions.renames["MODEL_MATRIX"] = "read_model_matrix"; actions.renames["MODEL_NORMAL_MATRIX"] = "model_normal_matrix"; actions.renames["VIEW_MATRIX"] = "scene_data.view_matrix"; - actions.renames["INV_VIEW_MATRIX"] = "scene_data.inv_view_matrix"; + actions.renames["INV_VIEW_MATRIX"] = "inv_view_matrix"; actions.renames["PROJECTION_MATRIX"] = "projection_matrix"; actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; actions.renames["MODELVIEW_MATRIX"] = "modelview"; @@ -657,6 +657,8 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.usage_defines["RADIANCE"] = "#define CUSTOM_RADIANCE_USED\n"; actions.usage_defines["IRRADIANCE"] = "#define CUSTOM_IRRADIANCE_USED\n"; + actions.usage_defines["MODEL_MATRIX"] = "#define MODEL_MATRIX_USED\n"; + actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 0210151420..4c14ef7b9e 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1627,7 +1627,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, ShadowRenderPushConstant push_constant; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { - push_constant.projection[y * 4 + x] = projection.matrix[y][x]; + push_constant.projection[y * 4 + x] = projection.columns[y][x]; } } static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) }; @@ -1702,7 +1702,7 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh ShadowRenderPushConstant push_constant; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { - push_constant.projection[y * 4 + x] = projection.matrix[y][x]; + push_constant.projection[y * 4 + x] = projection.columns[y][x]; } } @@ -1770,7 +1770,7 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan ShadowRenderPushConstant push_constant; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { - push_constant.projection[y * 4 + x] = projection.matrix[y][x]; + push_constant.projection[y * 4 + x] = projection.columns[y][x]; } } @@ -2324,7 +2324,7 @@ RendererRD::MaterialStorage::ShaderData *RendererCanvasRenderRD::_create_shader_ bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); - 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, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); + 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, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, false); } RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() { @@ -2512,6 +2512,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.renames["VERTEX_ID"] = "gl_VertexIndex"; actions.renames["LIGHT_POSITION"] = "light_position"; + actions.renames["LIGHT_DIRECTION"] = "light_direction"; + actions.renames["LIGHT_IS_DIRECTIONAL"] = "is_directional"; actions.renames["LIGHT_COLOR"] = "light_color"; actions.renames["LIGHT_ENERGY"] = "light_energy"; actions.renames["LIGHT"] = "light"; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index f169692ea0..dd3f62e509 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -44,13 +44,9 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID } for (int i = 0; i < p_amount; i++) { - RID texture = texture_storage->render_target_get_texture(p_render_targets[i].render_target); - ERR_CONTINUE(texture.is_null()); - RID rd_texture = texture_storage->texture_get_rd_texture(texture); + RID rd_texture = texture_storage->render_target_get_rd_texture(p_render_targets[i].render_target); ERR_CONTINUE(rd_texture.is_null()); - // TODO if keep_3d_linear was set when rendering to this render target we need to add a linear->sRGB conversion in. - if (!render_target_descriptors.has(rd_texture) || !RD::get_singleton()->uniform_set_is_valid(render_target_descriptors[rd_texture])) { Vector<RD::Uniform> uniforms; RD::Uniform u; @@ -170,6 +166,10 @@ void RendererCompositorRD::finalize() { } void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) { + if (p_image.is_null() || p_image->is_empty()) { + return; + } + RD::get_singleton()->prepare_screen_for_drawing(); RID texture = texture_storage->texture_allocate(); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 667d910a69..6157d7d840 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -195,32 +195,6 @@ void RendererSceneRenderRD::environment_set_sdfgi_frames_to_update_light(RS::Env gi.sdfgi_frames_to_update_light = p_update; } -void RendererSceneRenderRD::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) { - ssr_roughness_quality = p_quality; -} - -RS::EnvironmentSSRRoughnessQuality RendererSceneRenderRD::environment_get_ssr_roughness_quality() const { - return ssr_roughness_quality; -} - -void RendererSceneRenderRD::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { - ssao_quality = p_quality; - ssao_half_size = p_half_size; - ssao_adaptive_target = p_adaptive_target; - ssao_blur_passes = p_blur_passes; - ssao_fadeout_from = p_fadeout_from; - ssao_fadeout_to = p_fadeout_to; -} - -void RendererSceneRenderRD::environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { - ssil_quality = p_quality; - ssil_half_size = p_half_size; - ssil_adaptive_target = p_adaptive_target; - ssil_blur_passes = p_blur_passes; - ssil_fadeout_from = p_fadeout_from; - ssil_fadeout_to = p_fadeout_to; -} - Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) { ERR_FAIL_COND_V(p_env.is_null(), Ref<Image>()); @@ -284,257 +258,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba } } -//////////////////////////////////////////////////////////// - -RID RendererSceneRenderRD::fog_volume_instance_create(RID p_fog_volume) { - 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) { - 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) { - 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 { - 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 { - 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(); -} - -//////////////////////////////////////////////////////////// - -RID RendererSceneRenderRD::reflection_atlas_create() { - ReflectionAtlas ra; - ra.count = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_count"); - ra.size = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_size"); - - if (is_clustered_enabled()) { - ra.cluster_builder = memnew(ClusterBuilderRD); - ra.cluster_builder->set_shared(&cluster_builder_shared); - ra.cluster_builder->setup(Size2i(ra.size, ra.size), max_cluster_elements, RID(), RID(), RID()); - } else { - ra.cluster_builder = nullptr; - } - - return reflection_atlas_owner.make_rid(ra); -} - -void RendererSceneRenderRD::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) { - ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas); - ERR_FAIL_COND(!ra); - - if (ra->size == p_reflection_size && ra->count == p_reflection_count) { - return; //no changes - } - - if (ra->cluster_builder) { - // only if we're using our cluster - ra->cluster_builder->setup(Size2i(ra->size, ra->size), max_cluster_elements, RID(), RID(), RID()); - } - - ra->size = p_reflection_size; - ra->count = p_reflection_count; - - if (ra->reflection.is_valid()) { - //clear and invalidate everything - RD::get_singleton()->free(ra->reflection); - ra->reflection = RID(); - RD::get_singleton()->free(ra->depth_buffer); - ra->depth_buffer = RID(); - for (int i = 0; i < ra->reflections.size(); i++) { - ra->reflections.write[i].data.clear_reflection_data(); - if (ra->reflections[i].owner.is_null()) { - continue; - } - reflection_probe_release_atlas_index(ra->reflections[i].owner); - //rp->atlasindex clear - } - - ra->reflections.clear(); - } -} - -int RendererSceneRenderRD::reflection_atlas_get_size(RID p_ref_atlas) const { - ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas); - ERR_FAIL_COND_V(!ra, 0); - - return ra->size; -} - -//////////////////////// -RID RendererSceneRenderRD::reflection_probe_instance_create(RID p_probe) { - ReflectionProbeInstance rpi; - rpi.probe = p_probe; - rpi.forward_id = _allocate_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE); - - return reflection_probe_instance_owner.make_rid(rpi); -} - -void RendererSceneRenderRD::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND(!rpi); - - rpi->transform = p_transform; - rpi->dirty = true; -} - -void RendererSceneRenderRD::reflection_probe_release_atlas_index(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND(!rpi); - - if (rpi->atlas.is_null()) { - return; //nothing to release - } - ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); - ERR_FAIL_COND(!atlas); - ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size()); - atlas->reflections.write[rpi->atlas_index].owner = RID(); - rpi->atlas_index = -1; - rpi->atlas = RID(); -} - -bool RendererSceneRenderRD::reflection_probe_instance_needs_redraw(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, false); - - if (rpi->rendering) { - return false; - } - - if (rpi->dirty) { - return true; - } - - if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) { - return true; - } - - return rpi->atlas_index == -1; -} - -bool RendererSceneRenderRD::reflection_probe_instance_has_reflection(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, false); - - return rpi->atlas.is_valid(); -} - -bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { - ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_reflection_atlas); - - ERR_FAIL_COND_V(!atlas, false); - - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, false); - - RD::get_singleton()->draw_command_begin_label("Reflection probe render"); - - if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) { - WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings."); - reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count); - } - - if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) { - // Invalidate reflection atlas, need to regenerate - RD::get_singleton()->free(atlas->reflection); - atlas->reflection = RID(); - - for (int i = 0; i < atlas->reflections.size(); i++) { - if (atlas->reflections[i].owner.is_null()) { - continue; - } - reflection_probe_release_atlas_index(atlas->reflections[i].owner); - } - - atlas->reflections.clear(); - } - - if (atlas->reflection.is_null()) { - int mipmaps = MIN(sky.roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1); - mipmaps = RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering - { - //reflection atlas was unused, create: - RD::TextureFormat tf; - tf.array_layers = 6 * atlas->count; - tf.format = _render_buffers_get_color_format(); - tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; - tf.mipmaps = mipmaps; - tf.width = atlas->size; - tf.height = atlas->size; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0); - - atlas->reflection = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - { - RD::TextureFormat tf; - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; - tf.width = atlas->size; - tf.height = atlas->size; - tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - atlas->depth_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - atlas->reflections.resize(atlas->count); - for (int i = 0; i < atlas->count; i++) { - atlas->reflections.write[i].data.update_reflection_data(atlas->size, mipmaps, false, atlas->reflection, i * 6, RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format()); - for (int j = 0; j < 6; j++) { - atlas->reflections.write[i].fbs[j] = reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer); - } - } - - Vector<RID> fb; - fb.push_back(atlas->depth_buffer); - atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb); - } - - if (rpi->atlas_index == -1) { - for (int i = 0; i < atlas->reflections.size(); i++) { - if (atlas->reflections[i].owner.is_null()) { - rpi->atlas_index = i; - break; - } - } - //find the one used last - if (rpi->atlas_index == -1) { - //everything is in use, find the one least used via LRU - uint64_t pass_min = 0; - - for (int i = 0; i < atlas->reflections.size(); i++) { - ReflectionProbeInstance *rpi2 = reflection_probe_instance_owner.get_or_null(atlas->reflections[i].owner); - if (rpi2->last_pass < pass_min) { - pass_min = rpi2->last_pass; - rpi->atlas_index = i; - } - } - } - } - - if (rpi->atlas_index != -1) { // should we fail if this is still -1 ? - atlas->reflections.write[rpi->atlas_index].owner = p_instance; - } - - rpi->atlas = p_reflection_atlas; - rpi->rendering = true; - rpi->dirty = false; - rpi->processing_layer = 1; - rpi->processing_side = 0; - - RD::get_singleton()->draw_command_end_label(); - - return true; -} +/* REFLECTION PROBE */ RID RendererSceneRenderRD::reflection_probe_create_framebuffer(RID p_color, RID p_depth) { Vector<RID> fb; @@ -543,667 +267,39 @@ RID RendererSceneRenderRD::reflection_probe_create_framebuffer(RID p_color, RID return RD::get_singleton()->framebuffer_create(fb); } -bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, false); - ERR_FAIL_COND_V(!rpi->rendering, false); - ERR_FAIL_COND_V(rpi->atlas.is_null(), false); - - ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); - if (!atlas || rpi->atlas_index == -1) { - //does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering) - rpi->rendering = false; - return false; - } - - if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) { - // Using real time reflections, all roughness is done in one step - atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(false); - rpi->rendering = false; - rpi->processing_side = 0; - rpi->processing_layer = 1; - return true; - } - - if (rpi->processing_layer > 1) { - atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(false, 10, rpi->processing_layer, sky.sky_ggx_samples_quality); - rpi->processing_layer++; - if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) { - rpi->rendering = false; - rpi->processing_side = 0; - rpi->processing_layer = 1; - return true; - } - return false; - - } else { - atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(false, rpi->processing_side, rpi->processing_layer, sky.sky_ggx_samples_quality); - } - - rpi->processing_side++; - if (rpi->processing_side == 6) { - rpi->processing_side = 0; - rpi->processing_layer++; - } - - return false; -} - -uint32_t RendererSceneRenderRD::reflection_probe_instance_get_resolution(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, 0); - - ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); - ERR_FAIL_COND_V(!atlas, 0); - return atlas->size; -} - -RID RendererSceneRenderRD::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, RID()); - ERR_FAIL_INDEX_V(p_index, 6, RID()); - - ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); - ERR_FAIL_COND_V(!atlas, RID()); - return atlas->reflections[rpi->atlas_index].fbs[p_index]; -} - -RID RendererSceneRenderRD::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, RID()); - ERR_FAIL_INDEX_V(p_index, 6, RID()); - - ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); - ERR_FAIL_COND_V(!atlas, RID()); - return atlas->depth_fb; -} - -/////////////////////////////////////////////////////////// - -RID RendererSceneRenderRD::shadow_atlas_create() { - return shadow_atlas_owner.make_rid(ShadowAtlas()); -} - -void RendererSceneRenderRD::_update_shadow_atlas(ShadowAtlas *shadow_atlas) { - if (shadow_atlas->size > 0 && shadow_atlas->depth.is_null()) { - RD::TextureFormat tf; - tf.format = shadow_atlas->use_16_bits ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_D32_SFLOAT; - tf.width = shadow_atlas->size; - tf.height = shadow_atlas->size; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - shadow_atlas->depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); - Vector<RID> fb_tex; - fb_tex.push_back(shadow_atlas->depth); - shadow_atlas->fb = RD::get_singleton()->framebuffer_create(fb_tex); - } -} - -void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND(!shadow_atlas); - ERR_FAIL_COND(p_size < 0); - p_size = next_power_of_2(p_size); - - if (p_size == shadow_atlas->size && p_16_bits == shadow_atlas->use_16_bits) { - return; - } - - // erasing atlas - if (shadow_atlas->depth.is_valid()) { - RD::get_singleton()->free(shadow_atlas->depth); - shadow_atlas->depth = RID(); - } - for (int i = 0; i < 4; i++) { - //clear subdivisions - shadow_atlas->quadrants[i].shadows.clear(); - shadow_atlas->quadrants[i].shadows.resize(1 << shadow_atlas->quadrants[i].subdivision); - } - - //erase shadow atlas reference from lights - for (const KeyValue<RID, uint32_t> &E : shadow_atlas->shadow_owners) { - LightInstance *li = light_instance_owner.get_or_null(E.key); - ERR_CONTINUE(!li); - li->shadow_atlases.erase(p_atlas); - } - - //clear owners - shadow_atlas->shadow_owners.clear(); - - shadow_atlas->size = p_size; - shadow_atlas->use_16_bits = p_16_bits; -} - -void RendererSceneRenderRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND(!shadow_atlas); - ERR_FAIL_INDEX(p_quadrant, 4); - ERR_FAIL_INDEX(p_subdivision, 16384); - - uint32_t subdiv = next_power_of_2(p_subdivision); - if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer - subdiv <<= 1; - } - - subdiv = int(Math::sqrt((float)subdiv)); - - //obtain the number that will be x*x - - if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv) { - return; - } - - //erase all data from quadrant - for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) { - if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) { - shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); - LightInstance *li = light_instance_owner.get_or_null(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); - ERR_CONTINUE(!li); - li->shadow_atlases.erase(p_atlas); - } - } - - shadow_atlas->quadrants[p_quadrant].shadows.clear(); - shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv * subdiv); - shadow_atlas->quadrants[p_quadrant].subdivision = subdiv; - - //cache the smallest subdiv (for faster allocation in light update) - - shadow_atlas->smallest_subdiv = 1 << 30; - - for (int i = 0; i < 4; i++) { - if (shadow_atlas->quadrants[i].subdivision) { - shadow_atlas->smallest_subdiv = MIN(shadow_atlas->smallest_subdiv, shadow_atlas->quadrants[i].subdivision); - } - } - - if (shadow_atlas->smallest_subdiv == 1 << 30) { - shadow_atlas->smallest_subdiv = 0; - } - - //resort the size orders, simple bublesort for 4 elements.. - - int swaps = 0; - do { - swaps = 0; - - for (int i = 0; i < 3; i++) { - if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i + 1]].subdivision) { - SWAP(shadow_atlas->size_order[i], shadow_atlas->size_order[i + 1]); - swaps++; - } - } - } while (swaps > 0); -} - -bool RendererSceneRenderRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) { - for (int i = p_quadrant_count - 1; i >= 0; i--) { - int qidx = p_in_quadrants[i]; - - if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) { - return false; - } - - //look for an empty space - int sc = shadow_atlas->quadrants[qidx].shadows.size(); - const ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr(); - - int found_free_idx = -1; //found a free one - int found_used_idx = -1; //found existing one, must steal it - uint64_t min_pass = 0; // pass of the existing one, try to use the least recently used one (LRU fashion) - - for (int j = 0; j < sc; j++) { - if (!sarr[j].owner.is_valid()) { - found_free_idx = j; - break; - } - - LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner); - ERR_CONTINUE(!sli); - - if (sli->last_scene_pass != scene_pass) { - //was just allocated, don't kill it so soon, wait a bit.. - if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) { - continue; - } - - if (found_used_idx == -1 || sli->last_scene_pass < min_pass) { - found_used_idx = j; - min_pass = sli->last_scene_pass; - } - } - } - - if (found_free_idx == -1 && found_used_idx == -1) { - continue; //nothing found - } - - if (found_free_idx == -1 && found_used_idx != -1) { - found_free_idx = found_used_idx; - } - - r_quadrant = qidx; - r_shadow = found_free_idx; - - return true; - } - - return false; -} - -bool RendererSceneRenderRD::_shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) { - for (int i = p_quadrant_count - 1; i >= 0; i--) { - int qidx = p_in_quadrants[i]; - - if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) { - return false; - } - - //look for an empty space - int sc = shadow_atlas->quadrants[qidx].shadows.size(); - const ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr(); - - int found_idx = -1; - uint64_t min_pass = 0; // sum of currently selected spots, try to get the least recently used pair - - for (int j = 0; j < sc - 1; j++) { - uint64_t pass = 0; - - if (sarr[j].owner.is_valid()) { - LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner); - ERR_CONTINUE(!sli); - - if (sli->last_scene_pass == scene_pass) { - continue; - } - - //was just allocated, don't kill it so soon, wait a bit.. - if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) { - continue; - } - pass += sli->last_scene_pass; - } - - if (sarr[j + 1].owner.is_valid()) { - LightInstance *sli = light_instance_owner.get_or_null(sarr[j + 1].owner); - ERR_CONTINUE(!sli); - - if (sli->last_scene_pass == scene_pass) { - continue; - } - - //was just allocated, don't kill it so soon, wait a bit.. - if (p_tick - sarr[j + 1].alloc_tick < shadow_atlas_realloc_tolerance_msec) { - continue; - } - pass += sli->last_scene_pass; - } - - if (found_idx == -1 || pass < min_pass) { - found_idx = j; - min_pass = pass; - - // we found two empty spots, no need to check the rest - if (pass == 0) { - break; - } - } - } - - if (found_idx == -1) { - continue; //nothing found - } - - r_quadrant = qidx; - r_shadow = found_idx; - - return true; - } - - return false; -} - -bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!shadow_atlas, false); - - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - ERR_FAIL_COND_V(!li, false); - - if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) { - return false; - } - - uint32_t quad_size = shadow_atlas->size >> 1; - int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage)); - - int valid_quadrants[4]; - int valid_quadrant_count = 0; - int best_size = -1; //best size found - int best_subdiv = -1; //subdiv for the best size - - //find the quadrants this fits into, and the best possible size it can fit into - for (int i = 0; i < 4; i++) { - int q = shadow_atlas->size_order[i]; - int sd = shadow_atlas->quadrants[q].subdivision; - if (sd == 0) { - continue; //unused - } - - int max_fit = quad_size / sd; - - if (best_size != -1 && max_fit > best_size) { - break; //too large - } - - valid_quadrants[valid_quadrant_count++] = q; - best_subdiv = sd; - - if (max_fit >= desired_fit) { - best_size = max_fit; - } - } - - ERR_FAIL_COND_V(valid_quadrant_count == 0, false); - - uint64_t tick = OS::get_singleton()->get_ticks_msec(); - - uint32_t old_key = ShadowAtlas::SHADOW_INVALID; - uint32_t old_quadrant = ShadowAtlas::SHADOW_INVALID; - uint32_t old_shadow = ShadowAtlas::SHADOW_INVALID; - int old_subdivision = -1; - - bool should_realloc = false; - bool should_redraw = false; - - if (shadow_atlas->shadow_owners.has(p_light_instance)) { - old_key = shadow_atlas->shadow_owners[p_light_instance]; - old_quadrant = (old_key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - old_shadow = old_key & ShadowAtlas::SHADOW_INDEX_MASK; - - should_realloc = shadow_atlas->quadrants[old_quadrant].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec); - should_redraw = shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].version != p_light_version; - - if (!should_realloc) { - shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = p_light_version; - //already existing, see if it should redraw or it's just OK - return should_redraw; - } - - old_subdivision = shadow_atlas->quadrants[old_quadrant].subdivision; - } - - bool is_omni = li->light_type == RS::LIGHT_OMNI; - bool found_shadow = false; - int new_quadrant = -1; - int new_shadow = -1; - - if (is_omni) { - found_shadow = _shadow_atlas_find_omni_shadows(shadow_atlas, valid_quadrants, valid_quadrant_count, old_subdivision, tick, new_quadrant, new_shadow); - } else { - found_shadow = _shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, old_subdivision, tick, new_quadrant, new_shadow); - } - - if (found_shadow) { - if (old_quadrant != ShadowAtlas::SHADOW_INVALID) { - shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = 0; - shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].owner = RID(); - - if (old_key & ShadowAtlas::OMNI_LIGHT_FLAG) { - shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow + 1].version = 0; - shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow + 1].owner = RID(); - } - } - - uint32_t new_key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; - new_key |= new_shadow; - - ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; - _shadow_atlas_invalidate_shadow(sh, p_atlas, shadow_atlas, new_quadrant, new_shadow); - - sh->owner = p_light_instance; - sh->alloc_tick = tick; - sh->version = p_light_version; - - if (is_omni) { - new_key |= ShadowAtlas::OMNI_LIGHT_FLAG; - - int new_omni_shadow = new_shadow + 1; - ShadowAtlas::Quadrant::Shadow *extra_sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_omni_shadow]; - _shadow_atlas_invalidate_shadow(extra_sh, p_atlas, shadow_atlas, new_quadrant, new_omni_shadow); - - extra_sh->owner = p_light_instance; - extra_sh->alloc_tick = tick; - extra_sh->version = p_light_version; - } - - li->shadow_atlases.insert(p_atlas); - - //update it in map - shadow_atlas->shadow_owners[p_light_instance] = new_key; - //make it dirty, as it should redraw anyway - return true; - } - - return should_redraw; -} - -void RendererSceneRenderRD::_shadow_atlas_invalidate_shadow(RendererSceneRenderRD::ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, RendererSceneRenderRD::ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx) { - if (p_shadow->owner.is_valid()) { - LightInstance *sli = light_instance_owner.get_or_null(p_shadow->owner); - uint32_t old_key = p_shadow_atlas->shadow_owners[p_shadow->owner]; - - if (old_key & ShadowAtlas::OMNI_LIGHT_FLAG) { - uint32_t s = old_key & ShadowAtlas::SHADOW_INDEX_MASK; - uint32_t omni_shadow_idx = p_shadow_idx + (s == (uint32_t)p_shadow_idx ? 1 : -1); - RendererSceneRenderRD::ShadowAtlas::Quadrant::Shadow *omni_shadow = &p_shadow_atlas->quadrants[p_quadrant].shadows.write[omni_shadow_idx]; - omni_shadow->version = 0; - omni_shadow->owner = RID(); - } - - p_shadow_atlas->shadow_owners.erase(p_shadow->owner); - p_shadow->version = 0; - p_shadow->owner = RID(); - sli->shadow_atlases.erase(p_atlas); - } -} - -void RendererSceneRenderRD::_update_directional_shadow_atlas() { - if (directional_shadow.depth.is_null() && directional_shadow.size > 0) { - RD::TextureFormat tf; - tf.format = directional_shadow.use_16_bits ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_D32_SFLOAT; - tf.width = directional_shadow.size; - tf.height = directional_shadow.size; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - directional_shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); - Vector<RID> fb_tex; - fb_tex.push_back(directional_shadow.depth); - directional_shadow.fb = RD::get_singleton()->framebuffer_create(fb_tex); - } -} -void RendererSceneRenderRD::directional_shadow_atlas_set_size(int p_size, bool p_16_bits) { - p_size = nearest_power_of_2_templated(p_size); - - if (directional_shadow.size == p_size && directional_shadow.use_16_bits == p_16_bits) { - return; - } - - directional_shadow.size = p_size; - directional_shadow.use_16_bits = p_16_bits; - - if (directional_shadow.depth.is_valid()) { - RD::get_singleton()->free(directional_shadow.depth); - directional_shadow.depth = RID(); - _base_uniforms_changed(); - } -} - -void RendererSceneRenderRD::set_directional_shadow_count(int p_count) { - directional_shadow.light_count = p_count; - directional_shadow.current_light = 0; -} - -static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p_shadow_index) { - int split_h = 1; - int split_v = 1; - - while (split_h * split_v < p_shadow_count) { - if (split_h == split_v) { - split_h <<= 1; - } else { - split_v <<= 1; - } - } - - Rect2i rect(0, 0, p_size, p_size); - rect.size.width /= split_h; - rect.size.height /= split_v; - - rect.position.x = rect.size.width * (p_shadow_index % split_h); - rect.position.y = rect.size.height * (p_shadow_index / split_h); - - return rect; -} - -int RendererSceneRenderRD::get_directional_light_shadow_size(RID p_light_intance) { - ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0); - - Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0); - - LightInstance *light_instance = light_instance_owner.get_or_null(p_light_intance); - ERR_FAIL_COND_V(!light_instance, 0); - - switch (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light)) { - case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: - break; //none - case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: - r.size.height /= 2; - break; - case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: - r.size /= 2; - break; - } - - return MAX(r.size.width, r.size.height); -} - -////////////////////////////////////////////////// - -RID RendererSceneRenderRD::light_instance_create(RID p_light) { - RID li = light_instance_owner.make_rid(LightInstance()); - - LightInstance *light_instance = light_instance_owner.get_or_null(li); - - light_instance->self = li; - light_instance->light = p_light; - light_instance->light_type = RSG::light_storage->light_get_type(p_light); - if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) { - light_instance->forward_id = _allocate_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT); - } - - return li; -} - -void RendererSceneRenderRD::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) { - LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); - ERR_FAIL_COND(!light_instance); - - light_instance->transform = p_transform; -} - -void RendererSceneRenderRD::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) { - LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); - ERR_FAIL_COND(!light_instance); - - light_instance->aabb = p_aabb; -} - -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); - - ERR_FAIL_INDEX(p_pass, 6); +/* FOG VOLUME INSTANCE */ - light_instance->shadow_transform[p_pass].camera = p_projection; - light_instance->shadow_transform[p_pass].transform = p_transform; - light_instance->shadow_transform[p_pass].farplane = p_far; - light_instance->shadow_transform[p_pass].split = p_split; - light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale; - light_instance->shadow_transform[p_pass].range_begin = p_range_begin; - light_instance->shadow_transform[p_pass].shadow_texel_size = p_shadow_texel_size; - light_instance->shadow_transform[p_pass].uv_scale = p_uv_scale; -} - -void RendererSceneRenderRD::light_instance_mark_visible(RID p_light_instance) { - LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); - ERR_FAIL_COND(!light_instance); - - light_instance->last_scene_pass = scene_pass; +RID RendererSceneRenderRD::fog_volume_instance_create(RID p_fog_volume) { + return RendererRD::Fog::get_singleton()->fog_volume_instance_create(p_fog_volume); } -RendererSceneRenderRD::ShadowCubemap *RendererSceneRenderRD::_get_shadow_cubemap(int p_size) { - if (!shadow_cubemaps.has(p_size)) { - ShadowCubemap sc; - { - RD::TextureFormat tf; - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; - tf.width = p_size; - tf.height = p_size; - tf.texture_type = RD::TEXTURE_TYPE_CUBE; - tf.array_layers = 6; - tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - sc.cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - - for (int i = 0; i < 6; i++) { - RID side_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sc.cubemap, i, 0); - Vector<RID> fbtex; - fbtex.push_back(side_texture); - sc.side_fb[i] = RD::get_singleton()->framebuffer_create(fbtex); - } - - shadow_cubemaps[p_size] = sc; - } - - return &shadow_cubemaps[p_size]; +void RendererSceneRenderRD::fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) { + RendererRD::Fog::get_singleton()->fog_volume_instance_set_transform(p_fog_volume_instance, p_transform); } -////////////////////////// - -RID RendererSceneRenderRD::decal_instance_create(RID p_decal) { - DecalInstance di; - di.decal = p_decal; - di.forward_id = _allocate_forward_id(FORWARD_ID_TYPE_DECAL); - return decal_instance_owner.make_rid(di); +void RendererSceneRenderRD::fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) { + RendererRD::Fog::get_singleton()->fog_volume_instance_set_active(p_fog_volume_instance, p_active); } -void RendererSceneRenderRD::decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) { - DecalInstance *di = decal_instance_owner.get_or_null(p_decal); - ERR_FAIL_COND(!di); - di->transform = p_transform; +RID RendererSceneRenderRD::fog_volume_instance_get_volume(RID p_fog_volume_instance) const { + return RendererRD::Fog::get_singleton()->fog_volume_instance_get_volume(p_fog_volume_instance); } -///////////////////////////////// - -RID RendererSceneRenderRD::lightmap_instance_create(RID p_lightmap) { - LightmapInstance li; - li.lightmap = p_lightmap; - return lightmap_instance_owner.make_rid(li); -} -void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) { - LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap); - ERR_FAIL_COND(!li); - li->transform = p_transform; +Vector3 RendererSceneRenderRD::fog_volume_instance_get_position(RID p_fog_volume_instance) const { + return RendererRD::Fog::get_singleton()->fog_volume_instance_get_position(p_fog_volume_instance); } -///////////////////////////////// +/* VOXEL GI */ RID RendererSceneRenderRD::voxel_gi_instance_create(RID p_base) { return gi.voxel_gi_instance_create(p_base); } void RendererSceneRenderRD::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { + if (!is_dynamic_gi_supported()) { + return; + } + gi.voxel_gi_instance_set_transform_to_data(p_probe, p_xform); } @@ -1220,7 +316,7 @@ void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_ins return; } - gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this); + gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects); } void RendererSceneRenderRD::_debug_sdfgi_probes(Ref<RenderSceneBuffersRD> 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) { @@ -1243,9 +339,6 @@ Ref<RenderSceneBuffers> RendererSceneRenderRD::render_buffers_create() { rb->set_can_be_storage(_render_buffers_can_be_storage()); rb->set_max_cluster_elements(max_cluster_elements); rb->set_base_data_format(_render_buffers_get_color_format()); - if (ss_effects) { - rb->set_sseffects(ss_effects); - } if (vrs) { rb->set_vrs(vrs); } @@ -1306,136 +399,6 @@ void RendererSceneRenderRD::_allocate_luminance_textures(Ref<RenderSceneBuffersR } } -void RendererSceneRenderRD::_process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera) { - ERR_FAIL_COND(p_render_buffers.is_null()); - - Size2i internal_size = p_render_buffers->get_internal_size(); - bool can_use_effects = internal_size.x >= 8 && internal_size.y >= 8; - - if (!can_use_effects) { - //just copy - return; - } - - p_render_buffers->allocate_blur_textures(); - - for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) { - RID internal_texture = p_render_buffers->get_internal_texture(v); - RID depth_texture = p_render_buffers->get_depth_texture(v); - ss_effects->sub_surface_scattering(p_render_buffers, internal_texture, depth_texture, p_camera, internal_size, sss_scale, sss_depth_scale, sss_quality); - } -} - -void RendererSceneRenderRD::_process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive) { - ERR_FAIL_NULL(ss_effects); - ERR_FAIL_COND(p_render_buffers.is_null()); - - Size2i internal_size = p_render_buffers->get_internal_size(); - bool can_use_effects = internal_size.x >= 8 && internal_size.y >= 8; - uint32_t view_count = p_render_buffers->get_view_count(); - - if (!can_use_effects) { - //just copy - copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), RID(), view_count); - return; - } - - ERR_FAIL_COND(p_environment.is_null()); - ERR_FAIL_COND(!environment_get_ssr_enabled(p_environment)); - - Size2i half_size = Size2i(internal_size.x / 2, internal_size.y / 2); - if (p_render_buffers->ssr.output.is_null()) { - ss_effects->ssr_allocate_buffers(p_render_buffers->ssr, _render_buffers_get_color_format(), ssr_roughness_quality, half_size, view_count); - } - RID texture_slices[RendererSceneRender::MAX_RENDER_VIEWS]; - RID depth_slices[RendererSceneRender::MAX_RENDER_VIEWS]; - for (uint32_t v = 0; v < view_count; v++) { - texture_slices[v] = p_render_buffers->get_internal_texture(v); - depth_slices[v] = p_render_buffers->get_depth_texture(v); - } - ss_effects->screen_space_reflection(p_render_buffers->ssr, texture_slices, p_normal_slices, ssr_roughness_quality, p_metallic_slices, depth_slices, half_size, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), view_count, p_projections, p_eye_offsets); - copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), p_render_buffers->ssr.output, view_count); -} - -void RendererSceneRenderRD::_process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection) { - ERR_FAIL_NULL(ss_effects); - ERR_FAIL_COND(p_render_buffers.is_null()); - ERR_FAIL_COND(p_environment.is_null()); - - RENDER_TIMESTAMP("Process SSAO"); - - RendererRD::SSEffects::SSAOSettings settings; - settings.radius = environment_get_ssao_radius(p_environment); - settings.intensity = environment_get_ssao_intensity(p_environment); - settings.power = environment_get_ssao_power(p_environment); - settings.detail = environment_get_ssao_detail(p_environment); - settings.horizon = environment_get_ssao_horizon(p_environment); - settings.sharpness = environment_get_ssao_sharpness(p_environment); - - settings.quality = ssao_quality; - settings.half_size = ssao_half_size; - settings.adaptive_target = ssao_adaptive_target; - settings.blur_passes = ssao_blur_passes; - settings.fadeout_from = ssao_fadeout_from; - settings.fadeout_to = ssao_fadeout_to; - settings.full_screen_size = p_render_buffers->get_internal_size(); - - ss_effects->ssao_allocate_buffers(p_render_buffers->ss_effects.ssao, settings, p_render_buffers->ss_effects.linear_depth); - ss_effects->generate_ssao(p_render_buffers->ss_effects.ssao, p_normal_buffer, p_projection, settings); -} - -void RendererSceneRenderRD::_process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform) { - ERR_FAIL_NULL(ss_effects); - ERR_FAIL_COND(p_render_buffers.is_null()); - ERR_FAIL_COND(p_environment.is_null()); - - RENDER_TIMESTAMP("Process SSIL"); - - RendererRD::SSEffects::SSILSettings settings; - settings.radius = environment_get_ssil_radius(p_environment); - settings.intensity = environment_get_ssil_intensity(p_environment); - settings.sharpness = environment_get_ssil_sharpness(p_environment); - settings.normal_rejection = environment_get_ssil_normal_rejection(p_environment); - - settings.quality = ssil_quality; - settings.half_size = ssil_half_size; - settings.adaptive_target = ssil_adaptive_target; - settings.blur_passes = ssil_blur_passes; - settings.fadeout_from = ssil_fadeout_from; - settings.fadeout_to = ssil_fadeout_to; - settings.full_screen_size = p_render_buffers->get_internal_size(); - - Projection correction; - correction.set_depth_correction(true); - Projection projection = correction * p_projection; - Transform3D transform = p_transform; - transform.set_origin(Vector3(0.0, 0.0, 0.0)); - Projection last_frame_projection = p_render_buffers->ss_effects.last_frame_projection * Projection(p_render_buffers->ss_effects.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse(); - - ss_effects->ssil_allocate_buffers(p_render_buffers->ss_effects.ssil, settings, p_render_buffers->ss_effects.linear_depth); - ss_effects->screen_space_indirect_lighting(p_render_buffers->ss_effects.ssil, p_normal_buffer, p_projection, last_frame_projection, settings); - p_render_buffers->ss_effects.last_frame_projection = projection; - p_render_buffers->ss_effects.last_frame_transform = transform; -} - -void RendererSceneRenderRD::_copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers) { - ERR_FAIL_COND(p_render_buffers.is_null()); - - if (p_render_buffers->ss_effects.ssil.last_frame.is_valid()) { - Size2i size = p_render_buffers->get_internal_size(); - RID texture = p_render_buffers->get_internal_texture(); - copy_effects->copy_to_rect(texture, p_render_buffers->ss_effects.ssil.last_frame, Rect2i(0, 0, size.x, size.y)); - - int width = size.x; - int height = size.y; - for (int i = 0; i < p_render_buffers->ss_effects.ssil.last_frame_slices.size() - 1; i++) { - width = MAX(1, width >> 1); - height = MAX(1, height >> 1); - copy_effects->make_mipmap(p_render_buffers->ss_effects.ssil.last_frame_slices[i], p_render_buffers->ss_effects.ssil.last_frame_slices[i + 1], Size2i(width, height)); - } - } -} - void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) { Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; ERR_FAIL_COND(rb.is_null()); @@ -1851,7 +814,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD> if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) { if (p_shadow_atlas.is_valid()) { - RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); + RID shadow_atlas_texture = RendererRD::LightStorage::get_singleton()->shadow_atlas_get_texture(p_shadow_atlas); if (shadow_atlas_texture.is_null()) { shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); @@ -1863,9 +826,9 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD> } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) { - if (directional_shadow_get_texture().is_valid()) { - RID shadow_atlas_texture = directional_shadow_get_texture(); - Size2 rtsize = texture_storage->render_target_get_size(render_target); + if (RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture().is_valid()) { + RID shadow_atlas_texture = RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture(); + Size2i rtsize = texture_storage->render_target_get_size(render_target); copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize / 2), false, true); } @@ -1875,7 +838,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD> RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture(); if (decal_atlas.is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(render_target); + Size2i rtsize = texture_storage->render_target_get_size(render_target); copy_effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize / 2), false, false, true); } @@ -1883,43 +846,26 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD> if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) { if (p_render_buffers->luminance.current.is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(render_target); + Size2i rtsize = texture_storage->render_target_get_size(render_target); copy_effects->copy_to_fb_rect(p_render_buffers->luminance.current, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize / 8), false, true); } } - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && p_render_buffers->ss_effects.ssao.ao_final.is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(render_target); - copy_effects->copy_to_fb_rect(p_render_buffers->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, true); - } - - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSIL && p_render_buffers->ss_effects.ssil.ssil_final.is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(render_target); - copy_effects->copy_to_fb_rect(p_render_buffers->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); - } - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(render_target); copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); } - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) { - Size2 rtsize = texture_storage->render_target_get_size(render_target); - RID ambient_texture = p_render_buffers->get_texture(RB_SCOPE_GI, RB_TEX_AMBIENT); - RID reflection_texture = p_render_buffers->get_texture(RB_SCOPE_GI, RB_TEX_REFLECTION); - copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture, p_render_buffers->get_view_count() > 1); - } - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) { if (p_occlusion_buffer.is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(render_target); + Size2i rtsize = texture_storage->render_target_get_size(render_target); copy_effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize), true, false); } } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS && _render_buffers_get_velocity_texture(p_render_buffers).is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(render_target); + Size2i rtsize = texture_storage->render_target_get_size(render_target); copy_effects->copy_to_fb_rect(_render_buffers_get_velocity_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); } } @@ -1944,19 +890,6 @@ void RendererSceneRenderRD::gi_set_use_half_resolution(bool p_enable) { gi.half_resolution = p_enable; } -void RendererSceneRenderRD::sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) { - sss_quality = p_quality; -} - -RS::SubSurfaceScatteringQuality RendererSceneRenderRD::sub_surface_scattering_get_quality() const { - return sss_quality; -} - -void RendererSceneRenderRD::sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) { - sss_scale = p_scale; - sss_depth_scale = p_depth_scale; -} - 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"); @@ -2074,788 +1007,31 @@ bool RendererSceneRenderRD::is_using_radiance_cubemap_array() const { return sky.sky_use_cubemap_array; } -void RendererSceneRenderRD::_setup_reflections(RenderDataRD *p_render_data, const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) { - RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); - cluster.reflection_count = 0; - - for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) { - if (cluster.reflection_count == cluster.max_reflections) { - break; - } +void RendererSceneRenderRD::_update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers) { + if (p_render_buffers.is_valid() && vrs) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_reflections[i]); - if (!rpi) { - continue; - } - - cluster.reflection_sort[cluster.reflection_count].instance = rpi; - cluster.reflection_sort[cluster.reflection_count].depth = -p_camera_inverse_transform.xform(rpi->transform.origin).z; - cluster.reflection_count++; - } - - if (cluster.reflection_count > 0) { - SortArray<Cluster::InstanceSort<ReflectionProbeInstance>> sort_array; - sort_array.sort(cluster.reflection_sort, cluster.reflection_count); - } - - bool using_forward_ids = _uses_forward_ids(); - for (uint32_t i = 0; i < cluster.reflection_count; i++) { - ReflectionProbeInstance *rpi = cluster.reflection_sort[i].instance; - - if (using_forward_ids) { - _map_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id, i); - } - - RID base_probe = rpi->probe; - - Cluster::ReflectionData &reflection_ubo = cluster.reflections[i]; - - Vector3 extents = light_storage->reflection_probe_get_extents(base_probe); - - rpi->cull_mask = light_storage->reflection_probe_get_cull_mask(base_probe); - - reflection_ubo.box_extents[0] = extents.x; - reflection_ubo.box_extents[1] = extents.y; - reflection_ubo.box_extents[2] = extents.z; - reflection_ubo.index = rpi->atlas_index; - - Vector3 origin_offset = light_storage->reflection_probe_get_origin_offset(base_probe); - - reflection_ubo.box_offset[0] = origin_offset.x; - reflection_ubo.box_offset[1] = origin_offset.y; - reflection_ubo.box_offset[2] = origin_offset.z; - reflection_ubo.mask = light_storage->reflection_probe_get_cull_mask(base_probe); - - reflection_ubo.intensity = light_storage->reflection_probe_get_intensity(base_probe); - reflection_ubo.ambient_mode = light_storage->reflection_probe_get_ambient_mode(base_probe); - - reflection_ubo.exterior = !light_storage->reflection_probe_is_interior(base_probe); - reflection_ubo.box_project = light_storage->reflection_probe_is_box_projection(base_probe); - reflection_ubo.exposure_normalization = 1.0; - - if (p_render_data->camera_attributes.is_valid()) { - float exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); - reflection_ubo.exposure_normalization = exposure / light_storage->reflection_probe_get_baked_exposure(base_probe); - } - - Color ambient_linear = light_storage->reflection_probe_get_ambient_color(base_probe).srgb_to_linear(); - float interior_ambient_energy = light_storage->reflection_probe_get_ambient_color_energy(base_probe); - reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy; - reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy; - reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy; - - Transform3D transform = rpi->transform; - Transform3D proj = (p_camera_inverse_transform * transform).inverse(); - RendererRD::MaterialStorage::store_transform(proj, reflection_ubo.local_matrix); - - if (current_cluster_builder != nullptr) { - current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, transform, extents); - } - - rpi->last_pass = RSG::rasterizer->get_frame_number(); - } - - if (cluster.reflection_count) { - RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, cluster.reflection_count * sizeof(Cluster::ReflectionData), cluster.reflections, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); - } -} - -void RendererSceneRenderRD::_setup_lights(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) { - RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); - - Transform3D inverse_transform = p_camera_transform.affine_inverse(); - - r_directional_light_count = 0; - r_positional_light_count = 0; - - Plane camera_plane(-p_camera_transform.basis.get_column(Vector3::AXIS_Z).normalized(), p_camera_transform.origin); - - cluster.omni_light_count = 0; - cluster.spot_light_count = 0; - - r_directional_light_soft_shadows = false; - - for (int i = 0; i < (int)p_lights.size(); i++) { - LightInstance *li = light_instance_owner.get_or_null(p_lights[i]); - if (!li) { - continue; - } - RID base = li->light; - - ERR_CONTINUE(base.is_null()); - - RS::LightType type = light_storage->light_get_type(base); - switch (type) { - case RS::LIGHT_DIRECTIONAL: { - if (r_directional_light_count >= cluster.max_directional_lights || light_storage->light_directional_get_sky_mode(base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { - continue; - } - - Cluster::DirectionalLightData &light_data = cluster.directional_lights[r_directional_light_count]; - - Transform3D light_transform = li->transform; - - Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized(); - - light_data.direction[0] = direction.x; - light_data.direction[1] = direction.y; - light_data.direction[2] = direction.z; - - float sign = light_storage->light_is_negative(base) ? -1 : 1; - - light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); - - if (is_using_physical_light_units()) { - light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY); - } else { - light_data.energy *= Math_PI; - } - - if (p_render_data->camera_attributes.is_valid()) { - light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); - } - - Color linear_col = light_storage->light_get_color(base).srgb_to_linear(); - light_data.color[0] = linear_col.r; - light_data.color[1] = linear_col.g; - light_data.color[2] = linear_col.b; - - light_data.specular = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR); - light_data.volumetric_fog_energy = light_storage->light_get_param(base, RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY); - light_data.mask = light_storage->light_get_cull_mask(base); - - float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); - - light_data.size = 1.0 - Math::cos(Math::deg_to_rad(size)); //angle to cosine offset - - if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) { - WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet."); - } - - light_data.shadow_opacity = (p_using_shadows && light_storage->light_has_shadow(base)) - ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) - : 0.0; - - float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); - if (angular_diameter > 0.0) { - // I know tan(0) is 0, but let's not risk it with numerical precision. - // technically this will keep expanding until reaching the sun, but all we care - // is expand until we reach the radius of the near plane (there can't be more occluders than that) - angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter)); - if (light_storage->light_has_shadow(base) && light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR) > 0.0) { - // Only enable PCSS-like soft shadows if blurring is enabled. - // Otherwise, performance would decrease with no visual difference. - r_directional_light_soft_shadows = true; - } - } else { - angular_diameter = 0.0; - } - - if (light_data.shadow_opacity > 0.001) { - RS::LightDirectionalShadowMode smode = light_storage->light_directional_get_shadow_mode(base); - - int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3); - 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; - Projection matrix = li->shadow_transform[j].camera; - float split = li->shadow_transform[MIN(limit, j)].split; - - Projection bias; - bias.set_light_bias(); - Projection rectm; - rectm.set_light_atlas_rect(atlas_rect); - - Transform3D modelview = (inverse_transform * li->shadow_transform[j].transform).inverse(); - - 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; - light_data.shadow_normal_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size; - light_data.shadow_transmittance_bias[j] = light_storage->light_get_transmittance_bias(base) * bias_scale; - light_data.shadow_z_range[j] = li->shadow_transform[j].farplane; - light_data.shadow_range_begin[j] = li->shadow_transform[j].range_begin; - RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrices[j]); - - Vector2 uv_scale = li->shadow_transform[j].uv_scale; - uv_scale *= atlas_rect.size; //adapt to atlas size - switch (j) { - case 0: { - light_data.uv_scale1[0] = uv_scale.x; - light_data.uv_scale1[1] = uv_scale.y; - } break; - case 1: { - light_data.uv_scale2[0] = uv_scale.x; - light_data.uv_scale2[1] = uv_scale.y; - } break; - case 2: { - light_data.uv_scale3[0] = uv_scale.x; - light_data.uv_scale3[1] = uv_scale.y; - } break; - case 3: { - light_data.uv_scale4[0] = uv_scale.x; - light_data.uv_scale4[1] = uv_scale.y; - } break; - } - } - - float fade_start = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START); - light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep - light_data.fade_to = -light_data.shadow_split_offsets[3]; - - light_data.soft_shadow_scale = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR); - light_data.softshadow_angle = angular_diameter; - light_data.bake_mode = light_storage->light_get_bake_mode(base); - - if (angular_diameter <= 0.0) { - light_data.soft_shadow_scale *= directional_shadow_quality_radius_get(); // Only use quality radius for PCF - } - } - - r_directional_light_count++; - } break; - case RS::LIGHT_OMNI: { - if (cluster.omni_light_count >= cluster.max_lights) { - continue; - } - - const real_t distance = camera_plane.distance_to(li->transform.origin); - - if (light_storage->light_is_distance_fade_enabled(li->light)) { - const float fade_begin = light_storage->light_get_distance_fade_begin(li->light); - const float fade_length = light_storage->light_get_distance_fade_length(li->light); - - if (distance > fade_begin) { - if (distance > fade_begin + fade_length) { - // Out of range, don't draw this light to improve performance. - continue; - } - } - } - - cluster.omni_light_sort[cluster.omni_light_count].instance = li; - cluster.omni_light_sort[cluster.omni_light_count].depth = distance; - cluster.omni_light_count++; - } break; - case RS::LIGHT_SPOT: { - if (cluster.spot_light_count >= cluster.max_lights) { - continue; - } - - const real_t distance = camera_plane.distance_to(li->transform.origin); - - if (light_storage->light_is_distance_fade_enabled(li->light)) { - const float fade_begin = light_storage->light_get_distance_fade_begin(li->light); - const float fade_length = light_storage->light_get_distance_fade_length(li->light); - - if (distance > fade_begin) { - if (distance > fade_begin + fade_length) { - // Out of range, don't draw this light to improve performance. - continue; - } - } - } - - cluster.spot_light_sort[cluster.spot_light_count].instance = li; - cluster.spot_light_sort[cluster.spot_light_count].depth = distance; - cluster.spot_light_count++; - } break; - } - - li->last_pass = RSG::rasterizer->get_frame_number(); - } - - if (cluster.omni_light_count) { - SortArray<Cluster::InstanceSort<LightInstance>> sorter; - sorter.sort(cluster.omni_light_sort, cluster.omni_light_count); - } - - if (cluster.spot_light_count) { - SortArray<Cluster::InstanceSort<LightInstance>> sorter; - sorter.sort(cluster.spot_light_sort, cluster.spot_light_count); - } - - ShadowAtlas *shadow_atlas = nullptr; - - if (p_shadow_atlas.is_valid() && p_using_shadows) { - shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); - } - - bool using_forward_ids = _uses_forward_ids(); - - for (uint32_t i = 0; i < (cluster.omni_light_count + cluster.spot_light_count); i++) { - uint32_t index = (i < cluster.omni_light_count) ? i : i - (cluster.omni_light_count); - Cluster::LightData &light_data = (i < cluster.omni_light_count) ? cluster.omni_lights[index] : cluster.spot_lights[index]; - RS::LightType type = (i < cluster.omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT; - LightInstance *li = (i < cluster.omni_light_count) ? cluster.omni_light_sort[index].instance : cluster.spot_light_sort[index].instance; - RID base = li->light; - - if (using_forward_ids) { - _map_forward_id(type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT, li->forward_id, index); - } - - Transform3D light_transform = li->transform; - - float sign = light_storage->light_is_negative(base) ? -1 : 1; - Color linear_col = light_storage->light_get_color(base).srgb_to_linear(); - - light_data.attenuation = light_storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION); - - // Reuse fade begin, fade length and distance for shadow LOD determination later. - float fade_begin = 0.0; - float fade_shadow = 0.0; - float fade_length = 0.0; - real_t distance = 0.0; - - float fade = 1.0; - float shadow_opacity_fade = 1.0; - if (light_storage->light_is_distance_fade_enabled(li->light)) { - fade_begin = light_storage->light_get_distance_fade_begin(li->light); - fade_shadow = light_storage->light_get_distance_fade_shadow(li->light); - fade_length = light_storage->light_get_distance_fade_length(li->light); - distance = camera_plane.distance_to(li->transform.origin); - - // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player. - if (distance > fade_begin) { - fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length); - } - - if (distance > fade_shadow) { - shadow_opacity_fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_shadow) / fade_length); - } - } - - float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * fade; - - if (is_using_physical_light_units()) { - energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY); - - // Convert from Luminous Power to Luminous Intensity - if (type == RS::LIGHT_OMNI) { - energy *= 1.0 / (Math_PI * 4.0); - } else { - // Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle. - // We make this assumption to keep them easy to control. - energy *= 1.0 / Math_PI; - } - } else { - energy *= Math_PI; - } - - if (p_render_data->camera_attributes.is_valid()) { - energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); - } - - light_data.color[0] = linear_col.r * energy; - light_data.color[1] = linear_col.g * energy; - light_data.color[2] = linear_col.b * energy; - light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0; - light_data.volumetric_fog_energy = light_storage->light_get_param(base, RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY); - light_data.bake_mode = light_storage->light_get_bake_mode(base); - - float radius = MAX(0.001, light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE)); - light_data.inv_radius = 1.0 / radius; - - Vector3 pos = inverse_transform.xform(light_transform.origin); - - light_data.position[0] = pos.x; - light_data.position[1] = pos.y; - light_data.position[2] = pos.z; - - Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized(); - - light_data.direction[0] = direction.x; - light_data.direction[1] = direction.y; - light_data.direction[2] = direction.z; - - float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); - - light_data.size = size; - - light_data.inv_spot_attenuation = 1.0f / light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION); - float spot_angle = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE); - light_data.cos_spot_angle = Math::cos(Math::deg_to_rad(spot_angle)); - - light_data.mask = light_storage->light_get_cull_mask(base); - - light_data.atlas_rect[0] = 0; - light_data.atlas_rect[1] = 0; - light_data.atlas_rect[2] = 0; - light_data.atlas_rect[3] = 0; - - RID projector = light_storage->light_get_projector(base); - - if (projector.is_valid()) { - Rect2 rect = texture_storage->decal_atlas_get_texture_rect(projector); - - if (type == RS::LIGHT_SPOT) { - light_data.projector_rect[0] = rect.position.x; - light_data.projector_rect[1] = rect.position.y + rect.size.height; //flip because shadow is flipped - light_data.projector_rect[2] = rect.size.width; - light_data.projector_rect[3] = -rect.size.height; - } else { - light_data.projector_rect[0] = rect.position.x; - light_data.projector_rect[1] = rect.position.y; - light_data.projector_rect[2] = rect.size.width; - light_data.projector_rect[3] = rect.size.height * 0.5; //used by dp, so needs to be half - } - } else { - light_data.projector_rect[0] = 0; - light_data.projector_rect[1] = 0; - light_data.projector_rect[2] = 0; - light_data.projector_rect[3] = 0; - } - - const bool needs_shadow = - shadow_atlas && - shadow_atlas->shadow_owners.has(li->self) && - p_using_shadows && - light_storage->light_has_shadow(base); - - bool in_shadow_range = true; - if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) { - if (distance > light_storage->light_get_distance_fade_shadow(li->light) + light_storage->light_get_distance_fade_length(li->light)) { - // Out of range, don't draw shadows to improve performance. - in_shadow_range = false; - } - } - - if (needs_shadow && in_shadow_range) { - // fill in the shadow information - - light_data.shadow_opacity = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) * shadow_opacity_fade; - - float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas); - light_data.shadow_normal_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0; - - if (type == RS::LIGHT_SPOT) { - light_data.shadow_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0; - } else { //omni - light_data.shadow_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS); - } - - light_data.transmittance_bias = light_storage->light_get_transmittance_bias(base); - - Vector2i omni_offset; - Rect2 rect = light_instance_get_shadow_atlas_rect(li->self, p_shadow_atlas, omni_offset); - - light_data.atlas_rect[0] = rect.position.x; - light_data.atlas_rect[1] = rect.position.y; - light_data.atlas_rect[2] = rect.size.width; - light_data.atlas_rect[3] = rect.size.height; - - light_data.soft_shadow_scale = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR); - - if (type == RS::LIGHT_OMNI) { - Transform3D proj = (inverse_transform * light_transform).inverse(); - - RendererRD::MaterialStorage::store_transform(proj, 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. - light_data.soft_shadow_size = size; - } else { - light_data.soft_shadow_size = 0.0; - light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF - } - - light_data.direction[0] = omni_offset.x * float(rect.size.width); - light_data.direction[1] = omni_offset.y * float(rect.size.height); - } else if (type == RS::LIGHT_SPOT) { - Transform3D modelview = (inverse_transform * light_transform).inverse(); - Projection bias; - bias.set_light_bias(); - - 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. - Projection cm = li->shadow_transform[0].camera; - float half_np = cm.get_z_near() * Math::tan(Math::deg_to_rad(spot_angle)); - light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width; - } else { - light_data.soft_shadow_size = 0.0; - light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF - } - } - } else { - light_data.shadow_opacity = 0.0; - } - - li->cull_mask = light_storage->light_get_cull_mask(base); - - if (current_cluster_builder != nullptr) { - current_cluster_builder->add_light(type == RS::LIGHT_SPOT ? ClusterBuilderRD::LIGHT_TYPE_SPOT : ClusterBuilderRD::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle); - } - - r_positional_light_count++; - } - - //update without barriers - if (cluster.omni_light_count) { - RD::get_singleton()->buffer_update(cluster.omni_light_buffer, 0, sizeof(Cluster::LightData) * cluster.omni_light_count, cluster.omni_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); - } - - if (cluster.spot_light_count) { - RD::get_singleton()->buffer_update(cluster.spot_light_buffer, 0, sizeof(Cluster::LightData) * cluster.spot_light_count, cluster.spot_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); - } - - if (r_directional_light_count) { - RD::get_singleton()->buffer_update(cluster.directional_light_buffer, 0, sizeof(Cluster::DirectionalLightData) * r_directional_light_count, cluster.directional_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); - } -} - -void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) { - RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - - Transform3D uv_xform; - uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0)); - uv_xform.origin = Vector3(-1.0, 0.0, -1.0); - - uint32_t decal_count = p_decals.size(); - - cluster.decal_count = 0; - - for (uint32_t i = 0; i < decal_count; i++) { - if (cluster.decal_count == cluster.max_decals) { - break; - } - - DecalInstance *di = decal_instance_owner.get_or_null(p_decals[i]); - if (!di) { - continue; - } - RID decal = di->decal; - - Transform3D xform = di->transform; - - real_t distance = -p_camera_inverse_xform.xform(xform.origin).z; - - if (texture_storage->decal_is_distance_fade_enabled(decal)) { - float fade_begin = texture_storage->decal_get_distance_fade_begin(decal); - float fade_length = texture_storage->decal_get_distance_fade_length(decal); - - if (distance > fade_begin) { - if (distance > fade_begin + fade_length) { - continue; // do not use this decal, its invisible - } - } - } - - cluster.decal_sort[cluster.decal_count].instance = di; - cluster.decal_sort[cluster.decal_count].depth = distance; - cluster.decal_count++; - } - - if (cluster.decal_count > 0) { - SortArray<Cluster::InstanceSort<DecalInstance>> sort_array; - sort_array.sort(cluster.decal_sort, cluster.decal_count); - } - - bool using_forward_ids = _uses_forward_ids(); - for (uint32_t i = 0; i < cluster.decal_count; i++) { - DecalInstance *di = cluster.decal_sort[i].instance; - RID decal = di->decal; - - if (using_forward_ids) { - _map_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id, i); - } - - di->cull_mask = texture_storage->decal_get_cull_mask(decal); - - Transform3D xform = di->transform; - float fade = 1.0; - - if (texture_storage->decal_is_distance_fade_enabled(decal)) { - const real_t distance = -p_camera_inverse_xform.xform(xform.origin).z; - const float fade_begin = texture_storage->decal_get_distance_fade_begin(decal); - const float fade_length = texture_storage->decal_get_distance_fade_length(decal); - - if (distance > fade_begin) { - // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player. - fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length); - } - } - - Cluster::DecalData &dd = cluster.decals[i]; - - Vector3 decal_extents = texture_storage->decal_get_extents(decal); - - Transform3D scale_xform; - scale_xform.basis.scale(decal_extents); - Transform3D to_decal_xform = (p_camera_inverse_xform * di->transform * scale_xform * uv_xform).affine_inverse(); - RendererRD::MaterialStorage::store_transform(to_decal_xform, dd.xform); - - Vector3 normal = xform.basis.get_column(Vector3::AXIS_Y).normalized(); - normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine - - dd.normal[0] = normal.x; - dd.normal[1] = normal.y; - dd.normal[2] = normal.z; - dd.normal_fade = texture_storage->decal_get_normal_fade(decal); - - RID albedo_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO); - RID emission_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION); - if (albedo_tex.is_valid()) { - Rect2 rect = texture_storage->decal_atlas_get_texture_rect(albedo_tex); - dd.albedo_rect[0] = rect.position.x; - dd.albedo_rect[1] = rect.position.y; - dd.albedo_rect[2] = rect.size.x; - dd.albedo_rect[3] = rect.size.y; - } else { - if (!emission_tex.is_valid()) { - continue; //no albedo, no emission, no decal. - } - dd.albedo_rect[0] = 0; - dd.albedo_rect[1] = 0; - dd.albedo_rect[2] = 0; - dd.albedo_rect[3] = 0; - } - - RID normal_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL); + RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_buffers->get_render_target()); + if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) { + RID vrs_texture = p_render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE); - if (normal_tex.is_valid()) { - Rect2 rect = texture_storage->decal_atlas_get_texture_rect(normal_tex); - dd.normal_rect[0] = rect.position.x; - dd.normal_rect[1] = rect.position.y; - dd.normal_rect[2] = rect.size.x; - dd.normal_rect[3] = rect.size.y; + // We use get_cache_multipass instead of get_cache_multiview because the default behavior is for + // our vrs_texture to be used as the VRS attachment. In this particular case we're writing to it + // so it needs to be set as our color attachment - Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized(); - RendererRD::MaterialStorage::store_basis_3x4(normal_xform, dd.normal_xform); - } else { - dd.normal_rect[0] = 0; - dd.normal_rect[1] = 0; - dd.normal_rect[2] = 0; - dd.normal_rect[3] = 0; - } + Vector<RID> textures; + textures.push_back(vrs_texture); - RID orm_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM); - if (orm_tex.is_valid()) { - Rect2 rect = texture_storage->decal_atlas_get_texture_rect(orm_tex); - dd.orm_rect[0] = rect.position.x; - dd.orm_rect[1] = rect.position.y; - dd.orm_rect[2] = rect.size.x; - dd.orm_rect[3] = rect.size.y; - } else { - dd.orm_rect[0] = 0; - dd.orm_rect[1] = 0; - dd.orm_rect[2] = 0; - dd.orm_rect[3] = 0; - } + Vector<RD::FramebufferPass> passes; + RD::FramebufferPass pass; + pass.color_attachments.push_back(0); + passes.push_back(pass); - if (emission_tex.is_valid()) { - Rect2 rect = texture_storage->decal_atlas_get_texture_rect(emission_tex); - dd.emission_rect[0] = rect.position.x; - dd.emission_rect[1] = rect.position.y; - dd.emission_rect[2] = rect.size.x; - dd.emission_rect[3] = rect.size.y; - } else { - dd.emission_rect[0] = 0; - dd.emission_rect[1] = 0; - dd.emission_rect[2] = 0; - dd.emission_rect[3] = 0; - } + RID vrs_fb = FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, p_render_buffers->get_view_count()); - Color modulate = texture_storage->decal_get_modulate(decal); - dd.modulate[0] = modulate.r; - dd.modulate[1] = modulate.g; - dd.modulate[2] = modulate.b; - dd.modulate[3] = modulate.a * fade; - dd.emission_energy = texture_storage->decal_get_emission_energy(decal) * fade; - dd.albedo_mix = texture_storage->decal_get_albedo_mix(decal); - dd.mask = texture_storage->decal_get_cull_mask(decal); - dd.upper_fade = texture_storage->decal_get_upper_fade(decal); - dd.lower_fade = texture_storage->decal_get_lower_fade(decal); - - if (current_cluster_builder != nullptr) { - current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, xform, decal_extents); + vrs->update_vrs_texture(vrs_fb, p_render_buffers->get_render_target()); } } - - if (cluster.decal_count > 0) { - RD::get_singleton()->buffer_update(cluster.decal_buffer, 0, sizeof(Cluster::DecalData) * cluster.decal_count, cluster.decals, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// FOG SHADER - -void RendererSceneRenderRD::_update_volumetric_fog(Ref<RenderSceneBuffersRD> 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 - ERR_FAIL_COND(p_render_buffers.is_null()); - - // These should be available for our clustered renderer, at some point _update_volumetric_fog should be called by the renderer implemetentation itself - ERR_FAIL_COND(!p_render_buffers->has_custom_data(RB_SCOPE_GI)); - Ref<RendererRD::GI::RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI); - - Ref<RendererRD::GI::SDFGI> sdfgi; - if (p_render_buffers->has_custom_data(RB_SCOPE_SDFGI)) { - sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI); - } - - Size2i size = p_render_buffers->get_internal_size(); - float ratio = float(size.x) / float((size.x + size.y) / 2); - uint32_t target_width = uint32_t(float(volumetric_fog_size) * ratio); - uint32_t target_height = uint32_t(float(volumetric_fog_size) / ratio); - - if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { - Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); - //validate - if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment) || fog->width != target_width || fog->height != target_height || fog->depth != volumetric_fog_depth) { - p_render_buffers->set_custom_data(RB_SCOPE_FOG, Ref<RenderBufferCustomDataRD>()); - } - } - - if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment)) { - //no reason to enable or update, bye - return; - } - - if (p_environment.is_valid() && environment_get_volumetric_fog_enabled(p_environment) && !p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { - //required volumetric fog but not existing, create - Ref<RendererRD::Fog::VolumetricFog> fog; - - fog.instantiate(); - fog->init(Vector3i(target_width, target_height, volumetric_fog_depth), sky.sky_shader.default_shader_rd); - - p_render_buffers->set_custom_data(RB_SCOPE_FOG, fog); - } - - if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { - Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); - - RendererRD::Fog::VolumetricFogSettings settings; - settings.rb_size = size; - 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_gi_buffer = rbgi->get_voxel_gi_buffer(); - 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(); - - settings.vfog = fog; - settings.cluster_builder = p_render_buffers->cluster_builder; - settings.rbgi = rbgi; - settings.sdfgi = sdfgi; - settings.env = p_environment; - settings.sky = &sky; - settings.gi = &gi; - - 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); - } } bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) { @@ -2886,175 +1062,8 @@ 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, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer) { - // 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(); - - if (p_render_data->render_buffers.is_valid() && p_use_gi && p_render_data->render_buffers->has_custom_data(RB_SCOPE_SDFGI)) { - Ref<RendererRD::GI::SDFGI> sdfgi = p_render_data->render_buffers->get_custom_data(RB_SCOPE_SDFGI); - sdfgi->store_probes(); - } - - render_state.cube_shadows.clear(); - render_state.shadows.clear(); - render_state.directional_shadows.clear(); - - Plane camera_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin); - float lod_distance_multiplier = p_render_data->scene_data->cam_projection.get_lod_multiplier(); - { - for (int i = 0; i < render_state.render_shadow_count; i++) { - LightInstance *li = light_instance_owner.get_or_null(render_state.render_shadows[i].light); - - if (light_storage->light_get_type(li->light) == RS::LIGHT_DIRECTIONAL) { - render_state.directional_shadows.push_back(i); - } else if (light_storage->light_get_type(li->light) == RS::LIGHT_OMNI && light_storage->light_omni_get_shadow_mode(li->light) == RS::LIGHT_OMNI_SHADOW_CUBE) { - render_state.cube_shadows.push_back(i); - } else { - render_state.shadows.push_back(i); - } - } - - //cube shadows are rendered in their own way - for (uint32_t i = 0; i < render_state.cube_shadows.size(); i++) { - _render_shadow_pass(render_state.render_shadows[render_state.cube_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.cube_shadows[i]].pass, render_state.render_shadows[render_state.cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info); - } - - if (render_state.directional_shadows.size()) { - //open the pass for directional shadows - _update_directional_shadow_atlas(); - RD::get_singleton()->draw_list_begin(directional_shadow.fb, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE); - RD::get_singleton()->draw_list_end(); - } - } - - // Render GI - - bool render_shadows = render_state.directional_shadows.size() || render_state.shadows.size(); - bool render_gi = p_render_data->render_buffers.is_valid() && p_use_gi; - - if (render_shadows && render_gi) { - RENDER_TIMESTAMP("Render GI + Render Shadows (Parallel)"); - } else if (render_shadows) { - RENDER_TIMESTAMP("Render Shadows"); - } else if (render_gi) { - RENDER_TIMESTAMP("Render GI"); - } - - //prepare shadow rendering - if (render_shadows) { - _render_shadow_begin(); - - //render directional shadows - for (uint32_t i = 0; i < render_state.directional_shadows.size(); i++) { - _render_shadow_pass(render_state.render_shadows[render_state.directional_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.directional_shadows[i]].pass, render_state.render_shadows[render_state.directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == render_state.directional_shadows.size() - 1, false, p_render_data->render_info); - } - //render positional shadows - for (uint32_t i = 0; i < render_state.shadows.size(); i++) { - _render_shadow_pass(render_state.render_shadows[render_state.shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.shadows[i]].pass, render_state.render_shadows[render_state.shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == render_state.shadows.size() - 1, true, p_render_data->render_info); - } - - _render_shadow_process(); - } - - //start GI - if (render_gi) { - gi.process_gi(p_render_data->render_buffers, p_normal_roughness_slices, p_voxel_gi_buffer, p_render_data->environment, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances); - } - - //Do shadow rendering (in parallel with GI) - if (render_shadows) { - _render_shadow_end(RD::BARRIER_MASK_NO_BARRIER); - } - - if (render_gi) { - RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //use a later barrier - } - - if (p_render_data->render_buffers.is_valid() && ss_effects) { - if (p_use_ssao || p_use_ssil) { - Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; - ERR_FAIL_COND(rb.is_null()); - Size2i size = rb->get_internal_size(); - - bool invalidate_uniform_set = false; - if (rb->ss_effects.linear_depth.is_null()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16_SFLOAT; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = (size.x + 1) / 2; - tf.height = (size.y + 1) / 2; - tf.mipmaps = 5; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ss_effects.linear_depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->ss_effects.linear_depth, "SS Effects Depth"); - for (uint32_t i = 0; i < tf.mipmaps; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, i, 1, RD::TEXTURE_SLICE_2D_ARRAY); - rb->ss_effects.linear_depth_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SS Effects Depth Mip " + itos(i) + " "); - } - invalidate_uniform_set = true; - } - - RID depth_texture = rb->get_depth_texture(); - ss_effects->downsample_depth(depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, size, p_render_data->scene_data->cam_projection); - } - - if (p_use_ssao) { - // TODO make these proper stereo - _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection); - } - - if (p_use_ssil) { - // TODO make these proper stereo - _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform); - } - } - - //full barrier here, we need raster, transfer and compute and it depends from the previous work - RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL); - - if (current_cluster_builder) { - current_cluster_builder->begin(p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, !p_render_data->reflection_probe.is_valid()); - } - - bool using_shadows = true; - - if (p_render_data->reflection_probe.is_valid()) { - if (!RSG::light_storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { - using_shadows = false; - } - } else { - //do not render reflections when rendering a reflection probe - _setup_reflections(p_render_data, *p_render_data->reflection_probes, p_render_data->scene_data->cam_transform.affine_inverse(), p_render_data->environment); - } - - uint32_t directional_light_count = 0; - uint32_t positional_light_count = 0; - _setup_lights(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows); - _setup_decals(*p_render_data->decals, p_render_data->scene_data->cam_transform.affine_inverse()); - - p_render_data->directional_light_count = directional_light_count; - - if (current_cluster_builder) { - current_cluster_builder->bake_cluster(); - } - - if (p_render_data->render_buffers.is_valid()) { - bool directional_shadows = false; - for (uint32_t i = 0; i < directional_light_count; i++) { - if (cluster.directional_lights[i].shadow_opacity > 0.001) { - directional_shadows = true; - break; - } - } - if (is_volumetric_supported()) { - _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform, p_render_data->scene_data->prev_cam_transform.affine_inverse(), p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count, *p_render_data->fog_volumes); - } - } -} - void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &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_attributes, 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, RenderingMethod::RenderInfo *r_render_info) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); // getting this here now so we can direct call a bunch of things more easily @@ -3101,14 +1110,14 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render } if (p_shadow_atlas.is_valid()) { - Vector2 sas = shadow_atlas_get_size(p_shadow_atlas); - scene_data.shadow_atlas_pixel_size.x = 1.0 / sas.x; - scene_data.shadow_atlas_pixel_size.y = 1.0 / sas.y; + int shadow_atlas_size = light_storage->shadow_atlas_get_size(p_shadow_atlas); + scene_data.shadow_atlas_pixel_size.x = 1.0 / shadow_atlas_size; + scene_data.shadow_atlas_pixel_size.y = 1.0 / shadow_atlas_size; } { - Vector2 dss = directional_shadow_get_size(); - scene_data.directional_shadow_pixel_size.x = 1.0 / dss.x; - scene_data.directional_shadow_pixel_size.y = 1.0 / dss.y; + int directional_shadow_size = light_storage->directional_shadow_get_size(); + scene_data.directional_shadow_pixel_size.x = 1.0 / directional_shadow_size; + scene_data.directional_shadow_pixel_size.y = 1.0 / directional_shadow_size; } scene_data.time = time; @@ -3131,15 +1140,17 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render render_data.environment = p_environment; render_data.camera_attributes = p_camera_attributes; render_data.shadow_atlas = p_shadow_atlas; + render_data.occluder_debug_tex = p_occluder_debug_tex; render_data.reflection_atlas = p_reflection_atlas; render_data.reflection_probe = p_reflection_probe; render_data.reflection_probe_pass = p_reflection_probe_pass; - render_state.render_shadows = p_render_shadows; - render_state.render_shadow_count = p_render_shadow_count; - render_state.render_sdfgi_regions = p_render_sdfgi_regions; - render_state.render_sdfgi_region_count = p_render_sdfgi_region_count; - render_state.sdfgi_update_data = p_sdfgi_update_data; + render_data.render_shadows = p_render_shadows; + render_data.render_shadow_count = p_render_shadow_count; + render_data.render_sdfgi_regions = p_render_sdfgi_regions; + render_data.render_sdfgi_region_count = p_render_sdfgi_region_count; + render_data.sdfgi_update_data = p_sdfgi_update_data; + render_data.render_info = r_render_info; } @@ -3151,22 +1162,6 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render render_data.voxel_gi_instances = ∅ } - // sdfgi first - if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_SDFGI)) { - Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); - float exposure_normalization = 1.0; - - if (p_camera_attributes.is_valid()) { - exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes); - } - for (int i = 0; i < render_state.render_sdfgi_region_count; i++) { - sdfgi->render_region(rb, render_state.render_sdfgi_regions[i].region, render_state.render_sdfgi_regions[i].instances, this, exposure_normalization); - } - if (render_state.sdfgi_update_data->update_static) { - sdfgi->render_static_lights(&render_data, rb, render_state.sdfgi_update_data->static_cascade_count, p_sdfgi_update_data->static_cascade_indices, render_state.sdfgi_update_data->static_positional_lights, this); - } - } - Color clear_color; if (p_render_buffers.is_valid()) { clear_color = texture_storage->render_target_get_clear_request_color(rb->get_render_target()); @@ -3174,297 +1169,8 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render clear_color = RSG::texture_storage->get_default_clear_color(); } - //assign render indices to voxel_gi_instances - if (is_dynamic_gi_supported()) { - for (uint32_t i = 0; i < (uint32_t)p_voxel_gi_instances.size(); i++) { - gi.voxel_gi_instance_set_render_index(p_voxel_gi_instances[i], i); - } - } - - if (rb.is_valid()) { - // render_data.render_buffers == p_render_buffers so we can use our already retrieved rb - current_cluster_builder = rb->cluster_builder; - } else if (reflection_probe_instance_owner.owns(render_data.reflection_probe)) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(render_data.reflection_probe); - ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(rpi->atlas); - if (!ra) { - ERR_PRINT("reflection probe has no reflection atlas! Bug?"); - current_cluster_builder = nullptr; - } else { - current_cluster_builder = ra->cluster_builder; - } - if (p_camera_attributes.is_valid()) { - RendererRD::LightStorage::get_singleton()->reflection_probe_set_baked_exposure(rpi->probe, RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes)); - } - } else { - ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash - current_cluster_builder = nullptr; - } - - render_state.voxel_gi_count = 0; - - if (rb.is_valid() && is_dynamic_gi_supported()) { - if (rb->has_custom_data(RB_SCOPE_SDFGI)) { - Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); - if (sdfgi.is_valid()) { - sdfgi->update_cascades(); - sdfgi->pre_process_gi(scene_data.cam_transform, &render_data, this); - sdfgi->update_light(); - } - } - - gi.setup_voxel_gi_instances(&render_data, render_data.render_buffers, scene_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this); - } - - render_state.depth_prepass_used = false; //calls _pre_opaque_render between depth pre-pass and opaque pass - if (current_cluster_builder != nullptr) { - render_data.cluster_buffer = current_cluster_builder->get_cluster_buffer(); - render_data.cluster_size = current_cluster_builder->get_cluster_size(); - render_data.cluster_max_elements = current_cluster_builder->get_max_cluster_elements(); - } - - if (rb.is_valid() && vrs) { - RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(rb->get_render_target()); - if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) { - RID vrs_texture = rb->get_texture(RB_SCOPE_VRS, RB_TEXTURE); - - // We use get_cache_multipass instead of get_cache_multiview because the default behavior is for - // our vrs_texture to be used as the VRS attachment. In this particular case we're writing to it - // so it needs to be set as our color attachment - - Vector<RID> textures; - textures.push_back(vrs_texture); - - Vector<RD::FramebufferPass> passes; - RD::FramebufferPass pass; - pass.color_attachments.push_back(0); - passes.push_back(pass); - - RID vrs_fb = FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, rb->get_view_count()); - - vrs->update_vrs_texture(vrs_fb, rb->get_render_target()); - } - } - _render_scene(&render_data, clear_color); - - if (rb.is_valid()) { - _render_buffers_debug_draw(rb, p_shadow_atlas, p_occluder_debug_tex); - - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb->has_custom_data(RB_SCOPE_SDFGI)) { - Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); - Vector<RID> view_rids; - - // SDFGI renders at internal resolution, need to check if our debug correctly supports outputting upscaled. - Size2i size = rb->get_internal_size(); - RID source_texture = rb->get_internal_texture(); - for (uint32_t v = 0; v < rb->get_view_count(); v++) { - view_rids.push_back(rb->get_internal_texture(v)); - } - - sdfgi->debug_draw(scene_data.view_count, scene_data.view_projection, scene_data.cam_transform, size.x, size.y, rb->get_render_target(), source_texture, view_rids); - } - } -} - -void RendererSceneRenderRD::_debug_draw_cluster(Ref<RenderSceneBuffersRD> p_render_buffers) { - if (p_render_buffers.is_valid() && current_cluster_builder != nullptr) { - RS::ViewportDebugDraw dd = get_debug_draw_mode(); - - if (dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) { - ClusterBuilderRD::ElementType elem_type = ClusterBuilderRD::ELEMENT_TYPE_MAX; - switch (dd) { - case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS: - elem_type = ClusterBuilderRD::ELEMENT_TYPE_OMNI_LIGHT; - break; - case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS: - elem_type = ClusterBuilderRD::ELEMENT_TYPE_SPOT_LIGHT; - break; - case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS: - elem_type = ClusterBuilderRD::ELEMENT_TYPE_DECAL; - break; - case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES: - elem_type = ClusterBuilderRD::ELEMENT_TYPE_REFLECTION_PROBE; - break; - default: { - } - } - current_cluster_builder->debug(elem_type); - } - } -} - -void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info) { - LightInstance *light_instance = light_instance_owner.get_or_null(p_light); - ERR_FAIL_COND(!light_instance); - - Rect2i atlas_rect; - uint32_t atlas_size = 1; - RID atlas_fb; - - bool using_dual_paraboloid = false; - bool using_dual_paraboloid_flip = false; - Vector2i dual_paraboloid_offset; - RID render_fb; - RID render_texture; - float zfar; - - bool use_pancake = false; - bool render_cubemap = false; - bool finalize_cubemap = false; - - bool flip_y = false; - - Projection light_projection; - Transform3D light_transform; - - if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) { - //set pssm stuff - if (light_instance->last_scene_shadow_pass != scene_pass) { - light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light); - directional_shadow.current_light++; - light_instance->last_scene_shadow_pass = scene_pass; - } - - use_pancake = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0; - light_projection = light_instance->shadow_transform[p_pass].camera; - light_transform = light_instance->shadow_transform[p_pass].transform; - - atlas_rect = light_instance->directional_rect; - - if (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { - atlas_rect.size.width /= 2; - atlas_rect.size.height /= 2; - - if (p_pass == 1) { - atlas_rect.position.x += atlas_rect.size.width; - } else if (p_pass == 2) { - atlas_rect.position.y += atlas_rect.size.height; - } else if (p_pass == 3) { - atlas_rect.position += atlas_rect.size; - } - } else if (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { - atlas_rect.size.height /= 2; - - if (p_pass == 0) { - } else { - atlas_rect.position.y += atlas_rect.size.height; - } - } - - light_instance->shadow_transform[p_pass].atlas_rect = atlas_rect; - - light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size; - light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size; - - zfar = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE); - - render_fb = directional_shadow.fb; - render_texture = RID(); - flip_y = true; - - } else { - //set from shadow atlas - - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); - ERR_FAIL_COND(!shadow_atlas); - ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light)); - - _update_shadow_atlas(shadow_atlas); - - uint32_t key = shadow_atlas->shadow_owners[p_light]; - - uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; - - ERR_FAIL_INDEX((int)shadow, shadow_atlas->quadrants[quadrant].shadows.size()); - - uint32_t quadrant_size = shadow_atlas->size >> 1; - - atlas_rect.position.x = (quadrant & 1) * quadrant_size; - atlas_rect.position.y = (quadrant >> 1) * quadrant_size; - - uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); - atlas_rect.position.x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - atlas_rect.position.y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - - atlas_rect.size.width = shadow_size; - atlas_rect.size.height = shadow_size; - - zfar = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE); - - if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) { - bool wrap = (shadow + 1) % shadow_atlas->quadrants[quadrant].subdivision == 0; - dual_paraboloid_offset = wrap ? Vector2i(1 - shadow_atlas->quadrants[quadrant].subdivision, 1) : Vector2i(1, 0); - - if (RSG::light_storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) { - ShadowCubemap *cubemap = _get_shadow_cubemap(shadow_size / 2); - - render_fb = cubemap->side_fb[p_pass]; - render_texture = cubemap->cubemap; - - light_projection = light_instance->shadow_transform[p_pass].camera; - light_transform = light_instance->shadow_transform[p_pass].transform; - render_cubemap = true; - finalize_cubemap = p_pass == 5; - atlas_fb = shadow_atlas->fb; - - atlas_size = shadow_atlas->size; - - if (p_pass == 0) { - _render_shadow_begin(); - } - - } else { - atlas_rect.position.x += 1; - atlas_rect.position.y += 1; - atlas_rect.size.x -= 2; - atlas_rect.size.y -= 2; - - atlas_rect.position += p_pass * atlas_rect.size * dual_paraboloid_offset; - - light_projection = light_instance->shadow_transform[0].camera; - light_transform = light_instance->shadow_transform[0].transform; - - using_dual_paraboloid = true; - using_dual_paraboloid_flip = p_pass == 1; - render_fb = shadow_atlas->fb; - flip_y = true; - } - - } else if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_SPOT) { - light_projection = light_instance->shadow_transform[0].camera; - light_transform = light_instance->shadow_transform[0].transform; - - render_fb = shadow_atlas->fb; - - flip_y = true; - } - } - - if (render_cubemap) { - //rendering to cubemap - _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info); - if (finalize_cubemap) { - _render_shadow_process(); - _render_shadow_end(); - //reblit - Rect2 atlas_rect_norm = atlas_rect; - atlas_rect_norm.position /= float(atlas_size); - atlas_rect_norm.size /= float(atlas_size); - 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(), false); - atlas_rect_norm.position += Vector2(dual_paraboloid_offset) * atlas_rect_norm.size; - 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, Projection(), light_instance->transform, zfar, 0, 0, 0); - } - - } else { - //render shadow - _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info); - } } void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { @@ -3495,58 +1201,11 @@ bool RendererSceneRenderRD::free(RID p_rid) { environment_free(p_rid); } else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) { RSG::camera_attributes->camera_attributes_free(p_rid); - } else if (reflection_atlas_owner.owns(p_rid)) { - reflection_atlas_set_size(p_rid, 0, 0); - ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_rid); - if (ra->cluster_builder) { - memdelete(ra->cluster_builder); - } - reflection_atlas_owner.free(p_rid); - } else if (reflection_probe_instance_owner.owns(p_rid)) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_rid); - _free_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id); - reflection_probe_release_atlas_index(p_rid); - reflection_probe_instance_owner.free(p_rid); - } else if (decal_instance_owner.owns(p_rid)) { - DecalInstance *di = decal_instance_owner.get_or_null(p_rid); - _free_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id); - decal_instance_owner.free(p_rid); - } else if (lightmap_instance_owner.owns(p_rid)) { - lightmap_instance_owner.free(p_rid); } else if (gi.voxel_gi_instance_owns(p_rid)) { gi.voxel_gi_instance_free(p_rid); } else if (sky.sky_owner.owns(p_rid)) { sky.update_dirty_skys(); sky.free_sky(p_rid); - } else if (light_instance_owner.owns(p_rid)) { - LightInstance *light_instance = light_instance_owner.get_or_null(p_rid); - - //remove from shadow atlases.. - for (const RID &E : light_instance->shadow_atlases) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E); - ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid)); - uint32_t key = shadow_atlas->shadow_owners[p_rid]; - uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK; - - shadow_atlas->quadrants[q].shadows.write[s].owner = RID(); - - if (key & ShadowAtlas::OMNI_LIGHT_FLAG) { - // Omni lights use two atlas spots, make sure to clear the other as well - shadow_atlas->quadrants[q].shadows.write[s + 1].owner = RID(); - } - - shadow_atlas->shadow_owners.erase(p_rid); - } - - if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) { - _free_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id); - } - light_instance_owner.free(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 (RendererRD::Fog::get_singleton()->owns_fog_volume_instance(p_rid)) { RendererRD::Fog::get_singleton()->fog_instance_free(p_rid); } else { @@ -3621,6 +1280,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Typed //RID sampled_light; RenderGeometryInstance *gi = geometry_instance_create(p_base); + ERR_FAIL_NULL_V(gi, TypedArray<Image>()); uint32_t sc = RSG::mesh_storage->mesh_get_surface_count(p_base); Vector<RID> materials; @@ -3693,27 +1353,6 @@ void RendererSceneRenderRD::sdfgi_set_debug_probe_select(const Vector3 &p_positi RendererSceneRenderRD *RendererSceneRenderRD::singleton = nullptr; -RID RendererSceneRenderRD::get_reflection_probe_buffer() { - return cluster.reflection_buffer; -} -RID RendererSceneRenderRD::get_omni_light_buffer() { - return cluster.omni_light_buffer; -} - -RID RendererSceneRenderRD::get_spot_light_buffer() { - return cluster.spot_light_buffer; -} - -RID RendererSceneRenderRD::get_directional_light_buffer() { - return cluster.directional_light_buffer; -} -RID RendererSceneRenderRD::get_decal_buffer() { - return cluster.decal_buffer; -} -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); } @@ -3723,11 +1362,6 @@ bool RendererSceneRenderRD::is_dynamic_gi_supported() const { return true; } -bool RendererSceneRenderRD::is_clustered_enabled() const { - // used by default. - return true; -} - bool RendererSceneRenderRD::is_volumetric_supported() const { // usable by default (unless low end = true) return true; @@ -3743,9 +1377,10 @@ RendererSceneRenderRD::RendererSceneRenderRD() { void RendererSceneRenderRD::init() { max_cluster_elements = get_max_elements(); + RendererRD::LightStorage::get_singleton()->set_max_cluster_elements(max_cluster_elements); - directional_shadow.size = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/size"); - directional_shadow.use_16_bits = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/16_bits"); + /* Forward ID */ + forward_id_storage = create_forward_id_storage(); /* SKY SHADER */ @@ -3758,68 +1393,25 @@ void RendererSceneRenderRD::init() { } { //decals - cluster.max_decals = max_cluster_elements; - uint32_t decal_buffer_size = cluster.max_decals * sizeof(Cluster::DecalData); - cluster.decals = memnew_arr(Cluster::DecalData, cluster.max_decals); - cluster.decal_sort = memnew_arr(Cluster::InstanceSort<DecalInstance>, cluster.max_decals); - cluster.decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size); - } - - { //reflections - - cluster.max_reflections = max_cluster_elements; - cluster.reflections = memnew_arr(Cluster::ReflectionData, cluster.max_reflections); - cluster.reflection_sort = memnew_arr(Cluster::InstanceSort<ReflectionProbeInstance>, cluster.max_reflections); - cluster.reflection_buffer = RD::get_singleton()->storage_buffer_create(sizeof(Cluster::ReflectionData) * cluster.max_reflections); + RendererRD::TextureStorage::get_singleton()->set_max_decals(max_cluster_elements); } { //lights - cluster.max_lights = max_cluster_elements; - - uint32_t light_buffer_size = cluster.max_lights * sizeof(Cluster::LightData); - cluster.omni_lights = memnew_arr(Cluster::LightData, cluster.max_lights); - cluster.omni_light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size); - cluster.omni_light_sort = memnew_arr(Cluster::InstanceSort<LightInstance>, cluster.max_lights); - cluster.spot_lights = memnew_arr(Cluster::LightData, cluster.max_lights); - cluster.spot_light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size); - cluster.spot_light_sort = memnew_arr(Cluster::InstanceSort<LightInstance>, cluster.max_lights); - //defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(cluster.max_lights) + "\n"; - - cluster.max_directional_lights = MAX_DIRECTIONAL_LIGHTS; - uint32_t directional_light_buffer_size = cluster.max_directional_lights * sizeof(Cluster::DirectionalLightData); - cluster.directional_lights = memnew_arr(Cluster::DirectionalLightData, cluster.max_directional_lights); - cluster.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size); } if (is_volumetric_supported()) { - RendererRD::Fog::get_singleton()->init_fog_shader(cluster.max_directional_lights, get_roughness_layers(), is_using_radiance_cubemap_array()); - } - - { - RD::SamplerState sampler; - sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler.min_filter = RD::SAMPLER_FILTER_NEAREST; - sampler.enable_compare = true; - sampler.compare_op = RD::COMPARE_OP_LESS; - shadow_sampler = RD::get_singleton()->sampler_create(sampler); + RendererRD::Fog::get_singleton()->init_fog_shader(RendererRD::LightStorage::get_singleton()->get_max_directional_lights(), get_roughness_layers(), is_using_radiance_cubemap_array()); } RSG::camera_attributes->camera_attributes_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape")))); RSG::camera_attributes->camera_attributes_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_use_jitter")); use_physical_light_units = GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units"); - environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to")); screen_space_roughness_limiter = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/enabled"); screen_space_roughness_limiter_amount = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/amount"); screen_space_roughness_limiter_limit = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/limit"); glow_bicubic_upscale = int(GLOBAL_GET("rendering/environment/glow/upscale_mode")) > 0; glow_high_quality = GLOBAL_GET("rendering/environment/glow/use_high_quality"); - ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/environment/screen_space_reflection/roughness_quality"))); - sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality"))); - sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale"); - sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale"); - - environment_set_ssil_quality(RS::EnvironmentSSILQuality(int(GLOBAL_GET("rendering/environment/ssil/quality"))), GLOBAL_GET("rendering/environment/ssil/half_size"), GLOBAL_GET("rendering/environment/ssil/adaptive_target"), GLOBAL_GET("rendering/environment/ssil/blur_passes"), GLOBAL_GET("rendering/environment/ssil/fadeout_from"), GLOBAL_GET("rendering/environment/ssil/fadeout_to")); directional_penumbra_shadow_kernel = memnew_arr(float, 128); directional_soft_shadow_kernel = memnew_arr(float, 128); @@ -3843,11 +1435,14 @@ void RendererSceneRenderRD::init() { vrs = memnew(RendererRD::VRS); if (can_use_storage) { fsr = memnew(RendererRD::FSR); - ss_effects = memnew(RendererRD::SSEffects); } } RendererSceneRenderRD::~RendererSceneRenderRD() { + if (forward_id_storage) { + memdelete(forward_id_storage); + } + if (bokeh_dof) { memdelete(bokeh_dof); } @@ -3863,13 +1458,6 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { if (fsr) { memdelete(fsr); } - if (ss_effects) { - memdelete(ss_effects); - } - - for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) { - RD::get_singleton()->free(E.value.cubemap); - } if (sky.sky_scene_state.uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky.sky_scene_state.uniform_set)) { RD::get_singleton()->free(sky.sky_scene_state.uniform_set); @@ -3888,25 +1476,6 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { memdelete_arr(penumbra_shadow_kernel); memdelete_arr(soft_shadow_kernel); - { - RD::get_singleton()->free(cluster.directional_light_buffer); - RD::get_singleton()->free(cluster.omni_light_buffer); - RD::get_singleton()->free(cluster.spot_light_buffer); - RD::get_singleton()->free(cluster.reflection_buffer); - RD::get_singleton()->free(cluster.decal_buffer); - memdelete_arr(cluster.directional_lights); - memdelete_arr(cluster.omni_lights); - memdelete_arr(cluster.spot_lights); - memdelete_arr(cluster.omni_light_sort); - memdelete_arr(cluster.spot_light_sort); - memdelete_arr(cluster.reflections); - memdelete_arr(cluster.reflection_sort); - memdelete_arr(cluster.decals); - memdelete_arr(cluster.decal_sort); - } - - RD::get_singleton()->free(shadow_sampler); - - directional_shadow_atlas_set_size(0); + RSG::light_storage->directional_shadow_atlas_set_size(0); cull_argument.reset(); //avoid exit error } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 82dc2fd09f..2312603829 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -38,19 +38,21 @@ #include "servers/rendering/renderer_rd/effects/bokeh_dof.h" #include "servers/rendering/renderer_rd/effects/copy_effects.h" #include "servers/rendering/renderer_rd/effects/fsr.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/framebuffer_cache_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/light_storage.h" #include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" #include "servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_method.h" +// For RenderDataRD, possibly inherited from RefCounted and add proper getters for our implementation classes + struct RenderDataRD { Ref<RenderSceneBuffersRD> render_buffers; RenderSceneDataRD *scene_data; @@ -65,6 +67,7 @@ struct RenderDataRD { RID environment; RID camera_attributes; RID shadow_atlas; + RID occluder_debug_tex; RID reflection_atlas; RID reflection_probe; int reflection_probe_pass = 0; @@ -77,6 +80,21 @@ struct RenderDataRD { bool directional_light_soft_shadows = false; RenderingMethod::RenderInfo *render_info = nullptr; + + /* Shadow data */ + const RendererSceneRender::RenderShadowData *render_shadows = nullptr; + int render_shadow_count = 0; + + LocalVector<int> cube_shadows; + LocalVector<int> shadows; + LocalVector<int> directional_shadows; + + /* GI info */ + const RendererSceneRender::RenderSDFGIData *render_sdfgi_regions = nullptr; + int render_sdfgi_region_count = 0; + const RendererSceneRender::RenderSDFGIUpdateData *sdfgi_update_data = nullptr; + + uint32_t voxel_gi_count = 0; }; class RendererSceneRenderRD : public RendererSceneRender { @@ -84,6 +102,7 @@ class RendererSceneRenderRD : public RendererSceneRender { friend RendererRD::GI; protected: + RendererRD::ForwardIDStorage *forward_id_storage = nullptr; RendererRD::BokehDOF *bokeh_dof = nullptr; RendererRD::CopyEffects *copy_effects = nullptr; RendererRD::ToneMapper *tone_mapper = nullptr; @@ -92,18 +111,23 @@ protected: double time = 0.0; double time_step = 0.0; - virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) = 0; + /* ENVIRONMENT */ - void _setup_lights(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows); - void _setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform); - void _setup_reflections(RenderDataRD *p_render_data, const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment); + bool glow_bicubic_upscale = false; + bool glow_high_quality = false; - virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0; + bool use_physical_light_units = false; + + //////////////////////////////// + + virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); }; - virtual void _render_shadow_begin() = 0; - virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &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, RenderingMethod::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; + void _update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers); + + virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) = 0; + + virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0; + virtual void _render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer); virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) = 0; virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; @@ -111,25 +135,14 @@ protected: virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0; void _debug_sdfgi_probes(Ref<RenderSceneBuffersRD> 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(Ref<RenderSceneBuffersRD> p_render_buffers); - virtual void _base_uniforms_changed() = 0; virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0; virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0; - void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection); - void _process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive); - void _process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera); - void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform); - - void _copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers); - bool _needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); 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, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer); - void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data); void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data); void _render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data); @@ -140,26 +153,8 @@ protected: PagedArrayPool<RenderGeometryInstance *> cull_argument_pool; PagedArray<RenderGeometryInstance *> cull_argument; //need this to exist - RendererRD::SSEffects *ss_effects = nullptr; - RendererRD::GI gi; RendererRD::SkyRD sky; - - //used for mobile renderer mostly - - typedef int32_t ForwardID; - - enum ForwardIDType { - FORWARD_ID_TYPE_OMNI_LIGHT, - FORWARD_ID_TYPE_SPOT_LIGHT, - FORWARD_ID_TYPE_REFLECTION_PROBE, - FORWARD_ID_TYPE_DECAL, - FORWARD_ID_MAX, - }; - - virtual ForwardID _allocate_forward_id(ForwardIDType p_type) { return -1; } - virtual void _free_forward_id(ForwardIDType p_type, ForwardID p_id) {} - virtual void _map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) {} - virtual bool _uses_forward_ids() const { return false; } + RendererRD::GI gi; virtual void _update_shader_quality_settings() {} @@ -167,125 +162,7 @@ private: RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED; static RendererSceneRenderRD *singleton; - /* REFLECTION ATLAS */ - - struct ReflectionAtlas { - int count = 0; - int size = 0; - - RID reflection; - RID depth_buffer; - RID depth_fb; - - struct Reflection { - RID owner; - RendererRD::SkyRD::ReflectionData data; - RID fbs[6]; - }; - - Vector<Reflection> reflections; - - ClusterBuilderRD *cluster_builder = nullptr; - }; - - mutable RID_Owner<ReflectionAtlas> reflection_atlas_owner; - - /* REFLECTION PROBE INSTANCE */ - - struct ReflectionProbeInstance { - RID probe; - int atlas_index = -1; - RID atlas; - - bool dirty = true; - bool rendering = false; - int processing_layer = 1; - int processing_side = 0; - - uint32_t render_step = 0; - uint64_t last_pass = 0; - uint32_t cull_mask = 0; - - ForwardID forward_id = -1; - - Transform3D transform; - }; - - mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner; - - /* DECAL INSTANCE */ - - struct DecalInstance { - RID decal; - Transform3D transform; - uint32_t cull_mask = 0; - ForwardID forward_id = -1; - }; - - mutable RID_Owner<DecalInstance> decal_instance_owner; - - /* LIGHTMAP INSTANCE */ - - struct LightmapInstance { - RID lightmap; - Transform3D transform; - }; - - mutable RID_Owner<LightmapInstance> lightmap_instance_owner; - - /* SHADOW ATLAS */ - - struct ShadowShrinkStage { - RID texture; - RID filter_texture; - uint32_t size = 0; - }; - - struct ShadowAtlas { - enum { - QUADRANT_SHIFT = 27, - OMNI_LIGHT_FLAG = 1 << 26, - SHADOW_INDEX_MASK = OMNI_LIGHT_FLAG - 1, - SHADOW_INVALID = 0xFFFFFFFF - }; - - struct Quadrant { - uint32_t subdivision = 0; - - struct Shadow { - RID owner; - uint64_t version = 0; - uint64_t fog_version = 0; // used for fog - uint64_t alloc_tick = 0; - - Shadow() {} - }; - - Vector<Shadow> shadows; - - Quadrant() {} - } quadrants[4]; - - int size_order[4] = { 0, 1, 2, 3 }; - uint32_t smallest_subdiv = 0; - - int size = 0; - bool use_16_bits = true; - - RID depth; - RID fb; //for copying - - HashMap<RID, uint32_t> shadow_owners; - }; - - RID_Owner<ShadowAtlas> shadow_atlas_owner; - - void _update_shadow_atlas(ShadowAtlas *shadow_atlas); - - void _shadow_atlas_invalidate_shadow(RendererSceneRenderRD::ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, RendererSceneRenderRD::ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx); - bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow); - bool _shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow); - + /* Shadow atlas */ RS::ShadowQuality shadows_quality = RS::SHADOW_QUALITY_MAX; //So it always updates when first set RS::ShadowQuality directional_shadow_quality = RS::SHADOW_QUALITY_MAX; float shadows_quality_radius = 1.0; @@ -302,299 +179,36 @@ private: RS::DecalFilter decals_filter = RS::DECAL_FILTER_LINEAR_MIPMAPS; RS::LightProjectorFilter light_projectors_filter = RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS; - /* DIRECTIONAL SHADOW */ - - struct DirectionalShadow { - RID depth; - RID fb; //when renderign direct - - int light_count = 0; - int size = 0; - bool use_16_bits = true; - int current_light = 0; - } directional_shadow; - - void _update_directional_shadow_atlas(); - - /* SHADOW CUBEMAPS */ - - struct ShadowCubemap { - RID cubemap; - RID side_fb[6]; - }; - - HashMap<int, ShadowCubemap> shadow_cubemaps; - ShadowCubemap *_get_shadow_cubemap(int p_size); - - void _create_shadow_cubemaps(); - - /* LIGHT INSTANCE */ - - struct LightInstance { - struct ShadowTransform { - Projection camera; - Transform3D transform; - float farplane; - float split; - float bias_scale; - float shadow_texel_size; - float range_begin; - Rect2 atlas_rect; - Vector2 uv_scale; - }; - - RS::LightType light_type = RS::LIGHT_DIRECTIONAL; - - ShadowTransform shadow_transform[6]; - - AABB aabb; - RID self; - RID light; - Transform3D transform; - - Vector3 light_vector; - Vector3 spot_vector; - float linear_att = 0.0; - - uint64_t shadow_pass = 0; - uint64_t last_scene_pass = 0; - uint64_t last_scene_shadow_pass = 0; - uint64_t last_pass = 0; - uint32_t cull_mask = 0; - uint32_t light_directional_index = 0; - - Rect2 directional_rect; - - HashSet<RID> shadow_atlases; //shadow atlases where this light is registered - - ForwardID forward_id = -1; - - LightInstance() {} - }; - - mutable RID_Owner<LightInstance> light_instance_owner; - - /* ENVIRONMENT */ - - RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM; - bool ssao_half_size = false; - float ssao_adaptive_target = 0.5; - int ssao_blur_passes = 2; - float ssao_fadeout_from = 50.0; - float ssao_fadeout_to = 300.0; - - RS::EnvironmentSSILQuality ssil_quality = RS::ENV_SSIL_QUALITY_MEDIUM; - bool ssil_half_size = false; - bool ssil_using_half_size = false; - float ssil_adaptive_target = 0.5; - int ssil_blur_passes = 4; - float ssil_fadeout_from = 50.0; - float ssil_fadeout_to = 300.0; - - bool glow_bicubic_upscale = false; - bool glow_high_quality = false; - RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW; - - RS::SubSurfaceScatteringQuality sss_quality = RS::SUB_SURFACE_SCATTERING_QUALITY_MEDIUM; - float sss_scale = 0.05; - float sss_depth_scale = 0.01; - - bool use_physical_light_units = false; - - /* Cluster builder */ - - ClusterBuilderSharedDataRD cluster_builder_shared; - ClusterBuilderRD *current_cluster_builder = nullptr; - /* RENDER BUFFERS */ + // TODO move into effects/luminance.h/cpp void _allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb); - void _render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer); - /* GI */ bool screen_space_roughness_limiter = false; float screen_space_roughness_limiter_amount = 0.25; float screen_space_roughness_limiter_limit = 0.18; - /* Cluster */ - - struct Cluster { - /* Scene State UBO */ - - // !BAS! Most data here is not just used by our clustering logic but also by other lighting implementations. Maybe rename this struct to something more appropriate - - enum { - REFLECTION_AMBIENT_DISABLED = 0, - REFLECTION_AMBIENT_ENVIRONMENT = 1, - REFLECTION_AMBIENT_COLOR = 2, - }; - - struct ReflectionData { - float box_extents[3]; - float index; - float box_offset[3]; - uint32_t mask; - float ambient[3]; // ambient color, - float intensity; - uint32_t exterior; - uint32_t box_project; - uint32_t ambient_mode; - float exposure_normalization; - float local_matrix[16]; // up to here for spot and omni, rest is for directional - }; - - struct LightData { - float position[3]; - float inv_radius; - float direction[3]; // in omni, x and y are used for dual paraboloid offset - float size; - - float color[3]; - float attenuation; - - float inv_spot_attenuation; - float cos_spot_angle; - float specular_amount; - float shadow_opacity; - - float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv - float shadow_matrix[16]; - float shadow_bias; - float shadow_normal_bias; - float transmittance_bias; - float soft_shadow_size; - float soft_shadow_scale; - uint32_t mask; - float volumetric_fog_energy; - uint32_t bake_mode; - float projector_rect[4]; - }; - - struct DirectionalLightData { - float direction[3]; - float energy; - float color[3]; - float size; - float specular; - uint32_t mask; - float softshadow_angle; - float soft_shadow_scale; - uint32_t blend_splits; - float shadow_opacity; - float fade_from; - float fade_to; - uint32_t pad[2]; - uint32_t bake_mode; - float volumetric_fog_energy; - float shadow_bias[4]; - float shadow_normal_bias[4]; - float shadow_transmittance_bias[4]; - float shadow_z_range[4]; - float shadow_range_begin[4]; - float shadow_split_offsets[4]; - float shadow_matrices[4][16]; - float uv_scale1[2]; - float uv_scale2[2]; - float uv_scale3[2]; - float uv_scale4[2]; - }; - - struct DecalData { - float xform[16]; - float inv_extents[3]; - float albedo_mix; - float albedo_rect[4]; - float normal_rect[4]; - float orm_rect[4]; - float emission_rect[4]; - float modulate[4]; - float emission_energy; - uint32_t mask; - float upper_fade; - float lower_fade; - float normal_xform[12]; - float normal[3]; - float normal_fade; - }; - - template <class T> - struct InstanceSort { - float depth; - T *instance = nullptr; - bool operator<(const InstanceSort &p_sort) const { - return depth < p_sort.depth; - } - }; - - ReflectionData *reflections = nullptr; - InstanceSort<ReflectionProbeInstance> *reflection_sort; - uint32_t max_reflections; - RID reflection_buffer; - uint32_t max_reflection_probes_per_instance; - uint32_t reflection_count = 0; - - DecalData *decals = nullptr; - InstanceSort<DecalInstance> *decal_sort; - uint32_t max_decals; - RID decal_buffer; - uint32_t decal_count; - - LightData *omni_lights = nullptr; - LightData *spot_lights = nullptr; - - InstanceSort<LightInstance> *omni_light_sort; - InstanceSort<LightInstance> *spot_light_sort; - uint32_t max_lights; - RID omni_light_buffer; - RID spot_light_buffer; - uint32_t omni_light_count = 0; - uint32_t spot_light_count = 0; - - DirectionalLightData *directional_lights = nullptr; - uint32_t max_directional_lights; - RID directional_light_buffer; - - } cluster; - - struct RenderState { - const RendererSceneRender::RenderShadowData *render_shadows = nullptr; - int render_shadow_count = 0; - const RendererSceneRender::RenderSDFGIData *render_sdfgi_regions = nullptr; - int render_sdfgi_region_count = 0; - const RendererSceneRender::RenderSDFGIUpdateData *sdfgi_update_data = nullptr; - - uint32_t voxel_gi_count = 0; - - LocalVector<int> cube_shadows; - LocalVector<int> shadows; - LocalVector<int> directional_shadows; - - bool depth_prepass_used; // this does not seem used anywhere... - } render_state; - - RID shadow_sampler; + /* Light data */ uint64_t scene_pass = 0; - uint64_t shadow_atlas_realloc_tolerance_msec = 500; uint32_t max_cluster_elements = 512; - void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &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, RenderingMethod::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(Ref<RenderSceneBuffersRD> 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: static RendererSceneRenderRD *get_singleton() { return singleton; } - /* Cluster builder */ - ClusterBuilderSharedDataRD *get_cluster_builder_shared() { return &cluster_builder_shared; } + /* LIGHTING */ + + virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents){}; + virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture){}; + virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents){}; /* GI */ @@ -604,42 +218,6 @@ public: RendererRD::SkyRD *get_sky() { return &sky; } - /* SHADOW ATLAS API */ - - virtual RID shadow_atlas_create() override; - virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override; - virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override; - virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) override; - _FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) { - ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!atlas, false); - return atlas->shadow_owners.has(p_light_intance); - } - - _FORCE_INLINE_ RID shadow_atlas_get_texture(RID p_atlas) { - ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!atlas, RID()); - return atlas->depth; - } - - _FORCE_INLINE_ Size2i shadow_atlas_get_size(RID p_atlas) { - ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!atlas, Size2i()); - return Size2(atlas->size, atlas->size); - } - - virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override; - virtual int get_directional_light_shadow_size(RID p_light_intance) override; - virtual void set_directional_shadow_count(int p_count) override; - - _FORCE_INLINE_ RID directional_shadow_get_texture() { - return directional_shadow.depth; - } - - _FORCE_INLINE_ Size2i directional_shadow_get_size() { - return Size2i(directional_shadow.size, directional_shadow.size); - } - /* SDFGI UPDATE */ virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override; @@ -666,266 +244,32 @@ public: virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override; virtual void environment_set_volumetric_fog_filter_active(bool p_enable) override; - virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; - - virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; - virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override; virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override; virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override; - virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override; - RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const; - virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override; _FORCE_INLINE_ bool is_using_physical_light_units() { return use_physical_light_units; } - /* LIGHT INSTANCE API */ - - 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 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) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->light; - } - - _FORCE_INLINE_ Transform3D light_instance_get_base_transform(RID p_light_instance) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->transform; - } - - _FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas, Vector2i &r_omni_offset) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - uint32_t key = shadow_atlas->shadow_owners[li->self]; - - uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; - - ERR_FAIL_COND_V(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size(), Rect2()); - - uint32_t atlas_size = shadow_atlas->size; - uint32_t quadrant_size = atlas_size >> 1; - - uint32_t x = (quadrant & 1) * quadrant_size; - uint32_t y = (quadrant >> 1) * quadrant_size; - - uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); - x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - - if (key & ShadowAtlas::OMNI_LIGHT_FLAG) { - if (((shadow + 1) % shadow_atlas->quadrants[quadrant].subdivision) == 0) { - r_omni_offset.x = 1 - int(shadow_atlas->quadrants[quadrant].subdivision); - r_omni_offset.y = 1; - } else { - r_omni_offset.x = 1; - r_omni_offset.y = 0; - } - } - - uint32_t width = shadow_size; - uint32_t height = shadow_size; - - return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size)); - } - - _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; - } - - _FORCE_INLINE_ float light_instance_get_shadow_texel_size(RID p_light_instance, RID p_shadow_atlas) { -#ifdef DEBUG_ENABLED - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - ERR_FAIL_COND_V(!li->shadow_atlases.has(p_shadow_atlas), 0); -#endif - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); - ERR_FAIL_COND_V(!shadow_atlas, 0); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V(!shadow_atlas->shadow_owners.has(p_light_instance), 0); -#endif - uint32_t key = shadow_atlas->shadow_owners[p_light_instance]; - - uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - - uint32_t quadrant_size = shadow_atlas->size >> 1; - - uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); - - return float(1.0) / shadow_size; - } - - _FORCE_INLINE_ Transform3D - light_instance_get_shadow_transform(RID p_light_instance, int p_index) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->shadow_transform[p_index].transform; - } - _FORCE_INLINE_ float light_instance_get_shadow_bias_scale(RID p_light_instance, int p_index) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->shadow_transform[p_index].bias_scale; - } - _FORCE_INLINE_ float light_instance_get_shadow_range(RID p_light_instance, int p_index) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->shadow_transform[p_index].farplane; - } - _FORCE_INLINE_ float light_instance_get_shadow_range_begin(RID p_light_instance, int p_index) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->shadow_transform[p_index].range_begin; - } - - _FORCE_INLINE_ Vector2 light_instance_get_shadow_uv_scale(RID p_light_instance, int p_index) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->shadow_transform[p_index].uv_scale; - } - - _FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->shadow_transform[p_index].atlas_rect; - } - - _FORCE_INLINE_ float light_instance_get_directional_shadow_split(RID p_light_instance, int p_index) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->shadow_transform[p_index].split; - } - - _FORCE_INLINE_ float light_instance_get_directional_shadow_texel_size(RID p_light_instance, int p_index) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->shadow_transform[p_index].shadow_texel_size; - } - - _FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - li->last_pass = p_pass; - } - - _FORCE_INLINE_ uint64_t light_instance_get_render_pass(RID p_light_instance) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->last_pass; - } - - _FORCE_INLINE_ ForwardID light_instance_get_forward_id(RID p_light_instance) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->forward_id; - } + /* REFLECTION PROBE */ - _FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) { - LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - return li->light_type; - } + virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth); /* FOG VOLUMES */ + uint32_t get_volumetric_fog_size() const { return volumetric_fog_size; } + uint32_t get_volumetric_fog_depth() const { return volumetric_fog_depth; } + bool get_volumetric_fog_filter_active() const { return volumetric_fog_filter_active; } + virtual RID fog_volume_instance_create(RID p_fog_volume) override; virtual void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override; virtual void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override; virtual RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override; virtual Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override; - virtual RID reflection_atlas_create() override; - virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override; - virtual int reflection_atlas_get_size(RID p_ref_atlas) const override; - - _FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) { - ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_ref_atlas); - ERR_FAIL_COND_V(!atlas, RID()); - return atlas->reflection; - } - - virtual RID reflection_probe_instance_create(RID p_probe) override; - virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override; - virtual void reflection_probe_release_atlas_index(RID p_instance) override; - virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override; - virtual bool reflection_probe_instance_has_reflection(RID p_instance) override; - virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override; - virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth); - virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override; - - uint32_t reflection_probe_instance_get_resolution(RID p_instance); - RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index); - RID reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index); - - _FORCE_INLINE_ RID reflection_probe_instance_get_probe(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, RID()); - - return rpi->probe; - } - - _FORCE_INLINE_ ForwardID reflection_probe_instance_get_forward_id(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, 0); - - return rpi->forward_id; - } - - _FORCE_INLINE_ void reflection_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND(!rpi); - rpi->last_pass = p_render_pass; - } - - _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_pass(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, 0); - - return rpi->last_pass; - } - - _FORCE_INLINE_ Transform3D reflection_probe_instance_get_transform(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, Transform3D()); - - return rpi->transform; - } - - _FORCE_INLINE_ int reflection_probe_instance_get_atlas_index(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, -1); - - return rpi->atlas_index; - } - - virtual RID decal_instance_create(RID p_decal) override; - virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override; - - _FORCE_INLINE_ RID decal_instance_get_base(RID p_decal) const { - DecalInstance *decal = decal_instance_owner.get_or_null(p_decal); - return decal->decal; - } - - _FORCE_INLINE_ ForwardID decal_instance_get_forward_id(RID p_decal) const { - DecalInstance *decal = decal_instance_owner.get_or_null(p_decal); - return decal->forward_id; - } - - _FORCE_INLINE_ Transform3D decal_instance_get_transform(RID p_decal) const { - DecalInstance *decal = decal_instance_owner.get_or_null(p_decal); - return decal->transform; - } - - virtual RID lightmap_instance_create(RID p_lightmap) override; - virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override; - _FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) { - return lightmap_instance_owner.get_or_null(p_lightmap_instance) != nullptr; - } - - _FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) { - LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap_instance); - return li->lightmap; - } - _FORCE_INLINE_ Transform3D lightmap_instance_get_transform(RID p_lightmap_instance) { - LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap_instance); - return li->transform; - } - /* gi light probes */ virtual RID voxel_gi_instance_create(RID p_base) override; @@ -944,6 +288,7 @@ public: RID render_buffers_get_default_voxel_gi_buffer(); + virtual void base_uniforms_changed() = 0; virtual void update_uniform_sets(){}; virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &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_attributes, 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, RenderingMethod::RenderInfo *r_render_info = nullptr) override; @@ -964,10 +309,6 @@ public: virtual float screen_space_roughness_limiter_get_amount() const; virtual float screen_space_roughness_limiter_get_limit() const; - virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override; - 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 positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; @@ -1036,18 +377,10 @@ public: virtual void set_time(double p_time, double p_step) override; - RID get_reflection_probe_buffer(); - RID get_omni_light_buffer(); - RID get_spot_light_buffer(); - RID get_directional_light_buffer(); - RID get_decal_buffer(); - int get_max_directional_lights() const; - 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; virtual uint32_t get_max_elements() const; diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index f24d90a032..45dc63aa17 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -313,6 +313,14 @@ vec4 light_compute( vec2 uv, vec4 color, bool is_directional) { vec4 light = vec4(0.0); + vec3 light_direction = vec3(0.0); + + if (is_directional) { + light_direction = normalize(mix(vec3(light_position.xy, 0.0), vec3(0, 0, 1), light_position.z)); + light_position = vec3(0.0); + } else { + light_direction = normalize(light_position - light_vertex); + } #CODE : LIGHT @@ -686,7 +694,6 @@ void main() { vec3 light_pos = vec3(light_array.data[light_base].position, light_array.data[light_base].height); vec3 pos = light_vertex; vec3 light_vec = normalize(light_pos - pos); - float cNdotL = max(0.0, dot(normal, light_vec)); light_color.rgb = light_normal_compute(light_vec, normal, base_color, light_color.rgb, specular_shininess, specular_shininess_used); } diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index d41474118d..1a8a1f3aa3 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -129,12 +129,52 @@ invariant gl_Position; #GLOBALS +#ifdef USE_DOUBLE_PRECISION +// Helper functions for emulating double precision when adding floats. +vec3 quick_two_sum(vec3 a, vec3 b, out vec3 out_p) { + vec3 s = a + b; + out_p = b - (s - a); + return s; +} + +vec3 two_sum(vec3 a, vec3 b, out vec3 out_p) { + vec3 s = a + b; + vec3 v = s - a; + out_p = (a - (s - v)) + (b - v); + return s; +} + +vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec3 out_precision) { + vec3 s, t, se, te; + s = two_sum(base_a, base_b, se); + t = two_sum(prec_a, prec_b, te); + se += t; + s = quick_two_sum(s, se, se); + se += te; + s = quick_two_sum(s, se, out_precision); + return s; +} +#endif + void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) { vec4 instance_custom = vec4(0.0); #if defined(COLOR_USED) color_interp = color_attrib; #endif + mat4 inv_view_matrix = scene_data.inv_view_matrix; + +#ifdef USE_DOUBLE_PRECISION + vec3 model_precision = vec3(model_matrix[0][3], model_matrix[1][3], model_matrix[2][3]); + model_matrix[0][3] = 0.0; + model_matrix[1][3] = 0.0; + model_matrix[2][3] = 0.0; + vec3 view_precision = vec3(inv_view_matrix[0][3], inv_view_matrix[1][3], inv_view_matrix[2][3]); + inv_view_matrix[0][3] = 0.0; + inv_view_matrix[1][3] = 0.0; + inv_view_matrix[2][3] = 0.0; +#endif + mat3 model_normal_matrix; if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { model_normal_matrix = transpose(inverse(mat3(model_matrix))); @@ -142,11 +182,12 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime model_normal_matrix = mat3(model_matrix); } + mat4 matrix; + mat4 read_model_matrix = model_matrix; + if (is_multimesh) { //multimesh, instances are for it - mat4 matrix; - #ifdef USE_PARTICLE_TRAILS uint trail_size = (instances.data[instance_index].flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK; uint stride = 3 + 1 + 1; //particles always uses this format @@ -232,7 +273,14 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime #endif //transpose matrix = transpose(matrix); - model_matrix = model_matrix * matrix; +#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED) + // Normally we can bake the multimesh transform into the model matrix, but when using double precision + // we avoid baking it in so we can emulate high precision. + read_model_matrix = model_matrix * matrix; +#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) + model_matrix = read_model_matrix; +#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) +#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED) model_normal_matrix = model_normal_matrix * mat3(matrix); } @@ -297,7 +345,22 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime // using local coordinates (default) #if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) +#ifdef USE_DOUBLE_PRECISION + // We separate the basis from the origin because the basis is fine with single point precision. + // Then we combine the translations from the model matrix and the view matrix using emulated doubles. + // We add the result to the vertex and ignore the final lost precision. + vec3 model_origin = model_matrix[3].xyz; + if (is_multimesh) { + vertex = mat3(matrix) * vertex; + model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision); + } + vertex = mat3(model_matrix) * vertex; + vec3 temp_precision; // Will be ignored. + vertex += double_add_vec3(model_origin, model_precision, scene_data.inv_view_matrix[3].xyz, view_precision, temp_precision); + vertex = mat3(scene_data.view_matrix) * vertex; +#else vertex = (modelview * vec4(vertex, 1.0)).xyz; +#endif #ifdef NORMAL_USED normal = modelview_normal * normal; #endif @@ -490,7 +553,6 @@ layout(location = 10) in flat uint instance_index_interp; //defines to keep compatibility with vertex -#define model_matrix instances.data[draw_call.instance_index].transform #ifdef USE_MULTIVIEW #define projection_matrix scene_data.projection_matrix_view[ViewIndex] #define inv_projection_matrix scene_data.inv_projection_matrix_view[ViewIndex] @@ -737,6 +799,17 @@ void fragment_shader(in SceneData scene_data) { vec2 alpha_texture_coordinate = vec2(0.0, 0.0); #endif // ALPHA_ANTIALIASING_EDGE_USED + mat4 inv_view_matrix = scene_data.inv_view_matrix; + mat4 read_model_matrix = instances.data[instance_index].transform; +#ifdef USE_DOUBLE_PRECISION + read_model_matrix[0][3] = 0.0; + read_model_matrix[1][3] = 0.0; + read_model_matrix[2][3] = 0.0; + inv_view_matrix[0][3] = 0.0; + inv_view_matrix[1][3] = 0.0; + inv_view_matrix[2][3] = 0.0; +#endif + { #CODE : FRAGMENT } diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl index e8e2dce990..0d36b98645 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl @@ -62,13 +62,14 @@ layout(set = 0, binding = 3) uniform sampler decal_sampler; layout(set = 0, binding = 4) uniform sampler light_projector_sampler; -#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5) -#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6) -#define INSTANCE_FLAGS_USE_SDFGI (1 << 7) -#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8) -#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9) -#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10) -#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 11) +#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 4) +#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 5) +#define INSTANCE_FLAGS_USE_SDFGI (1 << 6) +#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 7) +#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 8) +#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9) +#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10) +#define INSTANCE_FLAGS_PARTICLES (1 << 11) #define INSTANCE_FLAGS_MULTIMESH (1 << 12) #define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13) #define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index a109fd4d75..33fd4c35b1 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -123,6 +123,33 @@ invariant gl_Position; #define scene_data scene_data_block.data +#ifdef USE_DOUBLE_PRECISION +// Helper functions for emulating double precision when adding floats. +vec3 quick_two_sum(vec3 a, vec3 b, out vec3 out_p) { + vec3 s = a + b; + out_p = b - (s - a); + return s; +} + +vec3 two_sum(vec3 a, vec3 b, out vec3 out_p) { + vec3 s = a + b; + vec3 v = s - a; + out_p = (a - (s - v)) + (b - v); + return s; +} + +vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec3 out_precision) { + vec3 s, t, se, te; + s = two_sum(base_a, base_b, se); + t = two_sum(prec_a, prec_b, te); + se += t; + s = quick_two_sum(s, se, se); + se += te; + s = quick_two_sum(s, se, out_precision); + return s; +} +#endif + void main() { vec4 instance_custom = vec4(0.0); #if defined(COLOR_USED) @@ -132,6 +159,17 @@ void main() { bool is_multimesh = bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH); mat4 model_matrix = draw_call.transform; + mat4 inv_view_matrix = scene_data.inv_view_matrix; +#ifdef USE_DOUBLE_PRECISION + vec3 model_precision = vec3(model_matrix[0][3], model_matrix[1][3], model_matrix[2][3]); + model_matrix[0][3] = 0.0; + model_matrix[1][3] = 0.0; + model_matrix[2][3] = 0.0; + vec3 view_precision = vec3(inv_view_matrix[0][3], inv_view_matrix[1][3], inv_view_matrix[2][3]); + inv_view_matrix[0][3] = 0.0; + inv_view_matrix[1][3] = 0.0; + inv_view_matrix[2][3] = 0.0; +#endif mat3 model_normal_matrix; if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { @@ -140,11 +178,12 @@ void main() { model_normal_matrix = mat3(model_matrix); } + mat4 matrix; + mat4 read_model_matrix = model_matrix; + if (is_multimesh) { //multimesh, instances are for it - mat4 matrix; - #ifdef USE_PARTICLE_TRAILS uint trail_size = (draw_call.flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK; uint stride = 3 + 1 + 1; //particles always uses this format @@ -230,7 +269,15 @@ void main() { #endif //transpose matrix = transpose(matrix); - model_matrix = model_matrix * matrix; + +#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED) + // Normally we can bake the multimesh transform into the model matrix, but when using double precision + // we avoid baking it in so we can emulate high precision. + read_model_matrix = model_matrix * matrix; +#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) + model_matrix = read_model_matrix; +#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) +#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED) model_normal_matrix = model_normal_matrix * mat3(matrix); } @@ -297,7 +344,22 @@ void main() { // using local coordinates (default) #if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) +#ifdef USE_DOUBLE_PRECISION + // We separate the basis from the origin because the basis is fine with single point precision. + // Then we combine the translations from the model matrix and the view matrix using emulated doubles. + // We add the result to the vertex and ignore the final lost precision. + vec3 model_origin = model_matrix[3].xyz; + if (is_multimesh) { + vertex = mat3(matrix) * vertex; + model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision); + } + vertex = mat3(model_matrix) * vertex; + vec3 temp_precision; + vertex += double_add_vec3(model_origin, model_precision, scene_data.inv_view_matrix[3].xyz, view_precision, temp_precision); + vertex = mat3(scene_data.view_matrix) * vertex; +#else vertex = (modelview * vec4(vertex, 1.0)).xyz; +#endif #ifdef NORMAL_USED normal = modelview_normal * normal; #endif @@ -468,7 +530,6 @@ layout(location = 9) highp in float dp_clip; //defines to keep compatibility with vertex -#define model_matrix draw_call.transform #ifdef USE_MULTIVIEW #define projection_matrix scene_data.projection_matrix_view[ViewIndex] #define inv_projection_matrix scene_data.inv_projection_matrix_view[ViewIndex] @@ -685,6 +746,17 @@ void main() { vec2 alpha_texture_coordinate = vec2(0.0, 0.0); #endif // ALPHA_ANTIALIASING_EDGE_USED + mat4 inv_view_matrix = scene_data.inv_view_matrix; + mat4 read_model_matrix = draw_call.transform; +#ifdef USE_DOUBLE_PRECISION + read_model_matrix[0][3] = 0.0; + read_model_matrix[1][3] = 0.0; + read_model_matrix[2][3] = 0.0; + inv_view_matrix[0][3] = 0.0; + inv_view_matrix[1][3] = 0.0; + inv_view_matrix[2][3] = 0.0; +#endif + { #CODE : FRAGMENT } diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index 5e4999fa0f..631ff0575b 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -55,13 +55,14 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler; layout(set = 0, binding = 3) uniform sampler decal_sampler; layout(set = 0, binding = 4) uniform sampler light_projector_sampler; -#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5) -#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6) -#define INSTANCE_FLAGS_USE_SDFGI (1 << 7) -#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8) -#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9) -#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10) -#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 11) +#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 4) +#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 5) +#define INSTANCE_FLAGS_USE_SDFGI (1 << 6) +#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 7) +#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 8) +#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9) +#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10) +#define INSTANCE_FLAGS_PARTICLES (1 << 11) #define INSTANCE_FLAGS_MULTIMESH (1 << 12) #define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13) #define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl index fb5759bc17..3a6dd579b9 100644 --- a/servers/rendering/renderer_rd/shaders/particles.glsl +++ b/servers/rendering/renderer_rd/shaders/particles.glsl @@ -475,7 +475,7 @@ void main() { float particle_size = FRAME.particle_size; -#ifdef USE_COLLISON_SCALE +#ifdef USE_COLLISION_SCALE particle_size *= dot(vec3(length(PARTICLE.xform[0].xyz), length(PARTICLE.xform[1].xyz), length(PARTICLE.xform[2].xyz)), vec3(0.33333333333)); diff --git a/servers/rendering/renderer_rd/storage_rd/forward_id_storage.cpp b/servers/rendering/renderer_rd/storage_rd/forward_id_storage.cpp new file mode 100644 index 0000000000..c7f106eba0 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/forward_id_storage.cpp @@ -0,0 +1,43 @@ +/*************************************************************************/ +/* forward_id_storage.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 "forward_id_storage.h" + +using namespace RendererRD; + +ForwardIDStorage *ForwardIDStorage::singleton = nullptr; + +ForwardIDStorage::ForwardIDStorage() { + singleton = this; +} + +ForwardIDStorage::~ForwardIDStorage() { + singleton = nullptr; +} diff --git a/servers/rendering/renderer_rd/storage_rd/forward_id_storage.h b/servers/rendering/renderer_rd/storage_rd/forward_id_storage.h new file mode 100644 index 0000000000..f6a74383d4 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/forward_id_storage.h @@ -0,0 +1,68 @@ +/*************************************************************************/ +/* forward_id_storage.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 FORWARD_ID_STORAGE_H +#define FORWARD_ID_STORAGE_H + +#include "servers/rendering/storage/utilities.h" + +class RendererSceneRenderRD; + +namespace RendererRD { + +typedef int32_t ForwardID; + +enum ForwardIDType { + FORWARD_ID_TYPE_OMNI_LIGHT, + FORWARD_ID_TYPE_SPOT_LIGHT, + FORWARD_ID_TYPE_REFLECTION_PROBE, + FORWARD_ID_TYPE_DECAL, + FORWARD_ID_MAX, +}; + +class ForwardIDStorage { +private: + static ForwardIDStorage *singleton; + +public: + static ForwardIDStorage *get_singleton() { return singleton; } + + ForwardIDStorage(); + virtual ~ForwardIDStorage(); + + virtual RendererRD::ForwardID allocate_forward_id(RendererRD::ForwardIDType p_type) { return -1; } + virtual void free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) {} + virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) {} + virtual bool uses_forward_ids() const { return false; } +}; + +} // namespace RendererRD + +#endif // FORWARD_ID_STORAGE_H diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index 81b0661481..c83473ef07 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -30,6 +30,7 @@ #include "light_storage.h" #include "core/config/project_settings.h" +#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "texture_storage.h" using namespace RendererRD; @@ -45,6 +46,9 @@ LightStorage::LightStorage() { TextureStorage *texture_storage = TextureStorage::get_singleton(); + directional_shadow.size = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/size"); + directional_shadow.use_16_bits = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/16_bits"); + using_lightmap_array = true; // high end if (using_lightmap_array) { uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); @@ -56,7 +60,7 @@ LightStorage::LightStorage() { } for (int i = 0; i < lightmap_textures.size(); i++) { - lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + lightmap_textures.write[i] = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } } @@ -64,9 +68,46 @@ LightStorage::LightStorage() { } LightStorage::~LightStorage() { + free_reflection_data(); + free_light_data(); + + for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) { + RD::get_singleton()->free(E.value.cubemap); + } + singleton = nullptr; } +bool LightStorage::free(RID p_rid) { + if (owns_reflection_probe(p_rid)) { + reflection_probe_free(p_rid); + return true; + } else if (owns_reflection_atlas(p_rid)) { + reflection_atlas_free(p_rid); + return true; + } else if (owns_reflection_probe_instance(p_rid)) { + reflection_probe_instance_free(p_rid); + return true; + } else if (owns_light(p_rid)) { + light_free(p_rid); + return true; + } else if (owns_light_instance(p_rid)) { + light_instance_free(p_rid); + return true; + } else if (owns_lightmap(p_rid)) { + lightmap_free(p_rid); + return true; + } else if (owns_lightmap_instance(p_rid)) { + lightmap_instance_free(p_rid); + return true; + } else if (owns_shadow_atlas(p_rid)) { + shadow_atlas_free(p_rid); + return true; + } + + return false; +} + /* LIGHT */ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) { @@ -183,7 +224,7 @@ void LightStorage::light_set_shadow(RID p_light, bool p_enabled) { } void LightStorage::light_set_projector(RID p_light, RID p_texture) { - RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + TextureStorage *texture_storage = TextureStorage::get_singleton(); Light *light = light_owner.get_or_null(p_light); ERR_FAIL_COND(!light); @@ -375,6 +416,595 @@ Dependency *LightStorage::light_get_dependency(RID p_light) const { return &light->dependency; } +/* LIGHT INSTANCE API */ + +RID LightStorage::light_instance_create(RID p_light) { + RID li = light_instance_owner.make_rid(LightInstance()); + + LightInstance *light_instance = light_instance_owner.get_or_null(li); + + light_instance->self = li; + light_instance->light = p_light; + light_instance->light_type = light_get_type(p_light); + if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) { + light_instance->forward_id = ForwardIDStorage::get_singleton()->allocate_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT); + } + + return li; +} + +void LightStorage::light_instance_free(RID p_light) { + LightInstance *light_instance = light_instance_owner.get_or_null(p_light); + + //remove from shadow atlases.. + for (const RID &E : light_instance->shadow_atlases) { + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E); + ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_light)); + uint32_t key = shadow_atlas->shadow_owners[p_light]; + uint32_t q = (key >> QUADRANT_SHIFT) & 0x3; + uint32_t s = key & SHADOW_INDEX_MASK; + + shadow_atlas->quadrants[q].shadows.write[s].owner = RID(); + + if (key & OMNI_LIGHT_FLAG) { + // Omni lights use two atlas spots, make sure to clear the other as well + shadow_atlas->quadrants[q].shadows.write[s + 1].owner = RID(); + } + + shadow_atlas->shadow_owners.erase(p_light); + } + + if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) { + ForwardIDStorage::get_singleton()->free_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id); + } + light_instance_owner.free(p_light); +} + +void LightStorage::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) { + LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); + ERR_FAIL_COND(!light_instance); + + light_instance->transform = p_transform; +} + +void LightStorage::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) { + LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); + ERR_FAIL_COND(!light_instance); + + light_instance->aabb = p_aabb; +} + +void LightStorage::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); + + ERR_FAIL_INDEX(p_pass, 6); + + light_instance->shadow_transform[p_pass].camera = p_projection; + light_instance->shadow_transform[p_pass].transform = p_transform; + light_instance->shadow_transform[p_pass].farplane = p_far; + light_instance->shadow_transform[p_pass].split = p_split; + light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale; + light_instance->shadow_transform[p_pass].range_begin = p_range_begin; + light_instance->shadow_transform[p_pass].shadow_texel_size = p_shadow_texel_size; + light_instance->shadow_transform[p_pass].uv_scale = p_uv_scale; +} + +void LightStorage::light_instance_mark_visible(RID p_light_instance) { + LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); + ERR_FAIL_COND(!light_instance); + + light_instance->last_scene_pass = RendererSceneRenderRD::get_singleton()->get_scene_pass(); +} + +/* LIGHT DATA */ + +void LightStorage::free_light_data() { + if (directional_light_buffer.is_valid()) { + RD::get_singleton()->free(directional_light_buffer); + directional_light_buffer = RID(); + } + + if (omni_light_buffer.is_valid()) { + RD::get_singleton()->free(omni_light_buffer); + omni_light_buffer = RID(); + } + + if (spot_light_buffer.is_valid()) { + RD::get_singleton()->free(spot_light_buffer); + spot_light_buffer = RID(); + } + + if (directional_lights != nullptr) { + memdelete_arr(directional_lights); + directional_lights = nullptr; + } + + if (omni_lights != nullptr) { + memdelete_arr(omni_lights); + omni_lights = nullptr; + } + + if (spot_lights != nullptr) { + memdelete_arr(spot_lights); + spot_lights = nullptr; + } + + if (omni_light_sort != nullptr) { + memdelete_arr(omni_light_sort); + omni_light_sort = nullptr; + } + + if (spot_light_sort != nullptr) { + memdelete_arr(spot_light_sort); + spot_light_sort = nullptr; + } +} + +void LightStorage::set_max_lights(const uint32_t p_max_lights) { + max_lights = p_max_lights; + + uint32_t light_buffer_size = max_lights * sizeof(LightData); + omni_lights = memnew_arr(LightData, max_lights); + omni_light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size); + omni_light_sort = memnew_arr(LightInstanceDepthSort, max_lights); + spot_lights = memnew_arr(LightData, max_lights); + spot_light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size); + spot_light_sort = memnew_arr(LightInstanceDepthSort, max_lights); + //defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(max_lights) + "\n"; + + max_directional_lights = RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; + uint32_t directional_light_buffer_size = max_directional_lights * sizeof(DirectionalLightData); + directional_lights = memnew_arr(DirectionalLightData, max_directional_lights); + directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size); +} + +void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) { + ForwardIDStorage *forward_id_storage = ForwardIDStorage::get_singleton(); + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + + Transform3D inverse_transform = p_camera_transform.affine_inverse(); + + r_directional_light_count = 0; + r_positional_light_count = 0; + + Plane camera_plane(-p_camera_transform.basis.get_column(Vector3::AXIS_Z).normalized(), p_camera_transform.origin); + + omni_light_count = 0; + spot_light_count = 0; + + r_directional_light_soft_shadows = false; + + for (int i = 0; i < (int)p_lights.size(); i++) { + LightInstance *light_instance = light_instance_owner.get_or_null(p_lights[i]); + if (!light_instance) { + continue; + } + Light *light = light_owner.get_or_null(light_instance->light); + + ERR_CONTINUE(light == nullptr); + + switch (light->type) { + case RS::LIGHT_DIRECTIONAL: { + if (r_directional_light_count >= max_directional_lights || light->directional_sky_mode == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { + continue; + } + + DirectionalLightData &light_data = directional_lights[r_directional_light_count]; + + Transform3D light_transform = light_instance->transform; + + Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized(); + + light_data.direction[0] = direction.x; + light_data.direction[1] = direction.y; + light_data.direction[2] = direction.z; + + float sign = light->negative ? -1 : 1; + + light_data.energy = sign * light->param[RS::LIGHT_PARAM_ENERGY]; + + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { + light_data.energy *= light->param[RS::LIGHT_PARAM_INTENSITY]; + } else { + light_data.energy *= Math_PI; + } + + if (p_render_data->camera_attributes.is_valid()) { + light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); + } + + Color linear_col = light->color.srgb_to_linear(); + light_data.color[0] = linear_col.r; + light_data.color[1] = linear_col.g; + light_data.color[2] = linear_col.b; + + light_data.specular = light->param[RS::LIGHT_PARAM_SPECULAR]; + light_data.volumetric_fog_energy = light->param[RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY]; + light_data.mask = light->cull_mask; + + float size = light->param[RS::LIGHT_PARAM_SIZE]; + + light_data.size = 1.0 - Math::cos(Math::deg_to_rad(size)); //angle to cosine offset + + if (RendererSceneRenderRD::get_singleton()->get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) { + WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet."); + } + + light_data.shadow_opacity = (p_using_shadows && light->shadow) + ? light->param[RS::LIGHT_PARAM_SHADOW_OPACITY] + : 0.0; + + float angular_diameter = light->param[RS::LIGHT_PARAM_SIZE]; + if (angular_diameter > 0.0) { + // I know tan(0) is 0, but let's not risk it with numerical precision. + // technically this will keep expanding until reaching the sun, but all we care + // is expand until we reach the radius of the near plane (there can't be more occluders than that) + angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter)); + if (light->shadow && light->param[RS::LIGHT_PARAM_SHADOW_BLUR] > 0.0) { + // Only enable PCSS-like soft shadows if blurring is enabled. + // Otherwise, performance would decrease with no visual difference. + r_directional_light_soft_shadows = true; + } + } else { + angular_diameter = 0.0; + } + + if (light_data.shadow_opacity > 0.001) { + RS::LightDirectionalShadowMode smode = light->directional_shadow_mode; + + int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3); + light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light->directional_blend_splits; + for (int j = 0; j < 4; j++) { + Rect2 atlas_rect = light_instance->shadow_transform[j].atlas_rect; + Projection matrix = light_instance->shadow_transform[j].camera; + float split = light_instance->shadow_transform[MIN(limit, j)].split; + + Projection bias; + bias.set_light_bias(); + Projection rectm; + rectm.set_light_atlas_rect(atlas_rect); + + Transform3D modelview = (inverse_transform * light_instance->shadow_transform[j].transform).inverse(); + + Projection shadow_mtx = rectm * bias * matrix * modelview; + light_data.shadow_split_offsets[j] = split; + float bias_scale = light_instance->shadow_transform[j].bias_scale; + light_data.shadow_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_BIAS] / 100.0 * bias_scale; + light_data.shadow_normal_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * light_instance->shadow_transform[j].shadow_texel_size; + light_data.shadow_transmittance_bias[j] = light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] * bias_scale; + light_data.shadow_z_range[j] = light_instance->shadow_transform[j].farplane; + light_data.shadow_range_begin[j] = light_instance->shadow_transform[j].range_begin; + RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrices[j]); + + Vector2 uv_scale = light_instance->shadow_transform[j].uv_scale; + uv_scale *= atlas_rect.size; //adapt to atlas size + switch (j) { + case 0: { + light_data.uv_scale1[0] = uv_scale.x; + light_data.uv_scale1[1] = uv_scale.y; + } break; + case 1: { + light_data.uv_scale2[0] = uv_scale.x; + light_data.uv_scale2[1] = uv_scale.y; + } break; + case 2: { + light_data.uv_scale3[0] = uv_scale.x; + light_data.uv_scale3[1] = uv_scale.y; + } break; + case 3: { + light_data.uv_scale4[0] = uv_scale.x; + light_data.uv_scale4[1] = uv_scale.y; + } break; + } + } + + float fade_start = light->param[RS::LIGHT_PARAM_SHADOW_FADE_START]; + light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep + light_data.fade_to = -light_data.shadow_split_offsets[3]; + + light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR]; + light_data.softshadow_angle = angular_diameter; + light_data.bake_mode = light->bake_mode; + + if (angular_diameter <= 0.0) { + light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->directional_shadow_quality_radius_get(); // Only use quality radius for PCF + } + } + + r_directional_light_count++; + } break; + case RS::LIGHT_OMNI: { + if (omni_light_count >= max_lights) { + continue; + } + + Transform3D light_transform = light_instance->transform; + const real_t distance = camera_plane.distance_to(light_transform.origin); + + if (light->distance_fade) { + const float fade_begin = light->distance_fade_begin; + const float fade_length = light->distance_fade_length; + + if (distance > fade_begin) { + if (distance > fade_begin + fade_length) { + // Out of range, don't draw this light to improve performance. + continue; + } + } + } + + omni_light_sort[omni_light_count].light_instance = light_instance; + omni_light_sort[omni_light_count].light = light; + omni_light_sort[omni_light_count].depth = distance; + omni_light_count++; + } break; + case RS::LIGHT_SPOT: { + if (spot_light_count >= max_lights) { + continue; + } + + Transform3D light_transform = light_instance->transform; + const real_t distance = camera_plane.distance_to(light_transform.origin); + + if (light->distance_fade) { + const float fade_begin = light->distance_fade_begin; + const float fade_length = light->distance_fade_length; + + if (distance > fade_begin) { + if (distance > fade_begin + fade_length) { + // Out of range, don't draw this light to improve performance. + continue; + } + } + } + + spot_light_sort[spot_light_count].light_instance = light_instance; + spot_light_sort[spot_light_count].light = light; + spot_light_sort[spot_light_count].depth = distance; + spot_light_count++; + } break; + } + + light_instance->last_pass = RSG::rasterizer->get_frame_number(); + } + + if (omni_light_count) { + SortArray<LightInstanceDepthSort> sorter; + sorter.sort(omni_light_sort, omni_light_count); + } + + if (spot_light_count) { + SortArray<LightInstanceDepthSort> sorter; + sorter.sort(spot_light_sort, spot_light_count); + } + + bool using_forward_ids = forward_id_storage->uses_forward_ids(); + + for (uint32_t i = 0; i < (omni_light_count + spot_light_count); i++) { + uint32_t index = (i < omni_light_count) ? i : i - (omni_light_count); + LightData &light_data = (i < omni_light_count) ? omni_lights[index] : spot_lights[index]; + RS::LightType type = (i < omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT; + LightInstance *light_instance = (i < omni_light_count) ? omni_light_sort[index].light_instance : spot_light_sort[index].light_instance; + Light *light = (i < omni_light_count) ? omni_light_sort[index].light : spot_light_sort[index].light; + + if (using_forward_ids) { + forward_id_storage->map_forward_id(type == RS::LIGHT_OMNI ? RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT : RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id, index); + } + + Transform3D light_transform = light_instance->transform; + + float sign = light->negative ? -1 : 1; + Color linear_col = light->color.srgb_to_linear(); + + light_data.attenuation = light->param[RS::LIGHT_PARAM_ATTENUATION]; + + // Reuse fade begin, fade length and distance for shadow LOD determination later. + float fade_begin = 0.0; + float fade_shadow = 0.0; + float fade_length = 0.0; + real_t distance = 0.0; + + float fade = 1.0; + float shadow_opacity_fade = 1.0; + if (light->distance_fade) { + fade_begin = light->distance_fade_begin; + fade_shadow = light->distance_fade_shadow; + fade_length = light->distance_fade_length; + distance = camera_plane.distance_to(light_transform.origin); + + // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player. + if (distance > fade_begin) { + fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length); + } + + if (distance > fade_shadow) { + shadow_opacity_fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_shadow) / fade_length); + } + } + + float energy = sign * light->param[RS::LIGHT_PARAM_ENERGY] * fade; + + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { + energy *= light->param[RS::LIGHT_PARAM_INTENSITY]; + + // Convert from Luminous Power to Luminous Intensity + if (type == RS::LIGHT_OMNI) { + energy *= 1.0 / (Math_PI * 4.0); + } else { + // Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle. + // We make this assumption to keep them easy to control. + energy *= 1.0 / Math_PI; + } + } else { + energy *= Math_PI; + } + + if (p_render_data->camera_attributes.is_valid()) { + energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); + } + + light_data.color[0] = linear_col.r * energy; + light_data.color[1] = linear_col.g * energy; + light_data.color[2] = linear_col.b * energy; + light_data.specular_amount = light->param[RS::LIGHT_PARAM_SPECULAR] * 2.0; + light_data.volumetric_fog_energy = light->param[RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY]; + light_data.bake_mode = light->bake_mode; + + float radius = MAX(0.001, light->param[RS::LIGHT_PARAM_RANGE]); + light_data.inv_radius = 1.0 / radius; + + Vector3 pos = inverse_transform.xform(light_transform.origin); + + light_data.position[0] = pos.x; + light_data.position[1] = pos.y; + light_data.position[2] = pos.z; + + Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized(); + + light_data.direction[0] = direction.x; + light_data.direction[1] = direction.y; + light_data.direction[2] = direction.z; + + float size = light->param[RS::LIGHT_PARAM_SIZE]; + + light_data.size = size; + + light_data.inv_spot_attenuation = 1.0f / light->param[RS::LIGHT_PARAM_SPOT_ATTENUATION]; + float spot_angle = light->param[RS::LIGHT_PARAM_SPOT_ANGLE]; + light_data.cos_spot_angle = Math::cos(Math::deg_to_rad(spot_angle)); + + light_data.mask = light->cull_mask; + + light_data.atlas_rect[0] = 0; + light_data.atlas_rect[1] = 0; + light_data.atlas_rect[2] = 0; + light_data.atlas_rect[3] = 0; + + RID projector = light->projector; + + if (projector.is_valid()) { + Rect2 rect = texture_storage->decal_atlas_get_texture_rect(projector); + + if (type == RS::LIGHT_SPOT) { + light_data.projector_rect[0] = rect.position.x; + light_data.projector_rect[1] = rect.position.y + rect.size.height; //flip because shadow is flipped + light_data.projector_rect[2] = rect.size.width; + light_data.projector_rect[3] = -rect.size.height; + } else { + light_data.projector_rect[0] = rect.position.x; + light_data.projector_rect[1] = rect.position.y; + light_data.projector_rect[2] = rect.size.width; + light_data.projector_rect[3] = rect.size.height * 0.5; //used by dp, so needs to be half + } + } else { + light_data.projector_rect[0] = 0; + light_data.projector_rect[1] = 0; + light_data.projector_rect[2] = 0; + light_data.projector_rect[3] = 0; + } + + const bool needs_shadow = + p_using_shadows && + owns_shadow_atlas(p_shadow_atlas) && + shadow_atlas_owns_light_instance(p_shadow_atlas, light_instance->self) && + light->shadow; + + bool in_shadow_range = true; + if (needs_shadow && light->distance_fade) { + if (distance > light->distance_fade_shadow + light->distance_fade_length) { + // Out of range, don't draw shadows to improve performance. + in_shadow_range = false; + } + } + + if (needs_shadow && in_shadow_range) { + // fill in the shadow information + + light_data.shadow_opacity = light->param[RS::LIGHT_PARAM_SHADOW_OPACITY] * shadow_opacity_fade; + + float shadow_texel_size = light_instance_get_shadow_texel_size(light_instance->self, p_shadow_atlas); + light_data.shadow_normal_bias = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * shadow_texel_size * 10.0; + + if (type == RS::LIGHT_SPOT) { + light_data.shadow_bias = light->param[RS::LIGHT_PARAM_SHADOW_BIAS] / 100.0; + } else { //omni + light_data.shadow_bias = light->param[RS::LIGHT_PARAM_SHADOW_BIAS]; + } + + light_data.transmittance_bias = light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS]; + + Vector2i omni_offset; + Rect2 rect = light_instance_get_shadow_atlas_rect(light_instance->self, p_shadow_atlas, omni_offset); + + light_data.atlas_rect[0] = rect.position.x; + light_data.atlas_rect[1] = rect.position.y; + light_data.atlas_rect[2] = rect.size.width; + light_data.atlas_rect[3] = rect.size.height; + + light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR]; + + if (type == RS::LIGHT_OMNI) { + Transform3D proj = (inverse_transform * light_transform).inverse(); + + RendererRD::MaterialStorage::store_transform(proj, 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. + light_data.soft_shadow_size = size; + } else { + light_data.soft_shadow_size = 0.0; + light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->shadows_quality_radius_get(); // Only use quality radius for PCF + } + + light_data.direction[0] = omni_offset.x * float(rect.size.width); + light_data.direction[1] = omni_offset.y * float(rect.size.height); + } else if (type == RS::LIGHT_SPOT) { + Transform3D modelview = (inverse_transform * light_transform).inverse(); + Projection bias; + bias.set_light_bias(); + + Projection cm = light_instance->shadow_transform[0].camera; + Projection shadow_mtx = bias * cm * 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. + float half_np = cm.get_z_near() * Math::tan(Math::deg_to_rad(spot_angle)); + light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width; + } else { + light_data.soft_shadow_size = 0.0; + light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->shadows_quality_radius_get(); // Only use quality radius for PCF + } + } + } else { + light_data.shadow_opacity = 0.0; + } + + light_instance->cull_mask = light->cull_mask; + + // hook for subclass to do further processing. + RendererSceneRenderRD::get_singleton()->setup_added_light(type, light_transform, radius, spot_angle); + + r_positional_light_count++; + } + + //update without barriers + if (omni_light_count) { + RD::get_singleton()->buffer_update(omni_light_buffer, 0, sizeof(LightData) * omni_light_count, omni_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + } + + if (spot_light_count) { + RD::get_singleton()->buffer_update(spot_light_buffer, 0, sizeof(LightData) * spot_light_count, spot_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + } + + if (r_directional_light_count) { + RD::get_singleton()->buffer_update(directional_light_buffer, 0, sizeof(DirectionalLightData) * r_directional_light_count, directional_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + } +} + /* REFLECTION PROBE */ RID LightStorage::reflection_probe_allocate() { @@ -631,6 +1261,443 @@ Dependency *LightStorage::reflection_probe_get_dependency(RID p_probe) const { return &reflection_probe->dependency; } +/* REFLECTION ATLAS */ + +RID LightStorage::reflection_atlas_create() { + ReflectionAtlas ra; + ra.count = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_count"); + ra.size = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_size"); + ra.cluster_builder = nullptr; + + return reflection_atlas_owner.make_rid(ra); +} + +void LightStorage::reflection_atlas_free(RID p_ref_atlas) { + reflection_atlas_set_size(p_ref_atlas, 0, 0); + ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas); + if (ra->cluster_builder) { + memdelete(ra->cluster_builder); + } + reflection_atlas_owner.free(p_ref_atlas); +} + +void LightStorage::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) { + ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas); + ERR_FAIL_COND(!ra); + + if (ra->size == p_reflection_size && ra->count == p_reflection_count) { + return; //no changes + } + + if (ra->cluster_builder) { + // only if we're using our cluster + ra->cluster_builder->setup(Size2i(ra->size, ra->size), max_cluster_elements, RID(), RID(), RID()); + } + + ra->size = p_reflection_size; + ra->count = p_reflection_count; + + if (ra->reflection.is_valid()) { + //clear and invalidate everything + RD::get_singleton()->free(ra->reflection); + ra->reflection = RID(); + RD::get_singleton()->free(ra->depth_buffer); + ra->depth_buffer = RID(); + for (int i = 0; i < ra->reflections.size(); i++) { + ra->reflections.write[i].data.clear_reflection_data(); + if (ra->reflections[i].owner.is_null()) { + continue; + } + reflection_probe_release_atlas_index(ra->reflections[i].owner); + //rp->atlasindex clear + } + + ra->reflections.clear(); + } +} + +int LightStorage::reflection_atlas_get_size(RID p_ref_atlas) const { + ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas); + ERR_FAIL_COND_V(!ra, 0); + + return ra->size; +} + +/* REFLECTION PROBE INSTANCE */ + +RID LightStorage::reflection_probe_instance_create(RID p_probe) { + ReflectionProbeInstance rpi; + rpi.probe = p_probe; + rpi.forward_id = ForwardIDStorage::get_singleton()->allocate_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE); + + return reflection_probe_instance_owner.make_rid(rpi); +} + +void LightStorage::reflection_probe_instance_free(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ForwardIDStorage::get_singleton()->free_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id); + reflection_probe_release_atlas_index(p_instance); + reflection_probe_instance_owner.free(p_instance); +} + +void LightStorage::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND(!rpi); + + rpi->transform = p_transform; + rpi->dirty = true; +} + +void LightStorage::reflection_probe_release_atlas_index(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND(!rpi); + + if (rpi->atlas.is_null()) { + return; //nothing to release + } + ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); + ERR_FAIL_COND(!atlas); + ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size()); + atlas->reflections.write[rpi->atlas_index].owner = RID(); + rpi->atlas_index = -1; + rpi->atlas = RID(); +} + +bool LightStorage::reflection_probe_instance_needs_redraw(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, false); + + if (rpi->rendering) { + return false; + } + + if (rpi->dirty) { + return true; + } + + if (LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) { + return true; + } + + return rpi->atlas_index == -1; +} + +bool LightStorage::reflection_probe_instance_has_reflection(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, false); + + return rpi->atlas.is_valid(); +} + +bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { + ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_reflection_atlas); + + ERR_FAIL_COND_V(!atlas, false); + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, false); + + RD::get_singleton()->draw_command_begin_label("Reflection probe render"); + + if (LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) { + WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings."); + reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count); + } + + if (LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) { + // Invalidate reflection atlas, need to regenerate + RD::get_singleton()->free(atlas->reflection); + atlas->reflection = RID(); + + for (int i = 0; i < atlas->reflections.size(); i++) { + if (atlas->reflections[i].owner.is_null()) { + continue; + } + reflection_probe_release_atlas_index(atlas->reflections[i].owner); + } + + atlas->reflections.clear(); + } + + if (atlas->reflection.is_null()) { + int mipmaps = MIN(RendererSceneRenderRD::get_singleton()->get_sky()->roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1); + mipmaps = LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering + { + //reflection atlas was unused, create: + RD::TextureFormat tf; + tf.array_layers = 6 * atlas->count; + tf.format = RendererSceneRenderRD::get_singleton()->_render_buffers_get_color_format(); + tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; + tf.mipmaps = mipmaps; + tf.width = atlas->size; + tf.height = atlas->size; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0); + + atlas->reflection = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + { + RD::TextureFormat tf; + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; + tf.width = atlas->size; + tf.height = atlas->size; + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + atlas->depth_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + atlas->reflections.resize(atlas->count); + for (int i = 0; i < atlas->count; i++) { + atlas->reflections.write[i].data.update_reflection_data(atlas->size, mipmaps, false, atlas->reflection, i * 6, LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, RendererSceneRenderRD::get_singleton()->get_sky()->roughness_layers, RendererSceneRenderRD::get_singleton()->_render_buffers_get_color_format()); + for (int j = 0; j < 6; j++) { + atlas->reflections.write[i].fbs[j] = RendererSceneRenderRD::get_singleton()->reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer); + } + } + + Vector<RID> fb; + fb.push_back(atlas->depth_buffer); + atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb); + } + + if (rpi->atlas_index == -1) { + for (int i = 0; i < atlas->reflections.size(); i++) { + if (atlas->reflections[i].owner.is_null()) { + rpi->atlas_index = i; + break; + } + } + //find the one used last + if (rpi->atlas_index == -1) { + //everything is in use, find the one least used via LRU + uint64_t pass_min = 0; + + for (int i = 0; i < atlas->reflections.size(); i++) { + ReflectionProbeInstance *rpi2 = reflection_probe_instance_owner.get_or_null(atlas->reflections[i].owner); + if (rpi2->last_pass < pass_min) { + pass_min = rpi2->last_pass; + rpi->atlas_index = i; + } + } + } + } + + if (rpi->atlas_index != -1) { // should we fail if this is still -1 ? + atlas->reflections.write[rpi->atlas_index].owner = p_instance; + } + + rpi->atlas = p_reflection_atlas; + rpi->rendering = true; + rpi->dirty = false; + rpi->processing_layer = 1; + rpi->processing_side = 0; + + RD::get_singleton()->draw_command_end_label(); + + return true; +} + +bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, false); + ERR_FAIL_COND_V(!rpi->rendering, false); + ERR_FAIL_COND_V(rpi->atlas.is_null(), false); + + ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); + if (!atlas || rpi->atlas_index == -1) { + //does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering) + rpi->rendering = false; + return false; + } + + if (LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) { + // Using real time reflections, all roughness is done in one step + atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(false); + rpi->rendering = false; + rpi->processing_side = 0; + rpi->processing_layer = 1; + return true; + } + + if (rpi->processing_layer > 1) { + atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(false, 10, rpi->processing_layer, RendererSceneRenderRD::get_singleton()->get_sky()->sky_ggx_samples_quality); + rpi->processing_layer++; + if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) { + rpi->rendering = false; + rpi->processing_side = 0; + rpi->processing_layer = 1; + return true; + } + return false; + + } else { + atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(false, rpi->processing_side, rpi->processing_layer, RendererSceneRenderRD::get_singleton()->get_sky()->sky_ggx_samples_quality); + } + + rpi->processing_side++; + if (rpi->processing_side == 6) { + rpi->processing_side = 0; + rpi->processing_layer++; + } + + return false; +} + +uint32_t LightStorage::reflection_probe_instance_get_resolution(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, 0); + + ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); + ERR_FAIL_COND_V(!atlas, 0); + return atlas->size; +} + +RID LightStorage::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, RID()); + ERR_FAIL_INDEX_V(p_index, 6, RID()); + + ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); + ERR_FAIL_COND_V(!atlas, RID()); + return atlas->reflections[rpi->atlas_index].fbs[p_index]; +} + +RID LightStorage::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, RID()); + ERR_FAIL_INDEX_V(p_index, 6, RID()); + + ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); + ERR_FAIL_COND_V(!atlas, RID()); + return atlas->depth_fb; +} + +ClusterBuilderRD *LightStorage::reflection_probe_instance_get_cluster_builder(RID p_instance, ClusterBuilderSharedDataRD *p_cluster_builder_shared) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(rpi->atlas); + if (!ra) { + ERR_PRINT("reflection probe has no reflection atlas! Bug?"); + return nullptr; + } else { + if (ra->cluster_builder == nullptr) { + ra->cluster_builder = memnew(ClusterBuilderRD); + ra->cluster_builder->set_shared(p_cluster_builder_shared); + ra->cluster_builder->setup(Size2i(ra->size, ra->size), get_max_cluster_elements(), RID(), RID(), RID()); + } + return ra->cluster_builder; + } +} + +/* REFLECTION DATA */ + +void LightStorage::free_reflection_data() { + if (reflection_buffer.is_valid()) { + RD::get_singleton()->free(reflection_buffer); + reflection_buffer = RID(); + } + + if (reflections != nullptr) { + memdelete_arr(reflections); + reflections = nullptr; + } + + if (reflection_sort != nullptr) { + memdelete_arr(reflection_sort); + reflection_sort = nullptr; + } +} + +void LightStorage::set_max_reflection_probes(const uint32_t p_max_reflection_probes) { + max_reflections = p_max_reflection_probes; + reflections = memnew_arr(ReflectionData, max_reflections); + reflection_sort = memnew_arr(ReflectionProbeInstanceSort, max_reflections); + reflection_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ReflectionData) * max_reflections); +} + +void LightStorage::update_reflection_probe_buffer(RenderDataRD *p_render_data, const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) { + ForwardIDStorage *forward_id_storage = ForwardIDStorage::get_singleton(); + + reflection_count = 0; + + for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) { + if (reflection_count == max_reflections) { + break; + } + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_reflections[i]); + if (!rpi) { + continue; + } + + Transform3D transform = rpi->transform; + + reflection_sort[reflection_count].probe_instance = rpi; + reflection_sort[reflection_count].depth = -p_camera_inverse_transform.xform(transform.origin).z; + reflection_count++; + } + + if (reflection_count > 0) { + SortArray<ReflectionProbeInstanceSort> sort_array; + sort_array.sort(reflection_sort, reflection_count); + } + + bool using_forward_ids = forward_id_storage->uses_forward_ids(); + for (uint32_t i = 0; i < reflection_count; i++) { + ReflectionProbeInstance *rpi = reflection_sort[i].probe_instance; + + if (using_forward_ids) { + forward_id_storage->map_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id, i); + } + + ReflectionProbe *probe = reflection_probe_owner.get_or_null(rpi->probe); + + ReflectionData &reflection_ubo = reflections[i]; + + Vector3 extents = probe->extents; + + rpi->cull_mask = probe->cull_mask; + + reflection_ubo.box_extents[0] = extents.x; + reflection_ubo.box_extents[1] = extents.y; + reflection_ubo.box_extents[2] = extents.z; + reflection_ubo.index = rpi->atlas_index; + + Vector3 origin_offset = probe->origin_offset; + + reflection_ubo.box_offset[0] = origin_offset.x; + reflection_ubo.box_offset[1] = origin_offset.y; + reflection_ubo.box_offset[2] = origin_offset.z; + reflection_ubo.mask = probe->cull_mask; + + reflection_ubo.intensity = probe->intensity; + reflection_ubo.ambient_mode = probe->ambient_mode; + + reflection_ubo.exterior = !probe->interior; + reflection_ubo.box_project = probe->box_projection; + reflection_ubo.exposure_normalization = 1.0; + + if (p_render_data->camera_attributes.is_valid()) { + float exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); + reflection_ubo.exposure_normalization = exposure / probe->baked_exposure; + } + + Color ambient_linear = probe->ambient_color.srgb_to_linear(); + float interior_ambient_energy = probe->ambient_color_energy; + reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy; + reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy; + reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy; + + Transform3D transform = rpi->transform; + Transform3D proj = (p_camera_inverse_transform * transform).inverse(); + MaterialStorage::store_transform(proj, reflection_ubo.local_matrix); + + // hook for subclass to do further processing. + RendererSceneRenderRD::get_singleton()->setup_added_reflection_probe(transform, extents); + + rpi->last_pass = RSG::rasterizer->get_frame_number(); + } + + if (reflection_count) { + RD::get_singleton()->buffer_update(reflection_buffer, 0, reflection_count * sizeof(ReflectionData), reflections, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + } +} + /* LIGHTMAP API */ RID LightStorage::lightmap_allocate() { @@ -649,7 +1716,7 @@ void LightStorage::lightmap_free(RID p_rid) { } void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) { - RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + TextureStorage *texture_storage = TextureStorage::get_singleton(); Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); ERR_FAIL_COND(!lm); @@ -658,17 +1725,17 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use //erase lightmap users if (lm->light_texture.is_valid()) { - RendererRD::TextureStorage::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture); + TextureStorage::Texture *t = texture_storage->get_singleton()->get_texture(lm->light_texture); if (t) { t->lightmap_users.erase(p_lightmap); } } - RendererRD::TextureStorage::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light); + TextureStorage::Texture *t = texture_storage->get_singleton()->get_texture(p_light); lm->light_texture = p_light; lm->uses_spherical_harmonics = p_uses_spherical_haromics; - RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_2d_array = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); if (!t) { if (using_lightmap_array) { if (lm->array_index >= 0) { @@ -830,3 +1897,550 @@ AABB LightStorage::lightmap_get_aabb(RID p_lightmap) const { ERR_FAIL_COND_V(!lm, AABB()); return lm->bounds; } + +/* LIGHTMAP INSTANCE */ + +RID LightStorage::lightmap_instance_create(RID p_lightmap) { + LightmapInstance li; + li.lightmap = p_lightmap; + return lightmap_instance_owner.make_rid(li); +} + +void LightStorage::lightmap_instance_free(RID p_lightmap) { + lightmap_instance_owner.free(p_lightmap); +} + +void LightStorage::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) { + LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap); + ERR_FAIL_COND(!li); + li->transform = p_transform; +} + +/* SHADOW ATLAS API */ + +RID LightStorage::shadow_atlas_create() { + return shadow_atlas_owner.make_rid(ShadowAtlas()); +} + +void LightStorage::shadow_atlas_free(RID p_atlas) { + shadow_atlas_set_size(p_atlas, 0); + shadow_atlas_owner.free(p_atlas); +} + +void LightStorage::_update_shadow_atlas(ShadowAtlas *shadow_atlas) { + if (shadow_atlas->size > 0 && shadow_atlas->depth.is_null()) { + RD::TextureFormat tf; + tf.format = shadow_atlas->use_16_bits ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_D32_SFLOAT; + tf.width = shadow_atlas->size; + tf.height = shadow_atlas->size; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + shadow_atlas->depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); + Vector<RID> fb_tex; + fb_tex.push_back(shadow_atlas->depth); + shadow_atlas->fb = RD::get_singleton()->framebuffer_create(fb_tex); + } +} + +void LightStorage::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) { + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); + ERR_FAIL_COND(!shadow_atlas); + ERR_FAIL_COND(p_size < 0); + p_size = next_power_of_2(p_size); + + if (p_size == shadow_atlas->size && p_16_bits == shadow_atlas->use_16_bits) { + return; + } + + // erasing atlas + if (shadow_atlas->depth.is_valid()) { + RD::get_singleton()->free(shadow_atlas->depth); + shadow_atlas->depth = RID(); + } + for (int i = 0; i < 4; i++) { + //clear subdivisions + shadow_atlas->quadrants[i].shadows.clear(); + shadow_atlas->quadrants[i].shadows.resize(1 << shadow_atlas->quadrants[i].subdivision); + } + + //erase shadow atlas reference from lights + for (const KeyValue<RID, uint32_t> &E : shadow_atlas->shadow_owners) { + LightInstance *li = light_instance_owner.get_or_null(E.key); + ERR_CONTINUE(!li); + li->shadow_atlases.erase(p_atlas); + } + + //clear owners + shadow_atlas->shadow_owners.clear(); + + shadow_atlas->size = p_size; + shadow_atlas->use_16_bits = p_16_bits; +} + +void LightStorage::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) { + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); + ERR_FAIL_COND(!shadow_atlas); + ERR_FAIL_INDEX(p_quadrant, 4); + ERR_FAIL_INDEX(p_subdivision, 16384); + + uint32_t subdiv = next_power_of_2(p_subdivision); + if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer + subdiv <<= 1; + } + + subdiv = int(Math::sqrt((float)subdiv)); + + //obtain the number that will be x*x + + if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv) { + return; + } + + //erase all data from quadrant + for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) { + if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) { + shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); + LightInstance *li = light_instance_owner.get_or_null(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); + ERR_CONTINUE(!li); + li->shadow_atlases.erase(p_atlas); + } + } + + shadow_atlas->quadrants[p_quadrant].shadows.clear(); + shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv * subdiv); + shadow_atlas->quadrants[p_quadrant].subdivision = subdiv; + + //cache the smallest subdiv (for faster allocation in light update) + + shadow_atlas->smallest_subdiv = 1 << 30; + + for (int i = 0; i < 4; i++) { + if (shadow_atlas->quadrants[i].subdivision) { + shadow_atlas->smallest_subdiv = MIN(shadow_atlas->smallest_subdiv, shadow_atlas->quadrants[i].subdivision); + } + } + + if (shadow_atlas->smallest_subdiv == 1 << 30) { + shadow_atlas->smallest_subdiv = 0; + } + + //resort the size orders, simple bublesort for 4 elements.. + + int swaps = 0; + do { + swaps = 0; + + for (int i = 0; i < 3; i++) { + if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i + 1]].subdivision) { + SWAP(shadow_atlas->size_order[i], shadow_atlas->size_order[i + 1]); + swaps++; + } + } + } while (swaps > 0); +} + +bool LightStorage::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) { + for (int i = p_quadrant_count - 1; i >= 0; i--) { + int qidx = p_in_quadrants[i]; + + if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) { + return false; + } + + //look for an empty space + int sc = shadow_atlas->quadrants[qidx].shadows.size(); + const ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr(); + + int found_free_idx = -1; //found a free one + int found_used_idx = -1; //found existing one, must steal it + uint64_t min_pass = 0; // pass of the existing one, try to use the least recently used one (LRU fashion) + + for (int j = 0; j < sc; j++) { + if (!sarr[j].owner.is_valid()) { + found_free_idx = j; + break; + } + + LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner); + ERR_CONTINUE(!sli); + + if (sli->last_scene_pass != RendererSceneRenderRD::get_singleton()->get_scene_pass()) { + //was just allocated, don't kill it so soon, wait a bit.. + if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) { + continue; + } + + if (found_used_idx == -1 || sli->last_scene_pass < min_pass) { + found_used_idx = j; + min_pass = sli->last_scene_pass; + } + } + } + + if (found_free_idx == -1 && found_used_idx == -1) { + continue; //nothing found + } + + if (found_free_idx == -1 && found_used_idx != -1) { + found_free_idx = found_used_idx; + } + + r_quadrant = qidx; + r_shadow = found_free_idx; + + return true; + } + + return false; +} + +bool LightStorage::_shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) { + for (int i = p_quadrant_count - 1; i >= 0; i--) { + int qidx = p_in_quadrants[i]; + + if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) { + return false; + } + + //look for an empty space + int sc = shadow_atlas->quadrants[qidx].shadows.size(); + const ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr(); + + int found_idx = -1; + uint64_t min_pass = 0; // sum of currently selected spots, try to get the least recently used pair + + for (int j = 0; j < sc - 1; j++) { + uint64_t pass = 0; + + if (sarr[j].owner.is_valid()) { + LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner); + ERR_CONTINUE(!sli); + + if (sli->last_scene_pass == RendererSceneRenderRD::get_singleton()->get_scene_pass()) { + continue; + } + + //was just allocated, don't kill it so soon, wait a bit.. + if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) { + continue; + } + pass += sli->last_scene_pass; + } + + if (sarr[j + 1].owner.is_valid()) { + LightInstance *sli = light_instance_owner.get_or_null(sarr[j + 1].owner); + ERR_CONTINUE(!sli); + + if (sli->last_scene_pass == RendererSceneRenderRD::get_singleton()->get_scene_pass()) { + continue; + } + + //was just allocated, don't kill it so soon, wait a bit.. + if (p_tick - sarr[j + 1].alloc_tick < shadow_atlas_realloc_tolerance_msec) { + continue; + } + pass += sli->last_scene_pass; + } + + if (found_idx == -1 || pass < min_pass) { + found_idx = j; + min_pass = pass; + + // we found two empty spots, no need to check the rest + if (pass == 0) { + break; + } + } + } + + if (found_idx == -1) { + continue; //nothing found + } + + r_quadrant = qidx; + r_shadow = found_idx; + + return true; + } + + return false; +} + +bool LightStorage::shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) { + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); + ERR_FAIL_COND_V(!shadow_atlas, false); + + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + ERR_FAIL_COND_V(!li, false); + + if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) { + return false; + } + + uint32_t quad_size = shadow_atlas->size >> 1; + int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage)); + + int valid_quadrants[4]; + int valid_quadrant_count = 0; + int best_size = -1; //best size found + int best_subdiv = -1; //subdiv for the best size + + //find the quadrants this fits into, and the best possible size it can fit into + for (int i = 0; i < 4; i++) { + int q = shadow_atlas->size_order[i]; + int sd = shadow_atlas->quadrants[q].subdivision; + if (sd == 0) { + continue; //unused + } + + int max_fit = quad_size / sd; + + if (best_size != -1 && max_fit > best_size) { + break; //too large + } + + valid_quadrants[valid_quadrant_count++] = q; + best_subdiv = sd; + + if (max_fit >= desired_fit) { + best_size = max_fit; + } + } + + ERR_FAIL_COND_V(valid_quadrant_count == 0, false); + + uint64_t tick = OS::get_singleton()->get_ticks_msec(); + + uint32_t old_key = SHADOW_INVALID; + uint32_t old_quadrant = SHADOW_INVALID; + uint32_t old_shadow = SHADOW_INVALID; + int old_subdivision = -1; + + bool should_realloc = false; + bool should_redraw = false; + + if (shadow_atlas->shadow_owners.has(p_light_instance)) { + old_key = shadow_atlas->shadow_owners[p_light_instance]; + old_quadrant = (old_key >> QUADRANT_SHIFT) & 0x3; + old_shadow = old_key & SHADOW_INDEX_MASK; + + should_realloc = shadow_atlas->quadrants[old_quadrant].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec); + should_redraw = shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].version != p_light_version; + + if (!should_realloc) { + shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = p_light_version; + //already existing, see if it should redraw or it's just OK + return should_redraw; + } + + old_subdivision = shadow_atlas->quadrants[old_quadrant].subdivision; + } + + bool is_omni = li->light_type == RS::LIGHT_OMNI; + bool found_shadow = false; + int new_quadrant = -1; + int new_shadow = -1; + + if (is_omni) { + found_shadow = _shadow_atlas_find_omni_shadows(shadow_atlas, valid_quadrants, valid_quadrant_count, old_subdivision, tick, new_quadrant, new_shadow); + } else { + found_shadow = _shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, old_subdivision, tick, new_quadrant, new_shadow); + } + + if (found_shadow) { + if (old_quadrant != SHADOW_INVALID) { + shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = 0; + shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].owner = RID(); + + if (old_key & OMNI_LIGHT_FLAG) { + shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow + 1].version = 0; + shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow + 1].owner = RID(); + } + } + + uint32_t new_key = new_quadrant << QUADRANT_SHIFT; + new_key |= new_shadow; + + ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; + _shadow_atlas_invalidate_shadow(sh, p_atlas, shadow_atlas, new_quadrant, new_shadow); + + sh->owner = p_light_instance; + sh->alloc_tick = tick; + sh->version = p_light_version; + + if (is_omni) { + new_key |= OMNI_LIGHT_FLAG; + + int new_omni_shadow = new_shadow + 1; + ShadowAtlas::Quadrant::Shadow *extra_sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_omni_shadow]; + _shadow_atlas_invalidate_shadow(extra_sh, p_atlas, shadow_atlas, new_quadrant, new_omni_shadow); + + extra_sh->owner = p_light_instance; + extra_sh->alloc_tick = tick; + extra_sh->version = p_light_version; + } + + li->shadow_atlases.insert(p_atlas); + + //update it in map + shadow_atlas->shadow_owners[p_light_instance] = new_key; + //make it dirty, as it should redraw anyway + return true; + } + + return should_redraw; +} + +void LightStorage::_shadow_atlas_invalidate_shadow(ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx) { + if (p_shadow->owner.is_valid()) { + LightInstance *sli = light_instance_owner.get_or_null(p_shadow->owner); + uint32_t old_key = p_shadow_atlas->shadow_owners[p_shadow->owner]; + + if (old_key & OMNI_LIGHT_FLAG) { + uint32_t s = old_key & SHADOW_INDEX_MASK; + uint32_t omni_shadow_idx = p_shadow_idx + (s == (uint32_t)p_shadow_idx ? 1 : -1); + ShadowAtlas::Quadrant::Shadow *omni_shadow = &p_shadow_atlas->quadrants[p_quadrant].shadows.write[omni_shadow_idx]; + omni_shadow->version = 0; + omni_shadow->owner = RID(); + } + + p_shadow_atlas->shadow_owners.erase(p_shadow->owner); + p_shadow->version = 0; + p_shadow->owner = RID(); + sli->shadow_atlases.erase(p_atlas); + } +} + +void LightStorage::shadow_atlas_update(RID p_atlas) { + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); + ERR_FAIL_COND(!shadow_atlas); + + _update_shadow_atlas(shadow_atlas); +} + +/* DIRECTIONAL SHADOW */ + +void LightStorage::update_directional_shadow_atlas() { + if (directional_shadow.depth.is_null() && directional_shadow.size > 0) { + RD::TextureFormat tf; + tf.format = directional_shadow.use_16_bits ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_D32_SFLOAT; + tf.width = directional_shadow.size; + tf.height = directional_shadow.size; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + directional_shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); + Vector<RID> fb_tex; + fb_tex.push_back(directional_shadow.depth); + directional_shadow.fb = RD::get_singleton()->framebuffer_create(fb_tex); + } +} +void LightStorage::directional_shadow_atlas_set_size(int p_size, bool p_16_bits) { + p_size = nearest_power_of_2_templated(p_size); + + if (directional_shadow.size == p_size && directional_shadow.use_16_bits == p_16_bits) { + return; + } + + directional_shadow.size = p_size; + directional_shadow.use_16_bits = p_16_bits; + + if (directional_shadow.depth.is_valid()) { + RD::get_singleton()->free(directional_shadow.depth); + directional_shadow.depth = RID(); + RendererSceneRenderRD::get_singleton()->base_uniforms_changed(); + } +} + +void LightStorage::set_directional_shadow_count(int p_count) { + directional_shadow.light_count = p_count; + directional_shadow.current_light = 0; +} + +static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p_shadow_index) { + int split_h = 1; + int split_v = 1; + + while (split_h * split_v < p_shadow_count) { + if (split_h == split_v) { + split_h <<= 1; + } else { + split_v <<= 1; + } + } + + Rect2i rect(0, 0, p_size, p_size); + rect.size.width /= split_h; + rect.size.height /= split_v; + + rect.position.x = rect.size.width * (p_shadow_index % split_h); + rect.position.y = rect.size.height * (p_shadow_index / split_h); + + return rect; +} + +Rect2i LightStorage::get_directional_shadow_rect() { + return _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light); +} + +int LightStorage::get_directional_light_shadow_size(RID p_light_intance) { + ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0); + + Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0); + + LightInstance *light_instance = light_instance_owner.get_or_null(p_light_intance); + ERR_FAIL_COND_V(!light_instance, 0); + + switch (light_directional_get_shadow_mode(light_instance->light)) { + case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: + break; //none + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: + r.size.height /= 2; + break; + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: + r.size /= 2; + break; + } + + return MAX(r.size.width, r.size.height); +} + +/* SHADOW CUBEMAPS */ + +LightStorage::ShadowCubemap *LightStorage::_get_shadow_cubemap(int p_size) { + if (!shadow_cubemaps.has(p_size)) { + ShadowCubemap sc; + { + RD::TextureFormat tf; + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; + tf.width = p_size; + tf.height = p_size; + tf.texture_type = RD::TEXTURE_TYPE_CUBE; + tf.array_layers = 6; + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + sc.cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + + for (int i = 0; i < 6; i++) { + RID side_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sc.cubemap, i, 0); + Vector<RID> fbtex; + fbtex.push_back(side_texture); + sc.side_fb[i] = RD::get_singleton()->framebuffer_create(fbtex); + } + + shadow_cubemaps[p_size] = sc; + } + + return &shadow_cubemaps[p_size]; +} + +RID LightStorage::get_cubemap(int p_size) { + ShadowCubemap *cubemap = _get_shadow_cubemap(p_size); + + return cubemap->cubemap; +} + +RID LightStorage::get_cubemap_fb(int p_size, int p_pass) { + ShadowCubemap *cubemap = _get_shadow_cubemap(p_size); + + return cubemap->side_fb[p_pass]; +} diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index 4b34cc74cb..79006ad982 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -32,17 +32,32 @@ #define LIGHT_STORAGE_RD_H #include "core/templates/local_vector.h" +#include "core/templates/paged_array.h" #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" +#include "servers/rendering/renderer_rd/cluster_builder_rd.h" +#include "servers/rendering/renderer_rd/environment/sky.h" +#include "servers/rendering/renderer_rd/storage_rd/forward_id_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/storage/light_storage.h" #include "servers/rendering/storage/utilities.h" +struct RenderDataRD; + namespace RendererRD { class LightStorage : public RendererLightStorage { +public: + enum ShadowAtlastQuadrant { + QUADRANT_SHIFT = 27, + OMNI_LIGHT_FLAG = 1 << 26, + SHADOW_INDEX_MASK = OMNI_LIGHT_FLAG - 1, + SHADOW_INVALID = 0xFFFFFFFF + }; + private: static LightStorage *singleton; + uint32_t max_cluster_elements = 512; /* LIGHT */ struct Light { @@ -71,6 +86,135 @@ private: mutable RID_Owner<Light, true> light_owner; + /* LIGHT INSTANCE */ + + struct LightInstance { + struct ShadowTransform { + Projection camera; + Transform3D transform; + float farplane; + float split; + float bias_scale; + float shadow_texel_size; + float range_begin; + Rect2 atlas_rect; + Vector2 uv_scale; + }; + + RS::LightType light_type = RS::LIGHT_DIRECTIONAL; + + ShadowTransform shadow_transform[6]; + + AABB aabb; + RID self; + RID light; + Transform3D transform; + + Vector3 light_vector; + Vector3 spot_vector; + float linear_att = 0.0; + + uint64_t shadow_pass = 0; + uint64_t last_scene_pass = 0; + uint64_t last_scene_shadow_pass = 0; + uint64_t last_pass = 0; + uint32_t cull_mask = 0; + uint32_t light_directional_index = 0; + + Rect2 directional_rect; + + HashSet<RID> shadow_atlases; //shadow atlases where this light is registered + + ForwardID forward_id = -1; + + LightInstance() {} + }; + + mutable RID_Owner<LightInstance> light_instance_owner; + + /* OMNI/SPOT LIGHT DATA */ + + struct LightData { + float position[3]; + float inv_radius; + float direction[3]; // in omni, x and y are used for dual paraboloid offset + float size; + + float color[3]; + float attenuation; + + float inv_spot_attenuation; + float cos_spot_angle; + float specular_amount; + float shadow_opacity; + + float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv + float shadow_matrix[16]; + float shadow_bias; + float shadow_normal_bias; + float transmittance_bias; + float soft_shadow_size; + float soft_shadow_scale; + uint32_t mask; + float volumetric_fog_energy; + uint32_t bake_mode; + float projector_rect[4]; + }; + + struct LightInstanceDepthSort { + float depth; + LightInstance *light_instance; + Light *light; + bool operator<(const LightInstanceDepthSort &p_sort) const { + return depth < p_sort.depth; + } + }; + + uint32_t max_lights; + uint32_t omni_light_count = 0; + uint32_t spot_light_count = 0; + LightData *omni_lights = nullptr; + LightData *spot_lights = nullptr; + LightInstanceDepthSort *omni_light_sort = nullptr; + LightInstanceDepthSort *spot_light_sort = nullptr; + RID omni_light_buffer; + RID spot_light_buffer; + + /* DIRECTIONAL LIGHT DATA */ + + struct DirectionalLightData { + float direction[3]; + float energy; + float color[3]; + float size; + float specular; + uint32_t mask; + float softshadow_angle; + float soft_shadow_scale; + uint32_t blend_splits; + float shadow_opacity; + float fade_from; + float fade_to; + uint32_t pad[2]; + uint32_t bake_mode; + float volumetric_fog_energy; + float shadow_bias[4]; + float shadow_normal_bias[4]; + float shadow_transmittance_bias[4]; + float shadow_z_range[4]; + float shadow_range_begin[4]; + float shadow_split_offsets[4]; + float shadow_matrices[4][16]; + float uv_scale1[2]; + float uv_scale2[2]; + float uv_scale3[2]; + float uv_scale4[2]; + }; + + uint32_t max_directional_lights; + DirectionalLightData *directional_lights = nullptr; + RID directional_light_buffer; + /* REFLECTION PROBE */ struct ReflectionProbe { @@ -94,6 +238,89 @@ private: }; mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner; + /* REFLECTION ATLAS */ + + struct ReflectionAtlas { + int count = 0; + int size = 0; + + RID reflection; + RID depth_buffer; + RID depth_fb; + + struct Reflection { + RID owner; + RendererRD::SkyRD::ReflectionData data; + RID fbs[6]; + }; + + Vector<Reflection> reflections; + + ClusterBuilderRD *cluster_builder = nullptr; // only used if cluster builder is supported by the renderer. + }; + + mutable RID_Owner<ReflectionAtlas> reflection_atlas_owner; + + /* REFLECTION PROBE INSTANCE */ + + struct ReflectionProbeInstance { + RID probe; + int atlas_index = -1; + RID atlas; + + bool dirty = true; + bool rendering = false; + int processing_layer = 1; + int processing_side = 0; + + uint32_t render_step = 0; + uint64_t last_pass = 0; + uint32_t cull_mask = 0; + + RendererRD::ForwardID forward_id = -1; + + Transform3D transform; + }; + + mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner; + + /* REFLECTION DATA */ + + enum { + REFLECTION_AMBIENT_DISABLED = 0, + REFLECTION_AMBIENT_ENVIRONMENT = 1, + REFLECTION_AMBIENT_COLOR = 2, + }; + + struct ReflectionData { + float box_extents[3]; + float index; + float box_offset[3]; + uint32_t mask; + float ambient[3]; // ambient color, + float intensity; + uint32_t exterior; + uint32_t box_project; + uint32_t ambient_mode; + float exposure_normalization; + float local_matrix[16]; // up to here for spot and omni, rest is for directional + }; + + struct ReflectionProbeInstanceSort { + float depth; + ReflectionProbeInstance *probe_instance; + bool operator<(const ReflectionProbeInstanceSort &p_sort) const { + return depth < p_sort.depth; + } + }; + + uint32_t max_reflections; + uint32_t reflection_count = 0; + // uint32_t max_reflection_probes_per_instance = 0; // seems unused + ReflectionData *reflections = nullptr; + ReflectionProbeInstanceSort *reflection_sort = nullptr; + RID reflection_buffer; + /* LIGHTMAP */ struct Lightmap { @@ -124,12 +351,101 @@ private: mutable RID_Owner<Lightmap, true> lightmap_owner; + /* LIGHTMAP INSTANCE */ + + struct LightmapInstance { + RID lightmap; + Transform3D transform; + }; + + mutable RID_Owner<LightmapInstance> lightmap_instance_owner; + + /* SHADOW ATLAS */ + + uint64_t shadow_atlas_realloc_tolerance_msec = 500; + + struct ShadowShrinkStage { + RID texture; + RID filter_texture; + uint32_t size = 0; + }; + + struct ShadowAtlas { + struct Quadrant { + uint32_t subdivision = 0; + + struct Shadow { + RID owner; + uint64_t version = 0; + uint64_t fog_version = 0; // used for fog + uint64_t alloc_tick = 0; + + Shadow() {} + }; + + Vector<Shadow> shadows; + + Quadrant() {} + } quadrants[4]; + + int size_order[4] = { 0, 1, 2, 3 }; + uint32_t smallest_subdiv = 0; + + int size = 0; + bool use_16_bits = true; + + RID depth; + RID fb; //for copying + + HashMap<RID, uint32_t> shadow_owners; + }; + + RID_Owner<ShadowAtlas> shadow_atlas_owner; + + void _update_shadow_atlas(ShadowAtlas *shadow_atlas); + + void _shadow_atlas_invalidate_shadow(ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx); + bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow); + bool _shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow); + + /* DIRECTIONAL SHADOW */ + + struct DirectionalShadow { + RID depth; + RID fb; //when renderign direct + + int light_count = 0; + int size = 0; + bool use_16_bits = true; + int current_light = 0; + } directional_shadow; + + /* SHADOW CUBEMAPS */ + + struct ShadowCubemap { + RID cubemap; + RID side_fb[6]; + }; + + HashMap<int, ShadowCubemap> shadow_cubemaps; + ShadowCubemap *_get_shadow_cubemap(int p_size); + public: static LightStorage *get_singleton(); LightStorage(); virtual ~LightStorage(); + bool free(RID p_rid); + + /* Settings */ + void set_max_cluster_elements(const uint32_t p_max_cluster_elements) { + max_cluster_elements = p_max_cluster_elements; + set_max_reflection_probes(p_max_cluster_elements); + set_max_lights(p_max_cluster_elements); + } + uint32_t get_max_cluster_elements() const { return max_cluster_elements; } + /* LIGHT */ bool owns_light(RID p_rid) { return light_owner.owns(p_rid); }; @@ -259,6 +575,205 @@ public: Dependency *light_get_dependency(RID p_light) const; + /* LIGHT INSTANCE API */ + + bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); }; + + virtual RID light_instance_create(RID p_light) override; + virtual void light_instance_free(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 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) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->light; + } + + _FORCE_INLINE_ Transform3D light_instance_get_base_transform(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->transform; + } + + _FORCE_INLINE_ AABB light_instance_get_base_aabb(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->aabb; + } + + _FORCE_INLINE_ void light_instance_set_cull_mask(RID p_light_instance, uint32_t p_cull_mask) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + li->cull_mask = p_cull_mask; + } + + _FORCE_INLINE_ uint32_t light_instance_get_cull_mask(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->cull_mask; + } + + _FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas, Vector2i &r_omni_offset) { + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + uint32_t key = shadow_atlas->shadow_owners[li->self]; + + uint32_t quadrant = (key >> QUADRANT_SHIFT) & 0x3; + uint32_t shadow = key & SHADOW_INDEX_MASK; + + ERR_FAIL_COND_V(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size(), Rect2()); + + uint32_t atlas_size = shadow_atlas->size; + uint32_t quadrant_size = atlas_size >> 1; + + uint32_t x = (quadrant & 1) * quadrant_size; + uint32_t y = (quadrant >> 1) * quadrant_size; + + uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); + x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + + if (key & OMNI_LIGHT_FLAG) { + if (((shadow + 1) % shadow_atlas->quadrants[quadrant].subdivision) == 0) { + r_omni_offset.x = 1 - int(shadow_atlas->quadrants[quadrant].subdivision); + r_omni_offset.y = 1; + } else { + r_omni_offset.x = 1; + r_omni_offset.y = 0; + } + } + + uint32_t width = shadow_size; + uint32_t height = shadow_size; + + return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size)); + } + + _FORCE_INLINE_ float light_instance_get_shadow_texel_size(RID p_light_instance, RID p_shadow_atlas) { +#ifdef DEBUG_ENABLED + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + ERR_FAIL_COND_V(!li->shadow_atlases.has(p_shadow_atlas), 0); +#endif + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); + ERR_FAIL_COND_V(!shadow_atlas, 0); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(!shadow_atlas->shadow_owners.has(p_light_instance), 0); +#endif + uint32_t key = shadow_atlas->shadow_owners[p_light_instance]; + + uint32_t quadrant = (key >> QUADRANT_SHIFT) & 0x3; + + uint32_t quadrant_size = shadow_atlas->size >> 1; + + uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); + + return float(1.0) / shadow_size; + } + + _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; + } + + _FORCE_INLINE_ Transform3D + light_instance_get_shadow_transform(RID p_light_instance, int p_index) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->shadow_transform[p_index].transform; + } + _FORCE_INLINE_ float light_instance_get_shadow_bias_scale(RID p_light_instance, int p_index) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->shadow_transform[p_index].bias_scale; + } + _FORCE_INLINE_ float light_instance_get_shadow_range(RID p_light_instance, int p_index) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->shadow_transform[p_index].farplane; + } + _FORCE_INLINE_ float light_instance_get_shadow_range_begin(RID p_light_instance, int p_index) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->shadow_transform[p_index].range_begin; + } + + _FORCE_INLINE_ Vector2 light_instance_get_shadow_uv_scale(RID p_light_instance, int p_index) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->shadow_transform[p_index].uv_scale; + } + + _FORCE_INLINE_ void light_instance_set_directional_shadow_atlas_rect(RID p_light_instance, int p_index, const Rect2 p_atlas_rect) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + li->shadow_transform[p_index].atlas_rect = p_atlas_rect; + } + + _FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->shadow_transform[p_index].atlas_rect; + } + + _FORCE_INLINE_ float light_instance_get_directional_shadow_split(RID p_light_instance, int p_index) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->shadow_transform[p_index].split; + } + + _FORCE_INLINE_ float light_instance_get_directional_shadow_texel_size(RID p_light_instance, int p_index) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->shadow_transform[p_index].shadow_texel_size; + } + + _FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + li->last_pass = p_pass; + } + + _FORCE_INLINE_ uint64_t light_instance_get_render_pass(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->last_pass; + } + + _FORCE_INLINE_ void light_instance_set_shadow_pass(RID p_light_instance, uint64_t p_pass) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + li->last_scene_shadow_pass = p_pass; + } + + _FORCE_INLINE_ uint64_t light_instance_get_shadow_pass(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->last_scene_shadow_pass; + } + + _FORCE_INLINE_ ForwardID light_instance_get_forward_id(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->forward_id; + } + + _FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->light_type; + } + + _FORCE_INLINE_ void light_instance_set_directional_rect(RID p_light_instance, const Rect2 &p_directional_rect) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + li->directional_rect = p_directional_rect; + } + + _FORCE_INLINE_ Rect2 light_instance_get_directional_rect(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->directional_rect; + } + + /* LIGHT DATA */ + + void free_light_data(); + void set_max_lights(const uint32_t p_max_lights); + RID get_omni_light_buffer() { return omni_light_buffer; } + RID get_spot_light_buffer() { return spot_light_buffer; } + RID get_directional_light_buffer() { return directional_light_buffer; } + uint32_t get_max_directional_lights() { return max_directional_lights; } + bool has_directional_shadows(const uint32_t p_directional_light_count) { + for (uint32_t i = 0; i < p_directional_light_count; i++) { + if (directional_lights[i].shadow_opacity > 0.001) { + return true; + } + } + return false; + } + void update_light_buffers(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows); + /* REFLECTION PROBE */ bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); }; @@ -305,6 +820,94 @@ public: Dependency *reflection_probe_get_dependency(RID p_probe) const; + /* REFLECTION ATLAS */ + + bool owns_reflection_atlas(RID p_rid) { return reflection_atlas_owner.owns(p_rid); } + + virtual RID reflection_atlas_create() override; + virtual void reflection_atlas_free(RID p_ref_atlas) override; + virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override; + virtual int reflection_atlas_get_size(RID p_ref_atlas) const override; + + _FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) { + ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_ref_atlas); + ERR_FAIL_COND_V(!atlas, RID()); + return atlas->reflection; + } + + /* REFLECTION PROBE INSTANCE */ + + bool owns_reflection_probe_instance(RID p_rid) { return reflection_probe_instance_owner.owns(p_rid); } + + virtual RID reflection_probe_instance_create(RID p_probe) override; + virtual void reflection_probe_instance_free(RID p_instance) override; + virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override; + virtual void reflection_probe_release_atlas_index(RID p_instance) override; + virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override; + virtual bool reflection_probe_instance_has_reflection(RID p_instance) override; + virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override; + virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override; + + uint32_t reflection_probe_instance_get_resolution(RID p_instance); + RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index); + RID reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index); + + _FORCE_INLINE_ RID reflection_probe_instance_get_probe(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, RID()); + + return rpi->probe; + } + + _FORCE_INLINE_ RendererRD::ForwardID reflection_probe_instance_get_forward_id(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, 0); + + return rpi->forward_id; + } + + _FORCE_INLINE_ void reflection_probe_instance_set_cull_mask(RID p_instance, uint32_t p_render_pass) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND(!rpi); + rpi->cull_mask = p_render_pass; + } + + _FORCE_INLINE_ void reflection_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND(!rpi); + rpi->last_pass = p_render_pass; + } + + _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_pass(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, 0); + + return rpi->last_pass; + } + + _FORCE_INLINE_ Transform3D reflection_probe_instance_get_transform(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, Transform3D()); + + return rpi->transform; + } + + _FORCE_INLINE_ int reflection_probe_instance_get_atlas_index(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); + ERR_FAIL_COND_V(!rpi, -1); + + return rpi->atlas_index; + } + + ClusterBuilderRD *reflection_probe_instance_get_cluster_builder(RID p_instance, ClusterBuilderSharedDataRD *p_cluster_builder_shared); + + /* REFLECTION DATA */ + + void free_reflection_data(); + void set_max_reflection_probes(const uint32_t p_max_reflection_probes); + RID get_reflection_probe_buffer() { return reflection_buffer; } + void update_reflection_probe_buffer(RenderDataRD *p_render_data, const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment); + /* LIGHTMAP */ bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); }; @@ -366,6 +969,111 @@ public: ERR_FAIL_COND_V(!using_lightmap_array, lightmap_textures); //only for arrays return lightmap_textures; } + + /* LIGHTMAP INSTANCE */ + + bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); }; + + virtual RID lightmap_instance_create(RID p_lightmap) override; + virtual void lightmap_instance_free(RID p_lightmap) override; + virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override; + _FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) { + return lightmap_instance_owner.get_or_null(p_lightmap_instance) != nullptr; + } + + _FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) { + LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap_instance); + return li->lightmap; + } + _FORCE_INLINE_ Transform3D lightmap_instance_get_transform(RID p_lightmap_instance) { + LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap_instance); + return li->transform; + } + + /* SHADOW ATLAS API */ + + bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); }; + + virtual RID shadow_atlas_create() override; + virtual void shadow_atlas_free(RID p_atlas) override; + + virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override; + virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override; + virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) override; + _FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) { + ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); + ERR_FAIL_COND_V(!atlas, false); + return atlas->shadow_owners.has(p_light_intance); + } + _FORCE_INLINE_ uint32_t shadow_atlas_get_light_instance_key(RID p_atlas, RID p_light_intance) { + ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); + ERR_FAIL_COND_V(!atlas, -1); + return atlas->shadow_owners[p_light_intance]; + } + + _FORCE_INLINE_ RID shadow_atlas_get_texture(RID p_atlas) { + ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); + ERR_FAIL_COND_V(!atlas, RID()); + return atlas->depth; + } + + _FORCE_INLINE_ int shadow_atlas_get_size(RID p_atlas) { + ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); + ERR_FAIL_COND_V(!atlas, 0); + return atlas->size; + } + + _FORCE_INLINE_ int shadow_atlas_get_quadrant_shadow_size(RID p_atlas, uint32_t p_quadrant) { + ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); + ERR_FAIL_COND_V(!atlas, 0); + ERR_FAIL_UNSIGNED_INDEX_V(p_quadrant, 4, 0); + return atlas->quadrants[p_quadrant].shadows.size(); + } + + _FORCE_INLINE_ uint32_t shadow_atlas_get_quadrant_subdivision(RID p_atlas, uint32_t p_quadrant) { + ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); + ERR_FAIL_COND_V(!atlas, 0); + ERR_FAIL_UNSIGNED_INDEX_V(p_quadrant, 4, 0); + return atlas->quadrants[p_quadrant].subdivision; + } + + _FORCE_INLINE_ RID shadow_atlas_get_fb(RID p_atlas) { + ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); + ERR_FAIL_COND_V(!atlas, RID()); + return atlas->fb; + } + + virtual void shadow_atlas_update(RID p_atlas) override; + + /* DIRECTIONAL SHADOW */ + + virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override; + virtual int get_directional_light_shadow_size(RID p_light_intance) override; + virtual void set_directional_shadow_count(int p_count) override; + + Rect2i get_directional_shadow_rect(); + void update_directional_shadow_atlas(); + + _FORCE_INLINE_ RID directional_shadow_get_texture() { + return directional_shadow.depth; + } + + _FORCE_INLINE_ int directional_shadow_get_size() { + return directional_shadow.size; + } + + _FORCE_INLINE_ RID direction_shadow_get_fb() { + return directional_shadow.fb; + } + + _FORCE_INLINE_ void directional_shadow_increase_current_light() { + directional_shadow.current_light++; + } + + /* SHADOW CUBEMAPS */ + + RID get_cubemap(int p_size); + RID get_cubemap_fb(int p_size, int p_pass); }; } // namespace RendererRD diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index b36a028f04..1fecac9045 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -720,7 +720,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy 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]; + gui[i * 4 + j] = v.columns[i][j]; } } } @@ -1270,7 +1270,7 @@ void MaterialStorage::MaterialData::free_parameters_uniform_set(RID p_uniform_se } } -bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { +bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, uint32_t p_barrier) { if ((uint32_t)ubo_data.size() != p_ubo_size) { p_uniform_dirty = true; if (uniform_buffer.is_valid()) { @@ -1294,7 +1294,7 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap< //check whether buffer changed if (p_uniform_dirty && ubo_data.size()) { - update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true); + update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), p_use_linear_color); RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier); } @@ -1528,6 +1528,18 @@ MaterialStorage::~MaterialStorage() { singleton = nullptr; } +bool MaterialStorage::free(RID p_rid) { + if (owns_shader(p_rid)) { + shader_free(p_rid); + return true; + } else if (owns_material(p_rid)) { + material_free(p_rid); + return true; + } + + return false; +} + /* Samplers */ void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) { @@ -2526,7 +2538,7 @@ void MaterialStorage::_update_queued_materials() { material_update_list.remove(&material->update_element); if (uniforms_changed) { - //some implementations such as 3D renderer cache the matreial uniform set, so update is required + //some implementations such as 3D renderer cache the material uniform set, so update is required material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); } } diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index db2e4cfa2a..19c2f39553 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -79,7 +79,7 @@ public: virtual ~MaterialData(); //to be used internally by update_parameters, in the most common configuration of material parameters - bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, uint32_t p_barrier = RD::BARRIER_MASK_ALL); void free_parameters_uniform_set(RID p_uniform_set); private: @@ -231,6 +231,8 @@ public: MaterialStorage(); virtual ~MaterialStorage(); + bool free(RID p_rid); + /* Helpers */ static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) { @@ -300,7 +302,7 @@ public: 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]; + p_array[i * 4 + j] = p_mtx.columns[i][j]; } } } @@ -311,6 +313,18 @@ public: } } + // http://andrewthall.org/papers/df64_qf128.pdf +#ifdef REAL_T_IS_DOUBLE + static _FORCE_INLINE_ void split_double(double a, float *ahi, float *alo) { + const double SPLITTER = (1 << 29) + 1; + double t = a * SPLITTER; + double thi = t - (t - a); + double tlo = a - thi; + *ahi = (float)thi; + *alo = (float)tlo; + } +#endif + /* Samplers */ _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 1827b73507..1e74d31383 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -197,6 +197,24 @@ MeshStorage::~MeshStorage() { singleton = nullptr; } +bool MeshStorage::free(RID p_rid) { + if (owns_mesh(p_rid)) { + mesh_free(p_rid); + return true; + } else if (owns_mesh_instance(p_rid)) { + mesh_instance_free(p_rid); + return true; + } else if (owns_multimesh(p_rid)) { + multimesh_free(p_rid); + return true; + } else if (owns_skeleton(p_rid)) { + skeleton_free(p_rid); + return true; + } + + return false; +} + /* MESH API */ RID MeshStorage::mesh_allocate() { @@ -2021,6 +2039,7 @@ Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bo void MeshStorage::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); + ERR_FAIL_NULL(skeleton); ERR_FAIL_COND(!skeleton->use_2d); skeleton->base_transform_2d = p_base_transform; diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 622f3911c7..c8a33bd4d7 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -308,6 +308,8 @@ public: MeshStorage(); virtual ~MeshStorage(); + bool free(RID p_rid); + RID get_default_rd_storage_buffer() const { return default_rd_storage_buffer; } /* MESH API */ diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 07d682bcc1..78f4c410c3 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -102,7 +102,7 @@ ParticlesStorage::ParticlesStorage() { actions.render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; actions.render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; - actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISON_SCALE\n"; + actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISION_SCALE\n"; actions.sampler_array_name = "material_samplers"; actions.base_texture_binding_index = 1; @@ -208,6 +208,21 @@ ParticlesStorage::~ParticlesStorage() { singleton = nullptr; } +bool ParticlesStorage::free(RID p_rid) { + if (owns_particles(p_rid)) { + particles_free(p_rid); + return true; + } else if (owns_particles_collision(p_rid)) { + particles_collision_free(p_rid); + return true; + } else if (owns_particles_collision_instance(p_rid)) { + particles_collision_instance_free(p_rid); + return true; + } + + return false; +} + /* PARTICLES */ RID ParticlesStorage::particles_allocate() { @@ -1697,7 +1712,7 @@ MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() { } bool ParticlesStorage::ParticleProcessMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - 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, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); + 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, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3, true); } ParticlesStorage::ParticleProcessMaterialData::~ParticleProcessMaterialData() { diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index af29f5022b..017844626f 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -405,6 +405,8 @@ public: ParticlesStorage(); virtual ~ParticlesStorage(); + bool free(RID p_rid); + /* PARTICLES */ bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); } diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp index 16fdbc07f5..0c2092f03e 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp @@ -40,11 +40,6 @@ RenderSceneBuffersRD::~RenderSceneBuffersRD() { cleanup(); data_buffers.clear(); - - // need to investigate if we can remove these things. - if (cluster_builder) { - memdelete(cluster_builder); - } } void RenderSceneBuffersRD::_bind_methods() { @@ -121,21 +116,6 @@ void RenderSceneBuffersRD::cleanup() { RD::get_singleton()->free(luminance.current); luminance.current = RID(); } - - if (ss_effects.linear_depth.is_valid()) { - RD::get_singleton()->free(ss_effects.linear_depth); - ss_effects.linear_depth = RID(); - ss_effects.linear_depth_slices.clear(); - } - - if (ss_effects.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects.downsample_uniform_set)) { - RD::get_singleton()->free(ss_effects.downsample_uniform_set); - ss_effects.downsample_uniform_set = RID(); - } - - sse->ssao_free(ss_effects.ssao); - sse->ssil_free(ss_effects.ssil); - sse->ssr_free(ssr); } void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { @@ -179,14 +159,6 @@ void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_interna use_debanding = p_use_debanding; view_count = p_view_count; - /* may move this into our clustered renderer data object */ - if (can_be_storage) { - if (cluster_builder == nullptr) { - cluster_builder = memnew(ClusterBuilderRD); - } - cluster_builder->set_shared(RendererSceneRenderRD::get_singleton()->get_cluster_builder_shared()); - } - // cleanout any old buffers we had. cleanup(); @@ -206,7 +178,7 @@ void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_interna // Create our depth buffer { - // TODO If we have depth buffer supplied externally, pick this up + // TODO Lazy create this in case we've got an external depth buffer RD::DataFormat format; uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; @@ -233,11 +205,6 @@ void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_interna for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) { E.value->configure(this); } - - if (cluster_builder) { - RID sampler = RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - cluster_builder->setup(internal_size, max_cluster_elements, get_depth_texture(), sampler, get_internal_texture()); - } } void RenderSceneBuffersRD::set_fsr_sharpness(float p_fsr_sharpness) { @@ -523,6 +490,28 @@ Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const String return ret; } +// Depth texture + +RID RenderSceneBuffersRD::get_depth_texture() { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RID depth = texture_storage->render_target_get_override_depth(render_target); + if (depth.is_valid()) { + return depth; + } else { + return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH); + } +} + +RID RenderSceneBuffersRD::get_depth_texture(const uint32_t p_layer) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RID depth_slice = texture_storage->render_target_get_override_depth_slice(render_target, p_layer); + if (depth_slice.is_valid()) { + return depth_slice; + } else { + return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, p_layer, 0); + } +} + // Velocity texture. void RenderSceneBuffersRD::ensure_velocity() { @@ -549,6 +538,20 @@ void RenderSceneBuffersRD::ensure_velocity() { } } +bool RenderSceneBuffersRD::has_velocity_buffer(bool p_has_msaa) { + if (p_has_msaa) { + return has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA); + } else { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RID velocity = texture_storage->render_target_get_override_velocity(render_target); + if (velocity.is_valid()) { + return true; + } else { + return has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY); + } + } +} + RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa) { if (p_get_msaa) { if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA)) { @@ -557,10 +560,28 @@ RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa) { return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA); } } else { - if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RID velocity = texture_storage->render_target_get_override_velocity(render_target); + if (velocity.is_valid()) { + return velocity; + } else if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) { return RID(); } else { return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY); } } } + +RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa, uint32_t p_layer) { + if (p_get_msaa) { + return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA, p_layer, 0); + } else { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RID velocity_slice = texture_storage->render_target_get_override_velocity_slice(render_target, p_layer); + if (velocity_slice.is_valid()) { + return velocity_slice; + } else { + return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY, p_layer, 0); + } + } +} diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h index 1975eec7b0..6907f69b93 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h @@ -31,19 +31,14 @@ #ifndef RENDER_SCENE_BUFFERS_RD_H #define RENDER_SCENE_BUFFERS_RD_H +#include "../effects/vrs.h" +#include "../framebuffer_cache_rd.h" #include "core/templates/hash_map.h" -#include "servers/rendering/renderer_rd/effects/vrs.h" -#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h" -#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h" +#include "render_buffer_custom_data_rd.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_method.h" #include "servers/rendering/storage/render_scene_buffers.h" -// These can be retired in due time -#include "servers/rendering/renderer_rd/cluster_builder_rd.h" -#include "servers/rendering/renderer_rd/effects/ss_effects.h" -#include "servers/rendering/renderer_rd/environment/fog.h" - #define RB_SCOPE_BUFFERS SNAME("render_buffers") #define RB_SCOPE_VRS SNAME("VRS") @@ -68,7 +63,6 @@ private: bool can_be_storage = true; uint32_t max_cluster_elements = 512; RD::DataFormat base_data_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - RendererRD::SSEffects *sse = nullptr; RendererRD::VRS *vrs = nullptr; uint64_t auto_exposure_version = 1; @@ -139,9 +133,9 @@ public: // info from our renderer void set_can_be_storage(const bool p_can_be_storage) { can_be_storage = p_can_be_storage; } void set_max_cluster_elements(const uint32_t p_max_elements) { max_cluster_elements = p_max_elements; } + uint32_t get_max_cluster_elements() { return max_cluster_elements; } void set_base_data_format(const RD::DataFormat p_base_data_format) { base_data_format = p_base_data_format; } RD::DataFormat get_base_data_format() const { return base_data_format; } - void set_sseffects(RendererRD::SSEffects *p_ss_effects) { sse = p_ss_effects; } void set_vrs(RendererRD::VRS *p_vrs) { vrs = p_vrs; } void cleanup(); @@ -195,12 +189,8 @@ public: return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0); } - _FORCE_INLINE_ RID get_depth_texture() const { - return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH); - } - _FORCE_INLINE_ RID get_depth_texture(const uint32_t p_layer) { - return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, p_layer, 0); - } + RID get_depth_texture(); + RID get_depth_texture(const uint32_t p_layer); // back buffer (color) RID get_back_buffer_texture() const { return has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) ? get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) : RID(); } // We (re)use our blur texture here. @@ -208,15 +198,13 @@ public: // Velocity, currently only used by TAA (Clustered) but we'll be using this in other places soon too. void ensure_velocity(); - bool has_velocity_buffer(bool p_has_msaa) { return has_texture(RB_SCOPE_BUFFERS, p_has_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY); } + bool has_velocity_buffer(bool p_has_msaa); RID get_velocity_buffer(bool p_get_msaa); - RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer) { return get_texture_slice(RB_SCOPE_BUFFERS, p_get_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY, p_layer, 0); } + RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Everything after this needs to be re-evaluated, this is all old implementation - ClusterBuilderRD *cluster_builder = nullptr; - struct WeightBuffers { RID weight; RID fb; // FB with both texture and weight writing into one level lower @@ -233,24 +221,6 @@ public: Vector<RID> fb; RID current_fb; } luminance; - - struct SSEffects { - RID linear_depth; - Vector<RID> linear_depth_slices; - - RID downsample_uniform_set; - - Projection last_frame_projection; - Transform3D last_frame_transform; - - RendererRD::SSEffects::SSAORenderBuffers ssao; - RendererRD::SSEffects::SSILRenderBuffers ssil; - } ss_effects; - - RendererRD::SSEffects::SSRRenderBuffers ssr; - - RID get_ao_texture() const { return ss_effects.ssao.ao_final; } - RID get_ssil_texture() const { return ss_effects.ssil.ssil_final; } }; #endif // RENDER_SCENE_BUFFERS_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp index f925f87cbe..7dd790d1da 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp @@ -59,6 +59,12 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p RendererRD::MaterialStorage::store_transform(cam_transform, ubo.inv_view_matrix); RendererRD::MaterialStorage::store_transform(cam_transform.affine_inverse(), ubo.view_matrix); +#ifdef REAL_T_IS_DOUBLE + RendererRD::MaterialStorage::split_double(-cam_transform.origin.x, &ubo.inv_view_matrix[12], &ubo.inv_view_matrix[3]); + RendererRD::MaterialStorage::split_double(-cam_transform.origin.y, &ubo.inv_view_matrix[13], &ubo.inv_view_matrix[7]); + RendererRD::MaterialStorage::split_double(-cam_transform.origin.z, &ubo.inv_view_matrix[14], &ubo.inv_view_matrix[11]); +#endif + for (uint32_t v = 0; v < view_count; v++) { projection = correction * view_projection[v]; RendererRD::MaterialStorage::store_camera(projection, ubo.projection_matrix_view[v]); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 800a742cb6..b3a7e05ff5 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -30,7 +30,9 @@ #include "texture_storage.h" #include "../effects/copy_effects.h" +#include "../framebuffer_cache_rd.h" #include "material_storage.h" +#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" using namespace RendererRD; @@ -457,6 +459,8 @@ TextureStorage::TextureStorage() { TextureStorage::~TextureStorage() { rt_sdf.shader.version_free(rt_sdf.shader_version); + free_decal_data(); + if (decal_atlas.textures.size()) { ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas."); } @@ -475,6 +479,27 @@ TextureStorage::~TextureStorage() { singleton = nullptr; } +bool TextureStorage::free(RID p_rid) { + if (owns_texture(p_rid)) { + texture_free(p_rid); + return true; + } else if (owns_canvas_texture(p_rid)) { + canvas_texture_free(p_rid); + return true; + } else if (owns_decal(p_rid)) { + decal_free(p_rid); + return true; + } else if (owns_decal_instance(p_rid)) { + decal_instance_free(p_rid); + return true; + } else if (owns_render_target(p_rid)) { + render_target_free(p_rid); + return true; + } + + return false; +} + bool TextureStorage::can_create_resources_async() const { return true; } @@ -673,6 +698,8 @@ void TextureStorage::texture_free(RID p_texture) { } void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) { + ERR_FAIL_COND(p_image.is_null()); + TextureToRDFormat ret_format; Ref<Image> image = _validate_texture_format(p_image, ret_format); @@ -1886,7 +1913,7 @@ Dependency *TextureStorage::decal_get_dependency(RID p_decal) { } void TextureStorage::update_decal_atlas() { - RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); + CopyEffects *copy_effects = CopyEffects::get_singleton(); ERR_FAIL_NULL(copy_effects); if (!decal_atlas.dirty) { @@ -2110,12 +2137,249 @@ void TextureStorage::texture_remove_from_decal_atlas(RID p_texture, bool p_panor } } +/* DECAL INSTANCE API */ + +RID TextureStorage::decal_instance_create(RID p_decal) { + DecalInstance di; + di.decal = p_decal; + di.forward_id = ForwardIDStorage::get_singleton()->allocate_forward_id(FORWARD_ID_TYPE_DECAL); + return decal_instance_owner.make_rid(di); +} + +void TextureStorage::decal_instance_free(RID p_decal_instance) { + DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance); + ForwardIDStorage::get_singleton()->free_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id); + decal_instance_owner.free(p_decal_instance); +} + +void TextureStorage::decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) { + DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance); + ERR_FAIL_COND(!di); + di->transform = p_transform; +} + +/* DECAL DATA API */ + +void TextureStorage::free_decal_data() { + if (decal_buffer.is_valid()) { + RD::get_singleton()->free(decal_buffer); + decal_buffer = RID(); + } + + if (decals != nullptr) { + memdelete_arr(decals); + decals = nullptr; + } + + if (decal_sort != nullptr) { + memdelete_arr(decal_sort); + decal_sort = nullptr; + } +} + +void TextureStorage::set_max_decals(const uint32_t p_max_decals) { + max_decals = p_max_decals; + uint32_t decal_buffer_size = max_decals * sizeof(DecalData); + decals = memnew_arr(DecalData, max_decals); + decal_sort = memnew_arr(DecalInstanceSort, max_decals); + decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size); +} + +void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) { + ForwardIDStorage *forward_id_storage = ForwardIDStorage::get_singleton(); + + Transform3D uv_xform; + uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0)); + uv_xform.origin = Vector3(-1.0, 0.0, -1.0); + + uint32_t decals_size = p_decals.size(); + + decal_count = 0; + + for (uint32_t i = 0; i < decals_size; i++) { + if (decal_count == max_decals) { + break; + } + + DecalInstance *decal_instance = decal_instance_owner.get_or_null(p_decals[i]); + if (!decal_instance) { + continue; + } + Decal *decal = decal_owner.get_or_null(decal_instance->decal); + + Transform3D xform = decal_instance->transform; + + real_t distance = -p_camera_inverse_xform.xform(xform.origin).z; + + if (decal->distance_fade) { + float fade_begin = decal->distance_fade_begin; + float fade_length = decal->distance_fade_length; + + if (distance > fade_begin) { + if (distance > fade_begin + fade_length) { + continue; // do not use this decal, its invisible + } + } + } + + decal_sort[decal_count].decal_instance = decal_instance; + decal_sort[decal_count].decal = decal; + decal_sort[decal_count].depth = distance; + decal_count++; + } + + if (decal_count > 0) { + SortArray<DecalInstanceSort> sort_array; + sort_array.sort(decal_sort, decal_count); + } + + bool using_forward_ids = forward_id_storage->uses_forward_ids(); + for (uint32_t i = 0; i < decal_count; i++) { + DecalInstance *decal_instance = decal_sort[i].decal_instance; + Decal *decal = decal_sort[i].decal; + + if (using_forward_ids) { + forward_id_storage->map_forward_id(FORWARD_ID_TYPE_DECAL, decal_instance->forward_id, i); + } + + decal_instance->cull_mask = decal->cull_mask; + + Transform3D xform = decal_instance->transform; + float fade = 1.0; + + if (decal->distance_fade) { + const real_t distance = -p_camera_inverse_xform.xform(xform.origin).z; + const float fade_begin = decal->distance_fade_begin; + const float fade_length = decal->distance_fade_length; + + if (distance > fade_begin) { + // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player. + fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length); + } + } + + DecalData &dd = decals[i]; + + Vector3 decal_extents = decal->extents; + + Transform3D scale_xform; + scale_xform.basis.scale(decal_extents); + Transform3D to_decal_xform = (p_camera_inverse_xform * xform * scale_xform * uv_xform).affine_inverse(); + MaterialStorage::store_transform(to_decal_xform, dd.xform); + + Vector3 normal = xform.basis.get_column(Vector3::AXIS_Y).normalized(); + normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine + + dd.normal[0] = normal.x; + dd.normal[1] = normal.y; + dd.normal[2] = normal.z; + dd.normal_fade = decal->normal_fade; + + RID albedo_tex = decal->textures[RS::DECAL_TEXTURE_ALBEDO]; + RID emission_tex = decal->textures[RS::DECAL_TEXTURE_EMISSION]; + if (albedo_tex.is_valid()) { + Rect2 rect = decal_atlas_get_texture_rect(albedo_tex); + dd.albedo_rect[0] = rect.position.x; + dd.albedo_rect[1] = rect.position.y; + dd.albedo_rect[2] = rect.size.x; + dd.albedo_rect[3] = rect.size.y; + } else { + if (!emission_tex.is_valid()) { + continue; //no albedo, no emission, no decal. + } + dd.albedo_rect[0] = 0; + dd.albedo_rect[1] = 0; + dd.albedo_rect[2] = 0; + dd.albedo_rect[3] = 0; + } + + RID normal_tex = decal->textures[RS::DECAL_TEXTURE_NORMAL]; + + if (normal_tex.is_valid()) { + Rect2 rect = decal_atlas_get_texture_rect(normal_tex); + dd.normal_rect[0] = rect.position.x; + dd.normal_rect[1] = rect.position.y; + dd.normal_rect[2] = rect.size.x; + dd.normal_rect[3] = rect.size.y; + + Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized(); + MaterialStorage::store_basis_3x4(normal_xform, dd.normal_xform); + } else { + dd.normal_rect[0] = 0; + dd.normal_rect[1] = 0; + dd.normal_rect[2] = 0; + dd.normal_rect[3] = 0; + } + + RID orm_tex = decal->textures[RS::DECAL_TEXTURE_ORM]; + if (orm_tex.is_valid()) { + Rect2 rect = decal_atlas_get_texture_rect(orm_tex); + dd.orm_rect[0] = rect.position.x; + dd.orm_rect[1] = rect.position.y; + dd.orm_rect[2] = rect.size.x; + dd.orm_rect[3] = rect.size.y; + } else { + dd.orm_rect[0] = 0; + dd.orm_rect[1] = 0; + dd.orm_rect[2] = 0; + dd.orm_rect[3] = 0; + } + + if (emission_tex.is_valid()) { + Rect2 rect = decal_atlas_get_texture_rect(emission_tex); + dd.emission_rect[0] = rect.position.x; + dd.emission_rect[1] = rect.position.y; + dd.emission_rect[2] = rect.size.x; + dd.emission_rect[3] = rect.size.y; + } else { + dd.emission_rect[0] = 0; + dd.emission_rect[1] = 0; + dd.emission_rect[2] = 0; + dd.emission_rect[3] = 0; + } + + Color modulate = decal->modulate; + dd.modulate[0] = modulate.r; + dd.modulate[1] = modulate.g; + dd.modulate[2] = modulate.b; + dd.modulate[3] = modulate.a * fade; + dd.emission_energy = decal->emission_energy * fade; + dd.albedo_mix = decal->albedo_mix; + dd.mask = decal->cull_mask; + dd.upper_fade = decal->upper_fade; + dd.lower_fade = decal->lower_fade; + + // hook for subclass to do further processing. + RendererSceneRenderRD::get_singleton()->setup_added_decal(xform, decal_extents); + } + + if (decal_count > 0) { + RD::get_singleton()->buffer_update(decal_buffer, 0, sizeof(DecalData) * decal_count, decals, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); + } +} + /* RENDER TARGET API */ +RID TextureStorage::RenderTarget::get_framebuffer() { + // Note that if we're using an overridden color buffer, we're likely cycling through a texture chain. + // this is where our framebuffer cache comes in clutch.. + + if (msaa != RS::VIEWPORT_MSAA_DISABLED) { + return FramebufferCacheRD::get_singleton()->get_cache_multiview(view_count, color_multisample, overridden.color.is_valid() ? overridden.color : color); + } else { + return FramebufferCacheRD::get_singleton()->get_cache_multiview(view_count, overridden.color.is_valid() ? overridden.color : color); + } +} + void TextureStorage::_clear_render_target(RenderTarget *rt) { - //free in reverse dependency order - if (rt->framebuffer.is_valid()) { - RD::get_singleton()->free(rt->framebuffer); + // clear overrides, we assume these are freed by the object that created them + rt->overridden.color = RID(); + rt->overridden.depth = RID(); + rt->overridden.velocity = RID(); + rt->overridden.cached_slices.clear(); // these are automatically freed when their parent textures are freed so just clear + + // free in reverse dependency order + if (rt->framebuffer_uniform_set.is_valid()) { rt->framebuffer_uniform_set = RID(); //chain deleted } @@ -2137,7 +2401,6 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { _render_target_clear_sdf(rt); - rt->framebuffer = RID(); rt->color = RID(); rt->color_multisample = RID(); } @@ -2185,11 +2448,10 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { } } + // TODO see if we can lazy create this once we actually use it as we may not need to create this if we have an overridden color buffer... rt->color = RD::get_singleton()->texture_create(rd_color_attachment_format, rd_view); ERR_FAIL_COND(rt->color.is_null()); - Vector<RID> fb_textures; - if (rt->msaa != RS::VIEWPORT_MSAA_DISABLED) { // Use the texture format of the color attachment for the multisample color attachment. RD::TextureFormat rd_color_multisample_format = rd_color_attachment_format; @@ -2203,15 +2465,8 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { RD::TextureView rd_view_multisample; rd_color_multisample_format.is_resolve_buffer = false; rt->color_multisample = RD::get_singleton()->texture_create(rd_color_multisample_format, rd_view_multisample); - fb_textures.push_back(rt->color_multisample); ERR_FAIL_COND(rt->color_multisample.is_null()); } - fb_textures.push_back(rt->color); - rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count); - if (rt->framebuffer.is_null()) { - _clear_render_target(rt); - ERR_FAIL_COND(rt->framebuffer.is_null()); - } { //update texture @@ -2321,6 +2576,11 @@ void TextureStorage::render_target_set_position(RID p_render_target, int p_x, in //unused for this render target } +Point2i TextureStorage::render_target_get_position(RID p_render_target) const { + //unused for this render target + return Point2i(); +} + void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); @@ -2332,6 +2592,13 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in } } +Size2i TextureStorage::render_target_get_size(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, Size2i()); + + return rt->size; +} + RID TextureStorage::render_target_get_texture(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, RID()); @@ -2339,7 +2606,84 @@ RID TextureStorage::render_target_get_texture(RID p_render_target) { return rt->texture; } -void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { +void TextureStorage::render_target_set_override_color(RID p_render_target, RID p_texture) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + rt->overridden.color = p_texture; +} + +RID TextureStorage::render_target_get_override_color(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->overridden.color; +} + +void TextureStorage::render_target_set_override_depth(RID p_render_target, RID p_texture) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + rt->overridden.depth = p_texture; +} + +RID TextureStorage::render_target_get_override_depth(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->overridden.depth; +} + +RID TextureStorage::render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + if (rt->overridden.depth.is_null()) { + return RID(); + } else if (rt->view_count == 1) { + return rt->overridden.depth; + } else { + RenderTarget::RTOverridden::SliceKey key(rt->overridden.depth, p_layer); + + if (!rt->overridden.cached_slices.has(key)) { + rt->overridden.cached_slices[key] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->overridden.depth, p_layer, 0); + } + + return rt->overridden.cached_slices[key]; + } +} + +void TextureStorage::render_target_set_override_velocity(RID p_render_target, RID p_texture) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + rt->overridden.velocity = p_texture; +} + +RID TextureStorage::render_target_get_override_velocity(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->overridden.velocity; +} + +RID TextureStorage::render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + if (rt->overridden.velocity.is_null()) { + return RID(); + } else if (rt->view_count == 1) { + return rt->overridden.velocity; + } else { + RenderTarget::RTOverridden::SliceKey key(rt->overridden.velocity, p_layer); + + if (!rt->overridden.cached_slices.has(key)) { + rt->overridden.cached_slices[key] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->overridden.velocity, p_layer, 0); + } + + return rt->overridden.cached_slices[key]; + } } void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_is_transparent) { @@ -2349,10 +2693,21 @@ void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_i _update_render_target(rt); } +bool TextureStorage::render_target_get_transparent(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, false); + + return rt->is_transparent; +} + void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, bool p_value) { } -bool TextureStorage::render_target_was_used(RID p_render_target) { +bool TextureStorage::render_target_get_direct_to_screen(RID p_render_target) const { + return false; +} + +bool TextureStorage::render_target_was_used(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, false); return rt->was_used; @@ -2375,25 +2730,29 @@ void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSA _update_render_target(rt); } -Size2 TextureStorage::render_target_get_size(RID p_render_target) { +RS::ViewportMSAA TextureStorage::render_target_get_msaa(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, Size2()); + ERR_FAIL_COND_V(!rt, RS::VIEWPORT_MSAA_DISABLED); - return rt->size; + return rt->msaa; } RID TextureStorage::render_target_get_rd_framebuffer(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, RID()); - return rt->framebuffer; + return rt->get_framebuffer(); } RID TextureStorage::render_target_get_rd_texture(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, RID()); - return rt->color; + if (rt->overridden.color.is_valid()) { + return rt->overridden.color; + } else { + return rt->color; + } } RID TextureStorage::render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer) { @@ -2464,7 +2823,7 @@ void TextureStorage::render_target_do_clear_request(RID p_render_target) { } Vector<Color> clear_colors; clear_colors.push_back(rt->clear_color); - RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors); RD::get_singleton()->draw_list_end(); rt->clear_requested = false; } @@ -2893,18 +3252,18 @@ void TextureStorage::render_target_set_vrs_mode(RID p_render_target, RS::Viewpor rt->vrs_mode = p_mode; } -void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID 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(!rt); + ERR_FAIL_COND_V(!rt, RS::VIEWPORT_VRS_DISABLED); - rt->vrs_texture = p_texture; + return rt->vrs_mode; } -RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_target) const { +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_V(!rt, RS::VIEWPORT_VRS_DISABLED); + ERR_FAIL_COND(!rt); - return rt->vrs_mode; + rt->vrs_texture = p_texture; } RID TextureStorage::render_target_get_vrs_texture(RID p_render_target) const { diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index a3acad30f3..00b4e50737 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -31,8 +31,12 @@ #ifndef TEXTURE_STORAGE_RD_H #define TEXTURE_STORAGE_RD_H +#include "core/templates/local_vector.h" +#include "core/templates/paged_array.h" #include "core/templates/rid_owner.h" #include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/forward_id_storage.h" +#include "servers/rendering/rendering_server_default.h" #include "servers/rendering/storage/texture_storage.h" #include "servers/rendering/storage/utilities.h" @@ -245,14 +249,58 @@ private: }; mutable RID_Owner<Decal, true> decal_owner; - Decal *get_decal(RID p_rid) const { return decal_owner.get_or_null(p_rid); }; + + /* DECAL INSTANCE */ + + struct DecalInstance { + RID decal; + Transform3D transform; + uint32_t cull_mask = 0; + RendererRD::ForwardID forward_id = -1; + }; + + mutable RID_Owner<DecalInstance> decal_instance_owner; + + /* DECAL DATA (UBO) */ + + struct DecalData { + float xform[16]; + float inv_extents[3]; + float albedo_mix; + float albedo_rect[4]; + float normal_rect[4]; + float orm_rect[4]; + float emission_rect[4]; + float modulate[4]; + float emission_energy; + uint32_t mask; + float upper_fade; + float lower_fade; + float normal_xform[12]; + float normal[3]; + float normal_fade; + }; + + struct DecalInstanceSort { + float depth; + DecalInstance *decal_instance; + Decal *decal; + bool operator<(const DecalInstanceSort &p_sort) const { + return depth < p_sort.depth; + } + }; + + uint32_t max_decals = 0; + uint32_t decal_count = 0; + DecalData *decals = nullptr; + DecalInstanceSort *decal_sort = nullptr; + RID decal_buffer; /* RENDER TARGET API */ struct RenderTarget { Size2i size; uint32_t view_count; - RID framebuffer; RID color; Vector<RID> color_slices; RID color_multisample; // Needed when MSAA is enabled. @@ -290,6 +338,43 @@ private: RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED; RID vrs_texture; + // overridden textures + struct RTOverridden { + RID color; + RID depth; + RID velocity; + + // In a multiview scenario, which is the most likely where we + // override our destination textures, we need to obtain slices + // for each layer of these textures. + // These are likely changing every frame as we loop through + // texture chains hence we add a cache to manage these slices. + // For this we define a key using the RID of the texture and + // the layer for which we create a slice. + struct SliceKey { + RID rid; + uint32_t layer = 0; + + bool operator==(const SliceKey &p_val) const { + return (rid == p_val.rid) && (layer == p_val.layer); + } + + static uint32_t hash(const SliceKey &p_val) { + uint32_t h = hash_one_uint64(p_val.rid.get_id()); + h = hash_murmur3_one_32(p_val.layer, h); + return hash_fmix32(h); + } + + SliceKey() {} + SliceKey(RID p_rid, uint32_t p_layer) { + rid = p_rid; + layer = p_layer; + } + }; + + mutable HashMap<SliceKey, RID, SliceKey> cached_slices; + } overridden; + //texture generated for this owner (nor RD). RID texture; bool was_used; @@ -297,6 +382,8 @@ private: //clear request bool clear_requested; Color clear_color; + + RID get_framebuffer(); }; mutable RID_Owner<RenderTarget> render_target_owner; @@ -343,6 +430,8 @@ public: TextureStorage(); virtual ~TextureStorage(); + bool free(RID p_rid); + /* Canvas Texture API */ bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; @@ -545,6 +634,46 @@ public: virtual AABB decal_get_aabb(RID p_decal) const override; Dependency *decal_get_dependency(RID p_decal); + /* DECAL INSTANCE API */ + + bool owns_decal_instance(RID p_rid) const { return decal_instance_owner.owns(p_rid); } + + virtual RID decal_instance_create(RID p_decal) override; + virtual void decal_instance_free(RID p_decal_instance) override; + virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) override; + + _FORCE_INLINE_ RID decal_instance_get_base(RID p_decal_instance) const { + DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance); + return di->decal; + } + + _FORCE_INLINE_ RendererRD::ForwardID decal_instance_get_forward_id(RID p_decal_instance) const { + DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance); + return di->forward_id; + } + + _FORCE_INLINE_ Transform3D decal_instance_get_transform(RID p_decal_instance) const { + DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance); + return di->transform; + } + + _FORCE_INLINE_ ForwardID decal_instance_get_forward_id(RID p_decal_instance) { + DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance); + return di->forward_id; + } + + _FORCE_INLINE_ void decal_instance_set_cullmask(RID p_decal_instance, uint32_t p_cull_mask) const { + DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance); + di->cull_mask = p_cull_mask; + } + + /* DECAL DATA API */ + + void free_decal_data(); + void set_max_decals(const uint32_t p_max_decals); + RID get_decal_buffer() { return decal_buffer; } + void update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform); + /* RENDER TARGET API */ bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); }; @@ -553,14 +682,17 @@ public: virtual void render_target_free(RID p_rid) override; virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override; + virtual Point2i render_target_get_position(RID p_render_target) const override; virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override; - virtual RID render_target_get_texture(RID p_render_target) override; - virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override; + virtual Size2i render_target_get_size(RID p_render_target) const override; virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override; + virtual bool render_target_get_transparent(RID p_render_target) const override; virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override; - virtual bool render_target_was_used(RID p_render_target) override; + virtual bool render_target_get_direct_to_screen(RID p_render_target) const override; + virtual bool render_target_was_used(RID p_render_target) const override; virtual void render_target_set_as_unused(RID p_render_target) override; virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override; + virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override; void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps); void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color); @@ -582,12 +714,21 @@ public: 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 RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override; virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override; + virtual RID render_target_get_vrs_texture(RID p_render_target) const override; - RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const; - RID render_target_get_vrs_texture(RID p_render_target) const; + virtual void render_target_set_override_color(RID p_render_target, RID p_texture) override; + virtual RID render_target_get_override_color(RID p_render_target) const override; + virtual void render_target_set_override_depth(RID p_render_target, RID p_texture) override; + virtual RID render_target_get_override_depth(RID p_render_target) const override; + RID render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const; + virtual void render_target_set_override_velocity(RID p_render_target, RID p_texture) override; + virtual RID render_target_get_override_velocity(RID p_render_target) const override; + RID render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const; + + virtual RID render_target_get_texture(RID p_render_target) override; - 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); RID render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer); diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp index b80bcd514f..e517186955 100644 --- a/servers/rendering/renderer_rd/storage_rd/utilities.cpp +++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp @@ -89,49 +89,28 @@ RS::InstanceType Utilities::get_base_type(RID p_rid) const { } bool Utilities::free(RID p_rid) { - if (RendererRD::TextureStorage::get_singleton()->owns_texture(p_rid)) { - RendererRD::TextureStorage::get_singleton()->texture_free(p_rid); - } else if (RendererRD::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) { - RendererRD::TextureStorage::get_singleton()->canvas_texture_free(p_rid); - } else if (RendererRD::MaterialStorage::get_singleton()->owns_shader(p_rid)) { - RendererRD::MaterialStorage::get_singleton()->shader_free(p_rid); - } else if (RendererRD::MaterialStorage::get_singleton()->owns_material(p_rid)) { - RendererRD::MaterialStorage::get_singleton()->material_free(p_rid); - } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) { - RendererRD::MeshStorage::get_singleton()->mesh_free(p_rid); - } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) { - RendererRD::MeshStorage::get_singleton()->mesh_instance_free(p_rid); - } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { - RendererRD::MeshStorage::get_singleton()->multimesh_free(p_rid); - } else if (RendererRD::MeshStorage::get_singleton()->owns_skeleton(p_rid)) { - RendererRD::MeshStorage::get_singleton()->skeleton_free(p_rid); - } else if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) { - RendererRD::LightStorage::get_singleton()->reflection_probe_free(p_rid); - } else if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) { - RendererRD::TextureStorage::get_singleton()->decal_free(p_rid); + if (RendererRD::LightStorage::get_singleton()->free(p_rid)) { + return true; + } else if (RendererRD::MaterialStorage::get_singleton()->free(p_rid)) { + return true; + } else if (RendererRD::MeshStorage::get_singleton()->free(p_rid)) { + return true; + } else if (RendererRD::ParticlesStorage::get_singleton()->free(p_rid)) { + return true; + } else if (RendererRD::TextureStorage::get_singleton()->free(p_rid)) { + return true; } else if (RendererRD::GI::get_singleton()->owns_voxel_gi(p_rid)) { RendererRD::GI::get_singleton()->voxel_gi_free(p_rid); - } else if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) { - RendererRD::LightStorage::get_singleton()->lightmap_free(p_rid); - } else if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) { - RendererRD::LightStorage::get_singleton()->light_free(p_rid); - } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) { - RendererRD::ParticlesStorage::get_singleton()->particles_free(p_rid); - } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) { - RendererRD::ParticlesStorage::get_singleton()->particles_collision_free(p_rid); + return true; + } else if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) { + RendererRD::Fog::get_singleton()->fog_volume_free(p_rid); + return true; } else if (owns_visibility_notifier(p_rid)) { visibility_notifier_free(p_rid); - } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision_instance(p_rid)) { - RendererRD::ParticlesStorage::get_singleton()->particles_collision_instance_free(p_rid); - } else if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) { - RendererRD::Fog::get_singleton()->fog_free(p_rid); - } else if (RendererRD::TextureStorage::get_singleton()->owns_render_target(p_rid)) { - RendererRD::TextureStorage::get_singleton()->render_target_free(p_rid); + return true; } else { return false; } - - return true; } /* DEPENDENCIES */ @@ -170,8 +149,8 @@ void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance Dependency *dependency = ParticlesStorage::get_singleton()->particles_collision_get_dependency(p_base); p_instance->update_dependency(dependency); } else if (Fog::get_singleton()->owns_fog_volume(p_base)) { - Fog::FogVolume *fv = Fog::get_singleton()->get_fog_volume(p_base); - p_instance->update_dependency(&fv->dependency); + Dependency *dependency = Fog::get_singleton()->fog_volume_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (owns_visibility_notifier(p_base)) { VisibilityNotifier *vn = get_visibility_notifier(p_base); p_instance->update_dependency(&vn->dependency); diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index c2dece8b46..66a64d4372 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -357,13 +357,14 @@ void RendererSceneCull::scenario_initialize(RID p_rid) { Scenario *scenario = scenario_owner.get_or_null(p_rid); scenario->self = p_rid; - scenario->reflection_probe_shadow_atlas = scene_render->shadow_atlas_create(); - scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest - scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4); - scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4); - scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4); - scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8); - scenario->reflection_atlas = scene_render->reflection_atlas_create(); + scenario->reflection_probe_shadow_atlas = RSG::light_storage->shadow_atlas_create(); + RSG::light_storage->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest + RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4); + RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4); + RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4); + RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8); + + scenario->reflection_atlas = RSG::light_storage->reflection_atlas_create(); scenario->instance_aabbs.set_page_pool(&instance_aabb_page_pool); scenario->instance_data.set_page_pool(&instance_data_page_pool); @@ -393,7 +394,7 @@ void RendererSceneCull::scenario_set_fallback_environment(RID p_scenario, RID p_ void RendererSceneCull::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) { Scenario *scenario = scenario_owner.get_or_null(p_scenario); ERR_FAIL_COND(!scenario); - scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count); + RSG::light_storage->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count); } bool RendererSceneCull::is_scenario(RID p_scenario) const { @@ -534,7 +535,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { scenario->directional_lights.erase(light->D); light->D = nullptr; } - scene_render->free(light->instance); + RSG::light_storage->light_instance_free(light->instance); } break; case RS::INSTANCE_PARTICLES_COLLISION: { InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data); @@ -549,14 +550,14 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { } break; case RS::INSTANCE_REFLECTION_PROBE: { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data); - scene_render->free(reflection_probe->instance); + RSG::light_storage->reflection_probe_instance_free(reflection_probe->instance); if (reflection_probe->update_list.in_list()) { reflection_probe_render_list.remove(&reflection_probe->update_list); } } break; case RS::INSTANCE_DECAL: { InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data); - scene_render->free(decal->instance); + RSG::texture_storage->decal_instance_free(decal->instance); } break; case RS::INSTANCE_LIGHTMAP: { @@ -565,7 +566,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { while (lightmap_data->users.begin()) { instance_geometry_set_lightmap((*lightmap_data->users.begin())->self, RID(), Rect2(), 0); } - scene_render->free(lightmap_data->instance); + RSG::light_storage->lightmap_instance_free(lightmap_data->instance); } break; case RS::INSTANCE_VOXEL_GI: { InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(instance->base_data); @@ -626,7 +627,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { light->D = scenario->directional_lights.push_back(instance); } - light->instance = scene_render->light_instance_create(p_base); + light->instance = RSG::light_storage->light_instance_create(p_base); instance->base_data = light; } break; @@ -684,19 +685,19 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { reflection_probe->owner = instance; instance->base_data = reflection_probe; - reflection_probe->instance = scene_render->reflection_probe_instance_create(p_base); + reflection_probe->instance = RSG::light_storage->reflection_probe_instance_create(p_base); } break; case RS::INSTANCE_DECAL: { InstanceDecalData *decal = memnew(InstanceDecalData); decal->owner = instance; instance->base_data = decal; - decal->instance = scene_render->decal_instance_create(p_base); + decal->instance = RSG::texture_storage->decal_instance_create(p_base); } break; case RS::INSTANCE_LIGHTMAP: { InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData); instance->base_data = lightmap_data; - lightmap_data->instance = scene_render->lightmap_instance_create(p_base); + lightmap_data->instance = RSG::light_storage->lightmap_instance_create(p_base); } break; case RS::INSTANCE_VOXEL_GI: { InstanceVoxelGIData *voxel_gi = memnew(InstanceVoxelGIData); @@ -758,7 +759,7 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) { } break; case RS::INSTANCE_REFLECTION_PROBE: { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data); - scene_render->reflection_probe_release_atlas_index(reflection_probe->instance); + RSG::light_storage->reflection_probe_release_atlas_index(reflection_probe->instance); } break; case RS::INSTANCE_PARTICLES_COLLISION: { @@ -1502,8 +1503,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { if (p_instance->base_type == RS::INSTANCE_LIGHT) { InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); - scene_render->light_instance_set_transform(light->instance, p_instance->transform); - scene_render->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb)); + RSG::light_storage->light_instance_set_transform(light->instance, p_instance->transform); + RSG::light_storage->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb)); light->shadow_dirty = true; RS::LightBakeMode bake_mode = RSG::light_storage->light_get_bake_mode(p_instance->base); @@ -1526,7 +1527,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { } else if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data); - scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform); + RSG::light_storage->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform); if (p_instance->scenario && p_instance->array_index >= 0) { InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index]; @@ -1535,11 +1536,11 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { } else if (p_instance->base_type == RS::INSTANCE_DECAL) { InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data); - scene_render->decal_instance_set_transform(decal->instance, p_instance->transform); + RSG::texture_storage->decal_instance_set_transform(decal->instance, p_instance->transform); } else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) { InstanceLightmapData *lightmap = static_cast<InstanceLightmapData *>(p_instance->base_data); - scene_render->lightmap_instance_set_transform(lightmap->instance, p_instance->transform); + RSG::light_storage->lightmap_instance_set_transform(lightmap->instance, p_instance->transform); } else if (p_instance->base_type == RS::INSTANCE_VOXEL_GI) { InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(p_instance->base_data); @@ -2050,7 +2051,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in distances[splits] = max_distance; - real_t texture_size = scene_render->get_directional_light_shadow_size(light->instance); + real_t texture_size = RSG::light_storage->get_directional_light_shadow_size(light->instance); bool overlap = RSG::light_storage->light_directional_get_blend_splits(p_instance->base); @@ -2241,7 +2242,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons case RS::LIGHT_OMNI: { RS::LightOmniShadowMode shadow_mode = RSG::light_storage->light_omni_get_shadow_mode(p_instance->base); - if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !scene_render->light_instances_can_render_shadow_cube()) { + if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !RSG::light_storage->light_instances_can_render_shadow_cube()) { if (max_shadows_used + 2 > MAX_UPDATE_SHADOWS) { return true; } @@ -2300,7 +2301,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons RSG::mesh_storage->update_mesh_instances(); - scene_render->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, i, 0); + RSG::light_storage->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, i, 0); shadow_data.light = light->instance; shadow_data.pass = i; } @@ -2376,14 +2377,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons } RSG::mesh_storage->update_mesh_instances(); - scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0); + RSG::light_storage->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0); shadow_data.light = light->instance; shadow_data.pass = i; } //restore the regular DP matrix - //scene_render->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, 0, 0); + //RSG::light_storage->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, 0, 0); } } break; @@ -2440,7 +2441,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons RSG::mesh_storage->update_mesh_instances(); - scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0); + RSG::light_storage->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0); shadow_data.light = light->instance; shadow_data.pass = 0; @@ -2680,14 +2681,14 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul cull_result.lights.push_back(idata.instance); cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid)); if (cull_data.shadow_atlas.is_valid() && RSG::light_storage->light_has_shadow(idata.base_rid)) { - scene_render->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later + RSG::light_storage->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later } } else if (base_type == RS::INSTANCE_REFLECTION_PROBE) { if (cull_data.render_reflection_probe != idata.instance) { //avoid entering The Matrix - if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || scene_render->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) { + if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || RSG::light_storage->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data); cull_data.cull->lock.lock(); if (!reflection_probe->update_list.in_list()) { @@ -2699,7 +2700,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul idata.flags &= ~uint32_t(InstanceData::FLAG_REFLECTION_PROBE_DIRTY); } - if (scene_render->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) { + if (RSG::light_storage->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) { cull_result.reflections.push_back(RID::from_uint64(idata.instance_data_rid)); } } @@ -2991,7 +2992,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c } } - scene_render->set_directional_shadow_count(lights_with_shadow.size()); + RSG::light_storage->set_directional_shadow_count(lights_with_shadow.size()); for (int i = 0; i < lights_with_shadow.size(); i++) { _light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect); @@ -3091,7 +3092,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c for (uint32_t j = 0; j < cull.shadows[i].cascade_count; j++) { const Cull::Shadow::Cascade &c = cull.shadows[i].cascades[j]; // print_line("shadow " + itos(i) + " cascade " + itos(j) + " elements: " + itos(c.cull_result.size())); - scene_render->light_instance_set_shadow_transform(cull.shadows[i].light_instance, c.projection, c.transform, c.zfar, c.split, j, c.shadow_texel_size, c.bias_scale, c.range_begin, c.uv_scale); + RSG::light_storage->light_instance_set_shadow_transform(cull.shadows[i].light_instance, c.projection, c.transform, c.zfar, c.split, j, c.shadow_texel_size, c.bias_scale, c.range_begin, c.uv_scale); if (max_shadows_used == MAX_UPDATE_SHADOWS) { continue; } @@ -3187,7 +3188,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c light->shadow_dirty = false; } - bool redraw = scene_render->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version); + bool redraw = RSG::light_storage->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version); if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) { //must redraw! @@ -3320,7 +3321,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int RenderingServerDefault::redraw_request(); //update, so it updates in editor if (p_step == 0) { - if (!scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) { + if (!RSG::light_storage->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) { return true; //all full } } @@ -3346,7 +3347,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int Vector3 extents = RSG::light_storage->reflection_probe_get_extents(p_instance->base); Vector3 origin_offset = RSG::light_storage->reflection_probe_get_origin_offset(p_instance->base); float max_distance = RSG::light_storage->reflection_probe_get_origin_max_distance(p_instance->base); - float size = scene_render->reflection_atlas_get_size(scenario->reflection_atlas); + float size = RSG::light_storage->reflection_atlas_get_size(scenario->reflection_atlas); float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / size; Vector3 edge = view_normals[p_step] * extents; @@ -3387,7 +3388,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int } else { //do roughness postprocess step until it believes it's done RENDER_TIMESTAMP("Post-Process ReflectionProbe, Step " + itos(p_step)); - return scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance); + return RSG::light_storage->reflection_probe_instance_postprocess_step(reflection_probe->instance); } return false; @@ -3967,8 +3968,8 @@ bool RendererSceneCull::free(RID p_rid) { scenario->instance_data.reset(); scenario->instance_visibility.reset(); - scene_render->free(scenario->reflection_probe_shadow_atlas); - scene_render->free(scenario->reflection_atlas); + RSG::light_storage->shadow_atlas_free(scenario->reflection_probe_shadow_atlas); + RSG::light_storage->reflection_atlas_free(scenario->reflection_atlas); scenario_owner.free(p_rid); RendererSceneOcclusionCull::get_singleton()->remove_scenario(p_rid); diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index fedaac99b1..d085b84a8c 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -1076,7 +1076,6 @@ public: #define PASSBASE scene_render - PASS2(directional_shadow_atlas_set_size, int, bool) PASS1(voxel_gi_set_quality, RS::VoxelGIQuality) /* SKY API */ @@ -1258,11 +1257,7 @@ public: PASS0R(Ref<RenderSceneBuffers>, render_buffers_create) PASS1(gi_set_use_half_resolution, bool) - /* Shadow Atlas */ - PASS0R(RID, shadow_atlas_create) - PASS3(shadow_atlas_set_size, RID, int, bool) - PASS3(shadow_atlas_set_quadrant_subdivision, RID, int, int) - + /* Misc */ PASS1(set_debug_draw_mode, RS::ViewportDebugDraw) PASS1(decals_set_filter, RS::DecalFilter) diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 34f4980f05..a8df897077 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -56,17 +56,6 @@ public: virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) = 0; virtual uint32_t geometry_instance_get_pair_mask() = 0; - /* SHADOW ATLAS API */ - - virtual RID shadow_atlas_create() = 0; - virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) = 0; - virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0; - virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0; - - virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0; - virtual int get_directional_light_shadow_size(RID p_light_intance) = 0; - virtual void set_directional_shadow_count(int p_count) = 0; - /* SDFGI UPDATE */ virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0; @@ -240,39 +229,12 @@ public: virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0; virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0; - virtual RID light_instance_create(RID p_light) = 0; - virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) = 0; - virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0; - 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()) = 0; - virtual void light_instance_mark_visible(RID p_light_instance) = 0; - virtual bool light_instances_can_render_shadow_cube() const { - return true; - } - virtual RID fog_volume_instance_create(RID p_fog_volume) = 0; virtual void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) = 0; virtual void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) = 0; virtual RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const = 0; virtual Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const = 0; - virtual RID reflection_atlas_create() = 0; - virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0; - virtual int reflection_atlas_get_size(RID p_ref_atlas) const = 0; - - virtual RID reflection_probe_instance_create(RID p_probe) = 0; - virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0; - virtual void reflection_probe_release_atlas_index(RID p_instance) = 0; - virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0; - virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0; - virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0; - virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0; - - virtual RID decal_instance_create(RID p_decal) = 0; - virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) = 0; - - virtual RID lightmap_instance_create(RID p_lightmap) = 0; - virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) = 0; - virtual RID voxel_gi_instance_create(RID p_voxel_gi) = 0; virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) = 0; virtual bool voxel_gi_needs_update(RID p_probe) const = 0; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 2b05e23a96..4f7683493b 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -664,9 +664,9 @@ void RendererViewport::draw_viewports() { RSG::texture_storage->render_target_set_as_unused(vp->render_target); if (vp->use_xr && xr_interface.is_valid()) { - // check for an external texture destination (disabled for now, not yet supported) - // RSG::texture_storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono)); - RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0); + RSG::texture_storage->render_target_set_override_color(vp->render_target, xr_interface->get_color_texture()); + RSG::texture_storage->render_target_set_override_depth(vp->render_target, xr_interface->get_depth_texture()); + RSG::texture_storage->render_target_set_override_velocity(vp->render_target, xr_interface->get_velocity_texture()); // render... RSG::scene->set_debug_draw_mode(vp->debug_draw); @@ -678,11 +678,13 @@ void RendererViewport::draw_viewports() { // commit our eyes Vector<BlitToScreen> blits = xr_interface->post_draw_viewport(vp->render_target, vp->viewport_to_screen_rect); - if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && blits.size() > 0) { + if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID) { if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3") { - RSG::rasterizer->blit_render_targets_to_screen(vp->viewport_to_screen, blits.ptr(), blits.size()); + if (blits.size() > 0) { + RSG::rasterizer->blit_render_targets_to_screen(vp->viewport_to_screen, blits.ptr(), blits.size()); + } RSG::rasterizer->end_frame(true); - } else { + } else if (blits.size() > 0) { if (!blit_to_screen_list.has(vp->viewport_to_screen)) { blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>(); } @@ -693,7 +695,9 @@ void RendererViewport::draw_viewports() { } } } else { - RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0); + RSG::texture_storage->render_target_set_override_color(vp->render_target, RID()); // TODO if fullscreen output, we can set this to our texture chain + RSG::texture_storage->render_target_set_override_depth(vp->render_target, RID()); + RSG::texture_storage->render_target_set_override_velocity(vp->render_target, RID()); RSG::scene->set_debug_draw_mode(vp->debug_draw); @@ -760,7 +764,7 @@ void RendererViewport::viewport_initialize(RID p_rid) { Viewport *viewport = viewport_owner.get_or_null(p_rid); viewport->self = p_rid; viewport->render_target = RSG::texture_storage->render_target_create(); - viewport->shadow_atlas = RSG::scene->shadow_atlas_create(); + viewport->shadow_atlas = RSG::light_storage->shadow_atlas_create(); viewport->viewport_render_direct_to_screen = false; viewport->fsr_enabled = !RSG::rasterizer->is_low_end() && !viewport->disable_3d; @@ -1076,14 +1080,14 @@ void RendererViewport::viewport_set_positional_shadow_atlas_size(RID p_viewport, viewport->shadow_atlas_size = p_size; viewport->shadow_atlas_16_bits = p_16_bits; - RSG::scene->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size, viewport->shadow_atlas_16_bits); + RSG::light_storage->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size, viewport->shadow_atlas_16_bits); } void RendererViewport::viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); - RSG::scene->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv); + RSG::light_storage->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv); } void RendererViewport::viewport_set_msaa_2d(RID p_viewport, RS::ViewportMSAA p_msaa) { @@ -1294,7 +1298,7 @@ bool RendererViewport::free(RID p_rid) { Viewport *viewport = viewport_owner.get_or_null(p_rid); RSG::texture_storage->render_target_free(viewport->render_target); - RSG::scene->free(viewport->shadow_atlas); + RSG::light_storage->shadow_atlas_free(viewport->shadow_atlas); if (viewport->render_buffers.is_valid()) { viewport->render_buffers.unref(); } diff --git a/servers/rendering/rendering_method.h b/servers/rendering/rendering_method.h index a178b00424..c4d9e25ecd 100644 --- a/servers/rendering/rendering_method.h +++ b/servers/rendering/rendering_method.h @@ -106,8 +106,6 @@ public: virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const = 0; virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const = 0; - virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0; - /* SKY API */ virtual RID sky_allocate() = 0; @@ -284,10 +282,6 @@ public: virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0; virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0; - virtual RID shadow_atlas_create() = 0; - virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_use_16_bits = true) = 0; - virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0; - /* Render Buffers */ virtual Ref<RenderSceneBuffers> render_buffers_create() = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 5ee29d5e2a..fe212151e3 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -410,6 +410,13 @@ public: FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID) FUNC1(lightmap_set_probe_capture_update_speed, float) + /* Shadow Atlas */ + FUNC0R(RID, shadow_atlas_create) + FUNC3(shadow_atlas_set_size, RID, int, bool) + FUNC3(shadow_atlas_set_quadrant_subdivision, RID, int, int) + + FUNC2(directional_shadow_atlas_set_size, int, bool) + /* DECAL API */ #undef ServerName @@ -652,7 +659,6 @@ public: #define ServerName RenderingMethod #define server_name RSG::scene - FUNC2(directional_shadow_atlas_set_size, int, bool) FUNC1(voxel_gi_set_quality, VoxelGIQuality) /* SKY API */ diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index ab5b8af794..1d83cc9de7 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -32,8 +32,8 @@ #include "core/config/project_settings.h" #include "core/os/os.h" +#include "servers/rendering/rendering_server_globals.h" #include "servers/rendering/shader_types.h" -#include "servers/rendering_server.h" #define SL ShaderLanguage @@ -1348,8 +1348,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene return code; } -ShaderLanguage::DataType ShaderCompiler::_get_variable_type(const StringName &p_type) { - RS::GlobalShaderParameterType gvt = RS::get_singleton()->global_shader_parameter_get_type(p_type); +ShaderLanguage::DataType ShaderCompiler::_get_global_shader_uniform_type(const StringName &p_name) { + RS::GlobalShaderParameterType gvt = RSG::material_storage->global_shader_parameter_get_type(p_name); return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt); } @@ -1358,7 +1358,7 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident info.functions = ShaderTypes::get_singleton()->get_functions(p_mode); info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode); info.shader_types = ShaderTypes::get_singleton()->get_types(); - info.global_shader_uniform_type_func = _get_variable_type; + info.global_shader_uniform_type_func = _get_global_shader_uniform_type; Error err = parser.compile(p_code, info); diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h index 1ad43daf5f..4cbe93afb2 100644 --- a/servers/rendering/shader_compiler.h +++ b/servers/rendering/shader_compiler.h @@ -122,7 +122,7 @@ private: DefaultIdentifierActions actions; - static ShaderLanguage::DataType _get_variable_type(const StringName &p_type); + static ShaderLanguage::DataType _get_global_shader_uniform_type(const StringName &p_name); public: Error compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code); diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index cd063f91ac..5e1da7c15d 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -86,8 +86,8 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["vertex"].main_function = true; //builtins - shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; @@ -297,6 +297,9 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SPECULAR_SHININESS"] = constt(ShaderLanguage::TYPE_VEC4); shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_IS_DIRECTIONAL"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VERTEX"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_MODULATE"] = ShaderLanguage::TYPE_VEC4; diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h index b04bc671ee..df5b893cd5 100644 --- a/servers/rendering/storage/light_storage.h +++ b/servers/rendering/storage/light_storage.h @@ -84,6 +84,18 @@ public: virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0; virtual uint64_t light_get_version(RID p_light) const = 0; + /* LIGHT INSTANCE API */ + + virtual RID light_instance_create(RID p_light) = 0; + virtual void light_instance_free(RID p_light_instance) = 0; + virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) = 0; + virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0; + 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()) = 0; + virtual void light_instance_mark_visible(RID p_light_instance) = 0; + virtual bool light_instances_can_render_shadow_cube() const { + return true; + } + /* PROBE API */ virtual RID reflection_probe_allocate() = 0; @@ -114,6 +126,24 @@ public: virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0; virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const = 0; + /* REFLECTION ATLAS */ + + virtual RID reflection_atlas_create() = 0; + virtual void reflection_atlas_free(RID p_ref_atlas) = 0; + virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0; + virtual int reflection_atlas_get_size(RID p_ref_atlas) const = 0; + + /* REFLECTION PROBE INSTANCE */ + + virtual RID reflection_probe_instance_create(RID p_probe) = 0; + virtual void reflection_probe_instance_free(RID p_instance) = 0; + virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0; + virtual void reflection_probe_release_atlas_index(RID p_instance) = 0; + virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0; + virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0; + virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0; + virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0; + /* LIGHTMAP */ virtual RID lightmap_allocate() = 0; @@ -134,6 +164,27 @@ public: virtual bool lightmap_is_interior(RID p_lightmap) const = 0; virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0; virtual float lightmap_get_probe_capture_update_speed() const = 0; + + /* LIGHTMAP INSTANCE */ + + virtual RID lightmap_instance_create(RID p_lightmap) = 0; + virtual void lightmap_instance_free(RID p_lightmap) = 0; + virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) = 0; + + /* SHADOW ATLAS */ + + virtual RID shadow_atlas_create() = 0; + virtual void shadow_atlas_free(RID p_atlas) = 0; + + virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_use_16_bits = true) = 0; + virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0; + virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0; + + virtual void shadow_atlas_update(RID p_atlas) = 0; + + virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0; + virtual int get_directional_light_shadow_size(RID p_light_intance) = 0; + virtual void set_directional_shadow_count(int p_count) = 0; }; #endif // LIGHT_STORAGE_H diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h index 08ff88d4a5..635f44786c 100644 --- a/servers/rendering/storage/texture_storage.h +++ b/servers/rendering/storage/texture_storage.h @@ -120,20 +120,29 @@ public: virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; + /* DECAL INSTANCE */ + + virtual RID decal_instance_create(RID p_decal) = 0; + virtual void decal_instance_free(RID p_decal_instance) = 0; + virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) = 0; + /* RENDER TARGET */ virtual RID render_target_create() = 0; virtual void render_target_free(RID p_rid) = 0; - virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0; - virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0; - virtual RID render_target_get_texture(RID p_render_target) = 0; - virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0; + virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0; // Q change input to const Point2i &p_position ? + virtual Point2i render_target_get_position(RID p_render_target) const = 0; + virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0; // Q change input to const Size2i &p_size ? + virtual Size2i render_target_get_size(RID p_render_target) const = 0; virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) = 0; + virtual bool render_target_get_transparent(RID p_render_target) const = 0; virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) = 0; - virtual bool render_target_was_used(RID p_render_target) = 0; + virtual bool render_target_get_direct_to_screen(RID p_render_target) const = 0; + virtual bool render_target_was_used(RID p_render_target) const = 0; virtual void render_target_set_as_unused(RID p_render_target) = 0; virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) = 0; + virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const = 0; virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0; virtual bool render_target_is_clear_requested(RID p_render_target) = 0; @@ -146,7 +155,20 @@ public: virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0; virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) = 0; + virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const = 0; virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) = 0; + virtual RID render_target_get_vrs_texture(RID p_render_target) const = 0; + + // override color, depth and velocity buffers (depth and velocity only for 3D) + virtual void render_target_set_override_color(RID p_render_target, RID p_texture) = 0; + virtual RID render_target_get_override_color(RID p_render_target) const = 0; + virtual void render_target_set_override_depth(RID p_render_target, RID p_texture) = 0; + virtual RID render_target_get_override_depth(RID p_render_target) const = 0; + virtual void render_target_set_override_velocity(RID p_render_target, RID p_texture) = 0; + virtual RID render_target_get_override_velocity(RID p_render_target) const = 0; + + // get textures + virtual RID render_target_get_texture(RID p_render_target) = 0; }; #endif // TEXTURE_STORAGE_H |