summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2022-10-04 11:20:13 +0200
committerRémi Verschelde <rverschelde@gmail.com>2022-10-04 11:20:13 +0200
commitbff9fcfc1c90f5e121a9f9ae0af93616b5c7304d (patch)
tree882e372031dec1cc935e7fc00cefae1c76b48de8
parentb909b0ebc9cbaf804e5c7c3f7e7de34189847a80 (diff)
parent02b0c22e38eb7ab9c3127b9b5d7c29cf58c1732d (diff)
Merge pull request #65822 from BastiaanOlij/more_reorg_20220915
Move cluster builder, sdfgi and gi structures to clustered renderer, and more
-rw-r--r--drivers/gles3/environment/fog.cpp2
-rw-r--r--drivers/gles3/environment/fog.h2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp136
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h77
-rw-r--r--drivers/gles3/storage/light_storage.cpp131
-rw-r--r--drivers/gles3/storage/light_storage.h90
-rw-r--r--drivers/gles3/storage/texture_storage.cpp12
-rw-r--r--drivers/gles3/storage/texture_storage.h6
-rw-r--r--servers/rendering/dummy/environment/fog.h2
-rw-r--r--servers/rendering/dummy/rasterizer_scene_dummy.h35
-rw-r--r--servers/rendering/dummy/storage/light_storage.h47
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h6
-rw-r--r--servers/rendering/environment/renderer_fog.h2
-rw-r--r--servers/rendering/renderer_rd/effects/fsr.cpp3
-rw-r--r--servers/rendering/renderer_rd/effects/fsr.h7
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp195
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.h51
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp9
-rw-r--r--servers/rendering/renderer_rd/environment/fog.h39
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp135
-rw-r--r--servers/rendering/renderer_rd/environment/gi.h12
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp7
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp837
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h89
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp460
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h111
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp2556
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h767
-rw-r--r--servers/rendering/renderer_rd/storage_rd/forward_id_storage.cpp43
-rw-r--r--servers/rendering/renderer_rd/storage_rd/forward_id_storage.h68
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp1626
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h708
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp12
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp18
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp15
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp33
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h34
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp247
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h93
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.cpp55
-rw-r--r--servers/rendering/renderer_scene_cull.cpp79
-rw-r--r--servers/rendering/renderer_scene_cull.h7
-rw-r--r--servers/rendering/renderer_scene_render.h38
-rw-r--r--servers/rendering/renderer_viewport.cpp8
-rw-r--r--servers/rendering/rendering_method.h6
-rw-r--r--servers/rendering/rendering_server_default.h8
-rw-r--r--servers/rendering/storage/light_storage.h51
-rw-r--r--servers/rendering/storage/texture_storage.h6
-rw-r--r--servers/rendering_server.h6
52 files changed, 4993 insertions, 4000 deletions
diff --git a/drivers/gles3/environment/fog.cpp b/drivers/gles3/environment/fog.cpp
index 02d88f6871..8587c5f9f7 100644
--- a/drivers/gles3/environment/fog.cpp
+++ b/drivers/gles3/environment/fog.cpp
@@ -43,7 +43,7 @@ RID Fog::fog_volume_allocate() {
void Fog::fog_volume_initialize(RID p_rid) {
}
-void Fog::fog_free(RID p_rid) {
+void Fog::fog_volume_free(RID p_rid) {
}
void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {
diff --git a/drivers/gles3/environment/fog.h b/drivers/gles3/environment/fog.h
index 350eb459cf..fcde7399dd 100644
--- a/drivers/gles3/environment/fog.h
+++ b/drivers/gles3/environment/fog.h
@@ -46,7 +46,7 @@ public:
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;
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/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index d106bb31c7..82d054ac59 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -34,7 +34,6 @@
#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/rendering_server_globals.h"
#include "storage/config.h"
-#include "storage/light_storage.h"
#include "storage/mesh_storage.h"
#include "storage/texture_storage.h"
@@ -70,7 +69,7 @@ void RasterizerSceneGLES3::GeometryInstanceGLES3::pair_light_instances(const RID
spot_lights.clear();
for (uint32_t i = 0; i < p_light_instance_count; i++) {
- RS::LightType type = RasterizerSceneGLES3::get_singleton()->light_instance_get_type(p_light_instances[i]);
+ RS::LightType type = GLES3::LightStorage::get_singleton()->light_instance_get_type(p_light_instances[i]);
switch (type) {
case RS::LIGHT_OMNI: {
if (omni_light_count < (uint32_t)config->max_lights_per_object) {
@@ -399,32 +398,6 @@ void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_g
ginstance->dirty_list_element.remove_from_list();
}
-/* SHADOW ATLAS API */
-
-RID RasterizerSceneGLES3::shadow_atlas_create() {
- return RID();
-}
-
-void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) {
-}
-
-void RasterizerSceneGLES3::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
-}
-
-bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) {
- return false;
-}
-
-void RasterizerSceneGLES3::directional_shadow_atlas_set_size(int p_size, bool p_16_bits) {
-}
-
-int RasterizerSceneGLES3::get_directional_light_shadow_size(RID p_light_intance) {
- return 0;
-}
-
-void RasterizerSceneGLES3::set_directional_shadow_count(int p_count) {
-}
-
/* SKY API */
void RasterizerSceneGLES3::_free_sky_data(Sky *p_sky) {
@@ -625,7 +598,7 @@ void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, cons
if (shader_data->uses_light) {
sky_globals.directional_light_count = 0;
for (int i = 0; i < (int)p_lights.size(); i++) {
- LightInstance *li = light_instance_owner.get_or_null(p_lights[i]);
+ GLES3::LightInstance *li = GLES3::LightStorage::get_singleton()->get_light_instance(p_lights[i]);
if (!li) {
continue;
}
@@ -1084,38 +1057,6 @@ void RasterizerSceneGLES3::positional_soft_shadow_filter_set_quality(RS::ShadowQ
void RasterizerSceneGLES3::directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) {
}
-RID RasterizerSceneGLES3::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);
-
- return li;
-}
-
-void RasterizerSceneGLES3::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 RasterizerSceneGLES3::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 RasterizerSceneGLES3::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) {
-}
-
-void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) {
-}
-
RID RasterizerSceneGLES3::fog_volume_instance_create(RID p_fog_volume) {
return RID();
}
@@ -1134,57 +1075,6 @@ Vector3 RasterizerSceneGLES3::fog_volume_instance_get_position(RID p_fog_volume_
return Vector3();
}
-RID RasterizerSceneGLES3::reflection_atlas_create() {
- return RID();
-}
-
-int RasterizerSceneGLES3::reflection_atlas_get_size(RID p_ref_atlas) const {
- return 0;
-}
-
-void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) {
-}
-
-RID RasterizerSceneGLES3::reflection_probe_instance_create(RID p_probe) {
- return RID();
-}
-
-void RasterizerSceneGLES3::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) {
-}
-
-void RasterizerSceneGLES3::reflection_probe_release_atlas_index(RID p_instance) {
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_needs_redraw(RID p_instance) {
- return false;
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_has_reflection(RID p_instance) {
- return false;
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
- return false;
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_postprocess_step(RID p_instance) {
- return true;
-}
-
-RID RasterizerSceneGLES3::decal_instance_create(RID p_decal) {
- return RID();
-}
-
-void RasterizerSceneGLES3::decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) {
-}
-
-RID RasterizerSceneGLES3::lightmap_instance_create(RID p_lightmap) {
- return RID();
-}
-
-void RasterizerSceneGLES3::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) {
-}
-
RID RasterizerSceneGLES3::voxel_gi_instance_create(RID p_voxel_gi) {
return RID();
}
@@ -1257,13 +1147,13 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
if (inst->omni_light_count) {
inst->omni_light_gl_cache.resize(inst->omni_light_count);
for (uint32_t j = 0; j < inst->omni_light_count; j++) {
- inst->omni_light_gl_cache[j] = light_instance_get_gl_id(inst->omni_lights[j]);
+ inst->omni_light_gl_cache[j] = GLES3::LightStorage::get_singleton()->light_instance_get_gl_id(inst->omni_lights[j]);
}
}
if (inst->spot_light_count) {
inst->spot_light_gl_cache.resize(inst->spot_light_count);
for (uint32_t j = 0; j < inst->spot_light_count; j++) {
- inst->spot_light_gl_cache[j] = light_instance_get_gl_id(inst->spot_lights[j]);
+ inst->spot_light_gl_cache[j] = GLES3::LightStorage::get_singleton()->light_instance_get_gl_id(inst->spot_lights[j]);
}
}
}
@@ -1501,7 +1391,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
int num_lights = lights.size();
for (int i = 0; i < num_lights; i++) {
- LightInstance *li = light_instance_owner.get_or_null(lights[i]);
+ GLES3::LightInstance *li = GLES3::LightStorage::get_singleton()->get_light_instance(lights[i]);
if (!li) {
continue;
}
@@ -1606,12 +1496,12 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
}
if (r_omni_light_count) {
- SortArray<InstanceSort<LightInstance>> sorter;
+ SortArray<InstanceSort<GLES3::LightInstance>> sorter;
sorter.sort(scene_state.omni_light_sort, r_omni_light_count);
}
if (r_spot_light_count) {
- SortArray<InstanceSort<LightInstance>> sorter;
+ SortArray<InstanceSort<GLES3::LightInstance>> sorter;
sorter.sort(scene_state.spot_light_sort, r_spot_light_count);
}
@@ -1619,7 +1509,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
uint32_t index = (i < r_omni_light_count) ? i : i - (r_omni_light_count);
LightData &light_data = (i < r_omni_light_count) ? scene_state.omni_lights[index] : scene_state.spot_lights[index];
RS::LightType type = (i < r_omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT;
- LightInstance *li = (i < r_omni_light_count) ? scene_state.omni_light_sort[index].instance : scene_state.spot_light_sort[index].instance;
+ GLES3::LightInstance *li = (i < r_omni_light_count) ? scene_state.omni_light_sort[index].instance : scene_state.spot_light_sort[index].instance;
RID base = li->light;
Transform3D light_transform = li->transform;
@@ -2390,10 +2280,8 @@ bool RasterizerSceneGLES3::free(RID p_rid) {
ERR_FAIL_COND_V(!sky, false);
_free_sky_data(sky);
sky_owner.free(p_rid);
- } else if (light_instance_owner.owns(p_rid)) {
- LightInstance *light_instance = light_instance_owner.get_or_null(p_rid);
- ERR_FAIL_COND_V(!light_instance, false);
- light_instance_owner.free(p_rid);
+ } else if (GLES3::LightStorage::get_singleton()->owns_light_instance(p_rid)) {
+ GLES3::LightStorage::get_singleton()->light_instance_free(p_rid);
} else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) {
//not much to delete, just free it
RSG::camera_attributes->camera_attributes_free(p_rid);
@@ -2433,13 +2321,13 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() {
uint32_t light_buffer_size = config->max_renderable_lights * sizeof(LightData);
scene_state.omni_lights = memnew_arr(LightData, config->max_renderable_lights);
- scene_state.omni_light_sort = memnew_arr(InstanceSort<LightInstance>, config->max_renderable_lights);
+ scene_state.omni_light_sort = memnew_arr(InstanceSort<GLES3::LightInstance>, config->max_renderable_lights);
glGenBuffers(1, &scene_state.omni_light_buffer);
glBindBuffer(GL_UNIFORM_BUFFER, scene_state.omni_light_buffer);
glBufferData(GL_UNIFORM_BUFFER, light_buffer_size, nullptr, GL_STREAM_DRAW);
scene_state.spot_lights = memnew_arr(LightData, config->max_renderable_lights);
- scene_state.spot_light_sort = memnew_arr(InstanceSort<LightInstance>, config->max_renderable_lights);
+ scene_state.spot_light_sort = memnew_arr(InstanceSort<GLES3::LightInstance>, config->max_renderable_lights);
glGenBuffers(1, &scene_state.spot_light_buffer);
glBindBuffer(GL_UNIFORM_BUFFER, scene_state.spot_light_buffer);
glBufferData(GL_UNIFORM_BUFFER, light_buffer_size, nullptr, GL_STREAM_DRAW);
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index f0dc972678..d11dc14080 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -44,6 +44,7 @@
#include "shader_gles3.h"
#include "shaders/cubemap_filter.glsl.gen.h"
#include "shaders/sky.glsl.gen.h"
+#include "storage/light_storage.h"
#include "storage/material_storage.h"
#include "storage/render_scene_buffers_gles3.h"
#include "storage/utilities.h"
@@ -183,34 +184,6 @@ private:
};
static_assert(sizeof(DirectionalLightData) % 16 == 0, "DirectionalLightData size must be a multiple of 16 bytes");
- struct LightInstance {
- RS::LightType light_type = RS::LIGHT_DIRECTIONAL;
-
- 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;
-
- uint32_t gl_id = -1;
-
- LightInstance() {}
- };
-
- mutable RID_Owner<LightInstance> light_instance_owner;
-
class GeometryInstanceGLES3;
// Cached data for drawing surfaces
@@ -398,8 +371,8 @@ private:
LightData *omni_lights = nullptr;
LightData *spot_lights = nullptr;
- InstanceSort<LightInstance> *omni_light_sort;
- InstanceSort<LightInstance> *spot_light_sort;
+ InstanceSort<GLES3::LightInstance> *omni_light_sort;
+ InstanceSort<GLES3::LightInstance> *spot_light_sort;
GLuint omni_light_buffer = 0;
GLuint spot_light_buffer = 0;
uint32_t omni_light_count = 0;
@@ -605,17 +578,6 @@ public:
uint32_t geometry_instance_get_pair_mask() override;
- /* SHADOW ATLAS API */
-
- RID shadow_atlas_create() override;
- 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;
-
- 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;
- 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 {}
@@ -666,45 +628,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;
- 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;
-
- _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_ uint32_t light_instance_get_gl_id(RID p_light_instance) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->gl_id;
- }
-
RID fog_volume_instance_create(RID p_fog_volume) override;
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;
Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override;
- RID reflection_atlas_create() override;
- int reflection_atlas_get_size(RID p_ref_atlas) const override;
- 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;
- 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;
- bool reflection_probe_instance_has_reflection(RID p_instance) override;
- bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override;
- bool reflection_probe_instance_postprocess_step(RID p_instance) override;
-
- RID decal_instance_create(RID p_decal) override;
- void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override;
-
- RID lightmap_instance_create(RID p_lightmap) override;
- void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override;
-
RID voxel_gi_instance_create(RID p_voxel_gi) override;
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;
diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp
index 6411590aee..b6bd4a2760 100644
--- a/drivers/gles3/storage/light_storage.cpp
+++ b/drivers/gles3/storage/light_storage.cpp
@@ -333,6 +333,46 @@ AABB LightStorage::light_get_aabb(RID p_light) const {
ERR_FAIL_V(AABB());
}
+/* 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);
+
+ return li;
+}
+
+void LightStorage::light_instance_free(RID p_light_instance) {
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+ light_instance_owner.free(p_light_instance);
+}
+
+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) {
+}
+
+void LightStorage::light_instance_mark_visible(RID p_light_instance) {
+}
+
/* PROBE API */
RID LightStorage::reflection_probe_allocate() {
@@ -419,6 +459,53 @@ float LightStorage::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
return 0.0;
}
+/* REFLECTION ATLAS */
+
+RID LightStorage::reflection_atlas_create() {
+ return RID();
+}
+
+void LightStorage::reflection_atlas_free(RID p_ref_atlas) {
+}
+
+int LightStorage::reflection_atlas_get_size(RID p_ref_atlas) const {
+ return 0;
+}
+
+void LightStorage::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) {
+}
+
+/* REFLECTION PROBE INSTANCE */
+
+RID LightStorage::reflection_probe_instance_create(RID p_probe) {
+ return RID();
+}
+
+void LightStorage::reflection_probe_instance_free(RID p_instance) {
+}
+
+void LightStorage::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) {
+}
+
+void LightStorage::reflection_probe_release_atlas_index(RID p_instance) {
+}
+
+bool LightStorage::reflection_probe_instance_needs_redraw(RID p_instance) {
+ return false;
+}
+
+bool LightStorage::reflection_probe_instance_has_reflection(RID p_instance) {
+ return false;
+}
+
+bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
+ return false;
+}
+
+bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) {
+ return true;
+}
+
/* LIGHTMAP CAPTURE */
RID LightStorage::lightmap_allocate() {
@@ -484,6 +571,18 @@ float LightStorage::lightmap_get_probe_capture_update_speed() const {
return 0;
}
+/* LIGHTMAP INSTANCE */
+
+RID LightStorage::lightmap_instance_create(RID p_lightmap) {
+ return RID();
+}
+
+void LightStorage::lightmap_instance_free(RID p_lightmap) {
+}
+
+void LightStorage::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) {
+}
+
/* LIGHT SHADOW MAPPING */
/*
@@ -584,4 +683,36 @@ void LightStorage::canvas_light_occluder_set_polylines(RID p_occluder, const Poo
}
*/
+/* SHADOW ATLAS API */
+
+RID LightStorage::shadow_atlas_create() {
+ return RID();
+}
+
+void LightStorage::shadow_atlas_free(RID p_atlas) {
+}
+
+void LightStorage::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) {
+}
+
+void LightStorage::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
+}
+
+bool LightStorage::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) {
+ return false;
+}
+
+void LightStorage::shadow_atlas_update(RID p_atlas) {
+}
+
+void LightStorage::directional_shadow_atlas_set_size(int p_size, bool p_16_bits) {
+}
+
+int LightStorage::get_directional_light_shadow_size(RID p_light_intance) {
+ return 0;
+}
+
+void LightStorage::set_directional_shadow_count(int p_count) {
+}
+
#endif // !GLES3_ENABLED
diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h
index 8b708116ac..12cb2c4393 100644
--- a/drivers/gles3/storage/light_storage.h
+++ b/drivers/gles3/storage/light_storage.h
@@ -76,6 +76,33 @@ struct Light {
Dependency dependency;
};
+/* Light instance */
+struct LightInstance {
+ RS::LightType light_type = RS::LIGHT_DIRECTIONAL;
+
+ 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;
+
+ uint32_t gl_id = -1;
+
+ LightInstance() {}
+};
+
/* REFLECTION PROBE */
struct ReflectionProbe {
@@ -128,6 +155,9 @@ private:
/* LIGHT */
mutable RID_Owner<Light, true> light_owner;
+ /* Light instance */
+ mutable RID_Owner<LightInstance> light_instance_owner;
+
/* REFLECTION PROBE */
mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
@@ -268,6 +298,28 @@ 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;
+ /* LIGHT INSTANCE API */
+
+ LightInstance *get_light_instance(RID p_rid) { return light_instance_owner.get_or_null(p_rid); };
+ 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_instance) 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_ 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_ uint32_t light_instance_get_gl_id(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->gl_id;
+ }
+
/* PROBE API */
virtual RID reflection_probe_allocate() override;
@@ -298,6 +350,24 @@ public:
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override;
virtual bool reflection_probe_renders_shadows(RID p_probe) const override;
+ /* REFLECTION ATLAS */
+
+ virtual RID reflection_atlas_create() override;
+ virtual void reflection_atlas_free(RID p_ref_atlas) override;
+ virtual int reflection_atlas_get_size(RID p_ref_atlas) const override;
+ 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;
+ 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;
+
/* LIGHTMAP CAPTURE */
Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); };
@@ -338,6 +408,26 @@ public:
RID canvas_light_occluder_create();
void canvas_light_occluder_set_polylines(RID p_occluder, const LocalVector<Vector2> &p_lines);
*/
+
+ /* LIGHTMAP INSTANCE */
+
+ 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;
+
+ /* SHADOW ATLAS API */
+
+ 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_intance, float p_coverage, uint64_t p_light_version) override;
+
+ 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;
+ virtual void set_directional_shadow_count(int p_count) override;
};
} // namespace GLES3
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index e18c0ec649..8ea10539ec 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -1183,6 +1183,18 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const {
return AABB();
}
+/* DECAL INSTANCE API */
+
+RID TextureStorage::decal_instance_create(RID p_decal) {
+ return RID();
+}
+
+void TextureStorage::decal_instance_free(RID p_decal_instance) {
+}
+
+void TextureStorage::decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) {
+}
+
/* RENDER TARGET API */
GLuint TextureStorage::system_fbo = 0;
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 4f4032723b..16bf406845 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -509,6 +509,12 @@ 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;
+ 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 API */
static GLuint system_fbo;
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..f5bdccca68 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -146,6 +146,12 @@ 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(); }
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..1cbc52dec3 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"
@@ -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;
@@ -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;
}
}
@@ -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;
}
}
@@ -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();
@@ -1586,7 +1616,7 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
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];
- 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
@@ -1634,10 +1664,10 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0];
push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1];
push_constant.vertical = 0;
- if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) {
+ 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..4c72f0a56e 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);
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..0853460861 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -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));
@@ -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();
@@ -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..21a15ed475 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -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 3a9c695653..c1a7818921 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() {
@@ -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()) {
@@ -1030,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++;
}
@@ -1058,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()) {
@@ -1070,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
@@ -1153,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
}
@@ -1188,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;
@@ -1538,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()) {
+ Size2 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()) {
+ Size2 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)) {
+ 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);
+ }
+}
+
+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;
+ }
+ }
+
+ int directional_shadow_size = light_storage->directional_shadow_get_size();
+ atlas_rect.position /= directional_shadow_size;
+ atlas_rect.size /= directional_shadow_size;
+
+ light_storage->light_instance_set_directional_shadow_atlas_rect(p_light, p_pass, atlas_rect);
+
+ 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() {
@@ -1894,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);
}
@@ -2010,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);
}
@@ -2025,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);
}
{
@@ -2069,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);
}
@@ -2147,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;
@@ -2164,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);
@@ -2176,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));
}
@@ -2191,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);
@@ -2267,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);
@@ -2353,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);
@@ -2512,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() {
@@ -2831,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;
}
@@ -3013,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() {
@@ -3056,15 +3824,31 @@ RenderForwardClustered::RenderForwardClustered() {
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;
@@ -3075,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 1e70f6880c..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);
@@ -558,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;
@@ -577,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_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index f458063aea..c3ce1b05f1 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;
+ }
+ }
+
+ int directional_shadow_size = light_storage->directional_shadow_get_size();
+ atlas_rect.position /= directional_shadow_size;
+ atlas_rect.size /= directional_shadow_size;
+
+ light_storage->light_instance_set_directional_shadow_atlas_rect(p_light, p_pass, atlas_rect);
+
+ 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();
@@ -1797,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)) {
@@ -1989,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;
@@ -2012,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]);
}
}
@@ -2387,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;
}
@@ -2446,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() {
@@ -2495,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 a53872fc88..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,8 +351,28 @@ 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 */
+ 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,
@@ -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/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 74b8f0890f..acc964b3f3 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;
- }
+/* FOG VOLUME INSTANCE */
- 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);
-
- 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,8 +826,8 @@ 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();
+ if (RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture().is_valid()) {
+ RID shadow_atlas_texture = RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture();
Size2 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);
@@ -1889,28 +852,11 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD>
}
}
- 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);
@@ -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;
- }
-
- 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
+void RendererSceneRenderRD::_update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ if (p_render_buffers.is_valid() && vrs) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- 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 = &empty;
}
- // 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 {
@@ -3694,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);
}
@@ -3724,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;
@@ -3744,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 */
@@ -3759,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);
@@ -3844,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);
}
@@ -3864,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);
@@ -3889,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/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 70243a9275..36f1bc0316 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -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) {
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index 2ce6550cc1..d496eed17a 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -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) {
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index b089b96101..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() {
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 4dca2233fe..18303ce870 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -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() {
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..1b2237b505 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();
@@ -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) {
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..169ee2e2b1 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();
@@ -215,8 +209,6 @@ public:
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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 +225,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/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 21811068cd..14e41a0d6b 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -31,6 +31,7 @@
#include "texture_storage.h"
#include "../effects/copy_effects.h"
#include "material_storage.h"
+#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
using namespace RendererRD;
@@ -457,6 +458,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 +478,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;
}
@@ -1888,7 +1912,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) {
@@ -2112,6 +2136,227 @@ 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 */
void TextureStorage::_clear_render_target(RenderTarget *rt) {
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index a3acad30f3..327a21a1fc 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,7 +249,52 @@ 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 */
@@ -343,6 +392,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 +596,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); };
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..11d22f321b 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -760,7 +760,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 +1076,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 +1294,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/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..5024a76c09 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -120,6 +120,12 @@ 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;
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 67ba407775..6885d80301 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -485,6 +485,12 @@ public:
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
virtual void light_directional_set_sky_mode(RID p_light, LightDirectionalSkyMode p_mode) = 0;
+ // Shadow atlas
+
+ 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;
+
virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0;
enum ShadowQuality {