summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorreduz <reduzio@gmail.com>2020-12-23 13:52:58 -0300
committerreduz <reduzio@gmail.com>2020-12-23 19:31:30 -0300
commit83058597cf02255d7c0359a96f125010f63deff7 (patch)
treef3eb989587e98c17f5b0c669af45993f893c8771
parentc4c211c3b7608f79457f16bb42ad8839a9cdcf5a (diff)
Replace Octree by DynamicBVH in cull code
-Much greater pairing/unpairing performance -For now, using it for culling too, but this will change in a couple of days. -Added a paged allocator, to efficiently alloc/free some types of objects.
-rw-r--r--core/math/dynamic_bvh.cpp25
-rw-r--r--core/math/dynamic_bvh.h125
-rw-r--r--core/templates/paged_allocator.h129
-rw-r--r--core/templates/paged_array.h2
-rw-r--r--core/templates/rid_owner.h13
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_forward.cpp62
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_forward.h18
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp123
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h43
-rw-r--r--servers/rendering/renderer_scene_cull.cpp819
-rw-r--r--servers/rendering/renderer_scene_cull.h205
-rw-r--r--servers/rendering/renderer_scene_render.h17
-rw-r--r--servers/rendering_server.cpp3
13 files changed, 1027 insertions, 557 deletions
diff --git a/core/math/dynamic_bvh.cpp b/core/math/dynamic_bvh.cpp
index 8486415c81..5f87f75b61 100644
--- a/core/math/dynamic_bvh.cpp
+++ b/core/math/dynamic_bvh.cpp
@@ -49,7 +49,6 @@ DynamicBVH::Node *DynamicBVH::_create_node(Node *p_parent, void *p_data) {
Node *node = memnew(Node);
node->parent = p_parent;
node->data = p_data;
- node->childs[1] = 0;
return (node);
}
@@ -335,6 +334,7 @@ DynamicBVH::ID DynamicBVH::insert(const AABB &p_box, void *p_userdata) {
ID id;
id.node = leaf;
+
return id;
}
@@ -389,12 +389,35 @@ void DynamicBVH::_extract_leaves(Node *p_node, List<ID> *r_elements) {
}
}
+void DynamicBVH::set_index(uint32_t p_index) {
+ ERR_FAIL_COND(bvh_root != nullptr);
+ index = p_index;
+}
+
+uint32_t DynamicBVH::get_index() const {
+ return index;
+}
+
void DynamicBVH::get_elements(List<ID> *r_elements) {
if (bvh_root) {
_extract_leaves(bvh_root, r_elements);
}
}
+int DynamicBVH::get_leaf_count() const {
+ return total_leaves;
+}
+int DynamicBVH::get_max_depth() const {
+ if (bvh_root) {
+ int depth = 1;
+ int max_depth = 0;
+ bvh_root->get_max_depth(depth, max_depth);
+ return max_depth;
+ } else {
+ return 0;
+ }
+}
+
DynamicBVH::~DynamicBVH() {
clear();
}
diff --git a/core/math/dynamic_bvh.h b/core/math/dynamic_bvh.h
index 81d70d7469..cdea51c674 100644
--- a/core/math/dynamic_bvh.h
+++ b/core/math/dynamic_bvh.h
@@ -61,13 +61,10 @@ class DynamicBVH {
public:
struct ID {
- Node *node;
+ Node *node = nullptr;
public:
_FORCE_INLINE_ bool is_valid() const { return node != nullptr; }
- _FORCE_INLINE_ ID() {
- node = nullptr;
- }
};
private:
@@ -134,6 +131,48 @@ private:
(min.z <= b.max.z) &&
(max.z >= b.min.z));
}
+
+ _FORCE_INLINE_ bool intersects_convex(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const {
+ Vector3 half_extents = (max - min) * 0.5;
+ Vector3 ofs = min + half_extents;
+
+ for (int i = 0; i < p_plane_count; i++) {
+ const Plane &p = p_planes[i];
+ Vector3 point(
+ (p.normal.x > 0) ? -half_extents.x : half_extents.x,
+ (p.normal.y > 0) ? -half_extents.y : half_extents.y,
+ (p.normal.z > 0) ? -half_extents.z : half_extents.z);
+ point += ofs;
+ if (p.is_point_over(point)) {
+ return false;
+ }
+ }
+
+ // Make sure all points in the shape aren't fully separated from the AABB on
+ // each axis.
+ int bad_point_counts_positive[3] = { 0 };
+ int bad_point_counts_negative[3] = { 0 };
+
+ for (int k = 0; k < 3; k++) {
+ for (int i = 0; i < p_point_count; i++) {
+ if (p_points[i].coord[k] > ofs.coord[k] + half_extents.coord[k]) {
+ bad_point_counts_positive[k]++;
+ }
+ if (p_points[i].coord[k] < ofs.coord[k] - half_extents.coord[k]) {
+ bad_point_counts_negative[k]++;
+ }
+ }
+
+ if (bad_point_counts_negative[k] == p_point_count) {
+ return false;
+ }
+ if (bad_point_counts_positive[k] == p_point_count) {
+ return false;
+ }
+ }
+
+ return true;
+ }
};
struct Node {
@@ -144,14 +183,14 @@ private:
void *data;
};
- _FORCE_INLINE_ bool is_leaf() const { return data != nullptr; }
+ _FORCE_INLINE_ bool is_leaf() const { return childs[1] == nullptr; }
_FORCE_INLINE_ bool is_internal() const { return (!is_leaf()); }
_FORCE_INLINE_ int get_index_in_parent() const {
ERR_FAIL_COND_V(!parent, 0);
return (parent->childs[1] == this) ? 1 : 0;
}
- _FORCE_INLINE_ void get_max_depth(int depth, int &maxdepth) {
+ void get_max_depth(int depth, int &maxdepth) {
if (is_internal()) {
childs[0]->get_max_depth(depth + 1, maxdepth);
childs[1]->get_max_depth(depth + 1, maxdepth);
@@ -183,6 +222,7 @@ private:
int lkhd = -1;
int total_leaves = 0;
uint32_t opath = 0;
+ uint32_t index = 0;
enum {
ALLOCA_STACK_SIZE = 128
@@ -245,6 +285,9 @@ public:
void remove(const ID &p_id);
void get_elements(List<ID> *r_elements);
+ int get_leaf_count() const;
+ int get_max_depth() const;
+
/* Discouraged, but works as a reference on how it must be used */
struct DefaultQueryResult {
virtual bool operator()(void *p_data) = 0; //return true whether you want to continue the query
@@ -254,9 +297,13 @@ public:
template <class QueryResult>
_FORCE_INLINE_ void aabb_query(const AABB &p_aabb, QueryResult &r_result);
template <class QueryResult>
+ _FORCE_INLINE_ void convex_query(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, QueryResult &r_result);
+ template <class QueryResult>
_FORCE_INLINE_ void ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResult &r_result);
- DynamicBVH();
+ void set_index(uint32_t p_index);
+ uint32_t get_index() const;
+
~DynamicBVH();
};
@@ -278,8 +325,8 @@ void DynamicBVH::aabb_query(const AABB &p_box, QueryResult &r_result) {
LocalVector<const Node *> aux_stack; //only used in rare occasions when you run out of alloca memory because tree is too unbalanced. Should correct itself over time.
do {
- const Node *n = stack[depth - 1];
depth--;
+ const Node *n = stack[depth];
if (n->volume.intersects(volume)) {
if (n->is_internal()) {
if (depth > threshold) {
@@ -304,7 +351,66 @@ void DynamicBVH::aabb_query(const AABB &p_box, QueryResult &r_result) {
}
template <class QueryResult>
+void DynamicBVH::convex_query(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, QueryResult &r_result) {
+ if (!bvh_root) {
+ return;
+ }
+
+ //generate a volume anyway to improve pre-testing
+ Volume volume;
+ for (int i = 0; i < p_point_count; i++) {
+ if (i == 0) {
+ volume.min = p_points[0];
+ volume.max = p_points[0];
+ } else {
+ volume.min.x = MIN(volume.min.x, p_points[i].x);
+ volume.min.y = MIN(volume.min.y, p_points[i].y);
+ volume.min.z = MIN(volume.min.z, p_points[i].z);
+
+ volume.max.x = MAX(volume.max.x, p_points[i].x);
+ volume.max.y = MAX(volume.max.y, p_points[i].y);
+ volume.max.z = MAX(volume.max.z, p_points[i].z);
+ }
+ }
+
+ const Node **stack = (const Node **)alloca(ALLOCA_STACK_SIZE * sizeof(const Node *));
+ stack[0] = bvh_root;
+ int32_t depth = 1;
+ int32_t threshold = ALLOCA_STACK_SIZE - 2;
+
+ LocalVector<const Node *> aux_stack; //only used in rare occasions when you run out of alloca memory because tree is too unbalanced. Should correct itself over time.
+
+ do {
+ depth--;
+ const Node *n = stack[depth];
+ if (n->volume.intersects(volume) && n->volume.intersects_convex(p_planes, p_plane_count, p_points, p_point_count)) {
+ if (n->is_internal()) {
+ if (depth > threshold) {
+ if (aux_stack.empty()) {
+ aux_stack.resize(ALLOCA_STACK_SIZE * 2);
+ copymem(aux_stack.ptr(), stack, ALLOCA_STACK_SIZE * sizeof(const Node *));
+ } else {
+ aux_stack.resize(aux_stack.size() * 2);
+ }
+ stack = aux_stack.ptr();
+ threshold = aux_stack.size() - 2;
+ }
+ stack[depth++] = n->childs[0];
+ stack[depth++] = n->childs[1];
+ } else {
+ if (r_result(n->data)) {
+ return;
+ }
+ }
+ }
+ } while (depth > 0);
+}
+template <class QueryResult>
void DynamicBVH::ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResult &r_result) {
+ if (!bvh_root) {
+ return;
+ }
+
Vector3 ray_dir = (p_to - p_from);
ray_dir.normalize();
@@ -327,7 +433,8 @@ void DynamicBVH::ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResu
LocalVector<const Node *> aux_stack; //only used in rare occasions when you run out of alloca memory because tree is too unbalanced. Should correct itself over time.
do {
- const Node *node = stack[--depth];
+ depth--;
+ const Node *node = stack[depth];
bounds[0] = node->volume.min;
bounds[1] = node->volume.max;
real_t tmin = 1.f, lambda_min = 0.f;
diff --git a/core/templates/paged_allocator.h b/core/templates/paged_allocator.h
new file mode 100644
index 0000000000..8bd1eecdeb
--- /dev/null
+++ b/core/templates/paged_allocator.h
@@ -0,0 +1,129 @@
+/*************************************************************************/
+/* paged_allocator.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 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 PAGED_ALLOCATOR_H
+#define PAGED_ALLOCATOR_H
+
+#include "core/os/memory.h"
+#include "core/os/spin_lock.h"
+#include "core/typedefs.h"
+
+template <class T, bool thread_safe = false>
+class PagedAllocator {
+ T **page_pool = nullptr;
+ T ***available_pool = nullptr;
+ uint32_t pages_allocated = 0;
+ uint32_t allocs_available = 0;
+
+ uint32_t page_shift = 0;
+ uint32_t page_mask = 0;
+ uint32_t page_size = 0;
+ SpinLock spin_lock;
+
+public:
+ T *alloc() {
+ if (thread_safe) {
+ spin_lock.lock();
+ }
+ if (unlikely(allocs_available == 0)) {
+ uint32_t pages_used = pages_allocated;
+
+ pages_allocated++;
+ page_pool = (T **)memrealloc(page_pool, sizeof(T *) * pages_allocated);
+ available_pool = (T ***)memrealloc(available_pool, sizeof(T **) * pages_allocated);
+
+ page_pool[pages_used] = (T *)memalloc(sizeof(T) * page_size);
+ available_pool[pages_used] = (T **)memalloc(sizeof(T *) * page_size);
+
+ for (uint32_t i = 0; i < page_size; i++) {
+ available_pool[0][i] = &page_pool[pages_used][i];
+ }
+ allocs_available += page_size;
+ }
+
+ allocs_available--;
+ T *alloc = available_pool[allocs_available >> page_shift][allocs_available & page_mask];
+ if (thread_safe) {
+ spin_lock.unlock();
+ }
+ memnew_placement(alloc, T);
+ return alloc;
+ }
+
+ void free(T *p_mem) {
+ if (thread_safe) {
+ spin_lock.lock();
+ }
+ p_mem->~T();
+ available_pool[allocs_available >> page_shift][allocs_available & page_mask] = p_mem;
+ if (thread_safe) {
+ spin_lock.unlock();
+ }
+ allocs_available++;
+ }
+
+ void reset() {
+ ERR_FAIL_COND(allocs_available < pages_allocated * page_size);
+ if (pages_allocated) {
+ for (uint32_t i = 0; i < pages_allocated; i++) {
+ memfree(page_pool[i]);
+ memfree(available_pool[i]);
+ }
+ memfree(page_pool);
+ memfree(available_pool);
+ page_pool = nullptr;
+ available_pool = nullptr;
+ pages_allocated = 0;
+ allocs_available = 0;
+ }
+ }
+ bool is_configured() const {
+ return page_size > 0;
+ }
+
+ void configure(uint32_t p_page_size, bool p_thread_safe) {
+ ERR_FAIL_COND(page_pool != nullptr); //sanity check
+ ERR_FAIL_COND(p_page_size == 0);
+ page_size = nearest_power_of_2_templated(p_page_size);
+ page_mask = page_size - 1;
+ page_shift = get_shift_from_power_of_2(page_size);
+ }
+
+ PagedAllocator(uint32_t p_page_size = 4096, bool p_thread_safe = false) { // power of 2 recommended because of alignment with OS page sizes. Even if element is bigger, its still a multiple and get rounded amount of pages
+ configure(p_page_size, false);
+ }
+
+ ~PagedAllocator() {
+ ERR_FAIL_COND_MSG(allocs_available < pages_allocated * page_size, "Pages in use exist at exit in PagedAllocator");
+ reset();
+ }
+};
+
+#endif // PAGED_ALLOCATOR_H
diff --git a/core/templates/paged_array.h b/core/templates/paged_array.h
index 71183c4ad8..aaf3893715 100644
--- a/core/templates/paged_array.h
+++ b/core/templates/paged_array.h
@@ -329,7 +329,7 @@ public:
}
}
- uint64_t size() const {
+ _FORCE_INLINE_ uint64_t size() const {
return count;
}
diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h
index d1bcb92010..7de4e43648 100644
--- a/core/templates/rid_owner.h
+++ b/core/templates/rid_owner.h
@@ -346,6 +346,18 @@ public:
alloc.free(p_rid);
}
+ _FORCE_INLINE_ uint32_t get_rid_count() const {
+ return alloc.get_rid_count();
+ }
+
+ _FORCE_INLINE_ RID get_rid_by_index(uint32_t p_index) {
+ return alloc.get_rid_by_index(p_index);
+ }
+
+ _FORCE_INLINE_ T *get_ptr_by_index(uint32_t p_index) {
+ return *alloc.get_ptr_by_index(p_index);
+ }
+
_FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) {
return alloc.get_owned_list(p_owned);
}
@@ -353,6 +365,7 @@ public:
void set_description(const char *p_descrption) {
alloc.set_description(p_descrption);
}
+
RID_PtrOwner(uint32_t p_target_chunk_byte_size = 4096) :
alloc(p_target_chunk_byte_size) {}
};
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp
index 01dd2965c4..c6b2fa6dc0 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp
@@ -1532,7 +1532,7 @@ void RendererSceneRenderForward::_add_geometry_with_material(InstanceBase *p_ins
}
}
-void RendererSceneRenderForward::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_using_sdfgi) {
+void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, bool p_using_sdfgi) {
scene_state.current_shader_index = 0;
scene_state.current_material_index = 0;
scene_state.used_sss = false;
@@ -1544,8 +1544,8 @@ void RendererSceneRenderForward::_fill_render_list(InstanceBase **p_cull_result,
//fill list
- for (int i = 0; i < p_cull_count; i++) {
- InstanceBase *inst = p_cull_result[i];
+ for (int i = 0; i < (int)p_instances.size(); i++) {
+ InstanceBase *inst = p_instances[i];
//add geometry for drawing
switch (inst->base_type) {
@@ -1635,14 +1635,14 @@ void RendererSceneRenderForward::_fill_render_list(InstanceBase **p_cull_result,
}
}
-void RendererSceneRenderForward::_setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform) {
+void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform) {
uint32_t lightmaps_used = 0;
- for (int i = 0; i < p_lightmap_cull_count; i++) {
+ for (int i = 0; i < (int)p_lightmaps.size(); i++) {
if (i >= (int)scene_state.max_lightmaps) {
break;
}
- InstanceBase *lm = p_lightmap_cull_result[i];
+ InstanceBase *lm = p_lightmaps[i];
Basis to_lm = lm->transform.basis.inverse() * p_cam_transform.basis;
to_lm = to_lm.inverse().transposed(); //will transform normals
RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
@@ -1654,7 +1654,7 @@ void RendererSceneRenderForward::_setup_lightmaps(InstanceBase **p_lightmap_cull
}
}
-void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
+void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
RenderBufferDataForward *render_buffer = nullptr;
if (p_render_buffer.is_valid()) {
render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer);
@@ -1709,7 +1709,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
opaque_framebuffer = render_buffer->color_fb;
- if (!low_end && p_gi_probe_cull_count > 0) {
+ if (!low_end && p_gi_probes.size() > 0) {
using_giprobe = true;
render_buffer->ensure_gi();
}
@@ -1776,13 +1776,13 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
ERR_FAIL(); //bug?
}
- _setup_lightmaps(p_lightmap_cull_result, p_lightmap_cull_count, p_cam_transform);
+ _setup_lightmaps(p_lightmaps, p_cam_transform);
_setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
render_list.clear();
- _fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, using_sdfgi);
+ _fill_render_list(p_instances, PASS_MODE_COLOR, using_sdfgi);
bool using_sss = !low_end && render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
@@ -1864,7 +1864,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
clear_color = p_default_bg_color;
}
- RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probe_cull_result, p_gi_probe_cull_count);
+ RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probes);
render_list.sort_by_key(false);
@@ -1903,7 +1903,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
}
if (using_sdfgi || using_giprobe) {
- _process_gi(p_render_buffer, render_buffer->normal_roughness_buffer, render_buffer->ambient_buffer, render_buffer->reflection_buffer, render_buffer->giprobe_buffer, p_environment, p_cam_projection, p_cam_transform, p_gi_probe_cull_result, p_gi_probe_cull_count);
+ _process_gi(p_render_buffer, render_buffer->normal_roughness_buffer, render_buffer->ambient_buffer, render_buffer->reflection_buffer, render_buffer->giprobe_buffer, p_environment, p_cam_projection, p_cam_transform, p_gi_probes);
}
_setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.is_valid());
@@ -1949,8 +1949,8 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse());
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
- for (int i = 0; i < p_gi_probe_cull_count; i++) {
- _debug_giprobe(p_gi_probe_cull_result[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0);
+ for (int i = 0; i < (int)p_gi_probes.size(); i++) {
+ _debug_giprobe(p_gi_probes[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0);
}
RD::get_singleton()->draw_list_end();
}
@@ -2027,7 +2027,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
}
}
-void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
RENDER_TIMESTAMP("Setup Rendering Shadow");
_update_render_base_uniform_set();
@@ -2046,9 +2046,9 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase
PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
- _fill_render_list(p_cull_result, p_cull_count, pass_mode);
+ _fill_render_list(p_instances, pass_mode);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Shadow");
@@ -2064,7 +2064,7 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase
}
}
-void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, InstanceBase **p_cull_result, int p_cull_count) {
+void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) {
RENDER_TIMESTAMP("Setup Render Collider Heightfield");
_update_render_base_uniform_set();
@@ -2079,9 +2079,9 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb,
PassMode pass_mode = PASS_MODE_SHADOW;
- _fill_render_list(p_cull_result, p_cull_count, pass_mode);
+ _fill_render_list(p_instances, pass_mode);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Collider Heightield");
@@ -2097,7 +2097,7 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb,
}
}
-void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering Material");
_update_render_base_uniform_set();
@@ -2112,9 +2112,9 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
render_list.clear();
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
- _fill_render_list(p_cull_result, p_cull_count, pass_mode);
+ _fill_render_list(p_instances, pass_mode);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Material");
@@ -2136,7 +2136,7 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
}
}
-void RendererSceneRenderForward::_render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering UV2");
_update_render_base_uniform_set();
@@ -2151,9 +2151,9 @@ void RendererSceneRenderForward::_render_uv2(InstanceBase **p_cull_result, int p
render_list.clear();
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
- _fill_render_list(p_cull_result, p_cull_count, pass_mode);
+ _fill_render_list(p_instances, pass_mode);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Material");
@@ -2197,7 +2197,7 @@ void RendererSceneRenderForward::_render_uv2(InstanceBase **p_cull_result, int p
}
}
-void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
RENDER_TIMESTAMP("Render SDFGI");
_update_render_base_uniform_set();
@@ -2209,7 +2209,7 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto
render_list.clear();
PassMode pass_mode = PASS_MODE_SDF;
- _fill_render_list(p_cull_result, p_cull_count, pass_mode);
+ _fill_render_list(p_instances, pass_mode);
render_list.sort_by_key(false);
_fill_instances(render_list.elements, render_list.element_count, true);
@@ -2453,7 +2453,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
}
}
-RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count) {
+RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes) {
if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
RD::get_singleton()->free(render_pass_uniform_set);
}
@@ -2516,8 +2516,8 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
u.ids.resize(MAX_GI_PROBES);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_GI_PROBES; i++) {
- if (i < p_gi_probe_cull_count) {
- RID tex = gi_probe_instance_get_texture(p_gi_probe_cull_result[i]);
+ if (i < (int)p_gi_probes.size()) {
+ RID tex = gi_probe_instance_get_texture(p_gi_probes[i]);
if (!tex.is_valid()) {
tex = default_tex;
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.h b/servers/rendering/renderer_rd/renderer_scene_render_forward.h
index da4cb579c1..5d77c13b43 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_forward.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.h
@@ -266,7 +266,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
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);
- RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count);
+ RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes);
struct LightmapData {
float normal_xform[12];
@@ -567,26 +567,26 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
};
void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
- void _setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform);
+ void _setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform);
void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false);
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
- void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_using_sdfgi = false);
+ void _fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, bool p_using_sdfgi = false);
Map<Size2i, RID> sdfgi_framebuffer_size_cache;
bool low_end = false;
protected:
- virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
- virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &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_lod_threshold = 0.0);
- virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, InstanceBase **p_cull_result, int p_cull_count);
+ virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
+ virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &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_lod_threshold = 0.0);
+ virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances);
public:
virtual void set_time(double p_time, double p_step);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 1d9983a28c..02ec399f58 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -1153,7 +1153,7 @@ void RendererSceneRenderRD::_sdfgi_update_cascades(RID p_render_buffers) {
RD::get_singleton()->buffer_update(rb->sdfgi->cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, true);
}
-void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count) {
+void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_environment, const PagedArray<RID> &p_directional_light_instances, const RID *p_positional_light_instances, uint32_t p_positional_light_count) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(rb == nullptr);
if (rb->sdfgi == nullptr) {
@@ -1179,7 +1179,7 @@ void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_envi
SDGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS];
uint32_t idx = 0;
- for (uint32_t j = 0; j < p_directional_light_count; j++) {
+ for (uint32_t j = 0; j < (uint32_t)p_directional_light_instances.size(); j++) {
if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) {
break;
}
@@ -1402,7 +1402,7 @@ void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_envi
RENDER_TIMESTAMP("<SDFGI Update Probes");
}
-void RendererSceneRenderRD::_setup_giprobes(RID p_render_buffers, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, uint32_t &r_gi_probes_used) {
+void RendererSceneRenderRD::_setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used) {
r_gi_probes_used = 0;
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(rb == nullptr);
@@ -1417,8 +1417,8 @@ void RendererSceneRenderRD::_setup_giprobes(RID p_render_buffers, const Transfor
for (int i = 0; i < RenderBuffers::MAX_GIPROBES; i++) {
RID texture;
- if (i < p_gi_probe_cull_count) {
- GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_gi_probe_cull_result[i]);
+ if (i < (int)p_gi_probes.size()) {
+ GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_gi_probes[i]);
if (gipi) {
texture = gipi->texture;
@@ -1489,12 +1489,12 @@ void RendererSceneRenderRD::_setup_giprobes(RID p_render_buffers, const Transfor
}
}
- if (p_gi_probe_cull_count > 0) {
- RD::get_singleton()->buffer_update(gi_probe_buffer, 0, sizeof(GI::GIProbeData) * MIN(RenderBuffers::MAX_GIPROBES, p_gi_probe_cull_count), gi_probe_data, true);
+ if (p_gi_probes.size() > 0) {
+ RD::get_singleton()->buffer_update(gi_probe_buffer, 0, sizeof(GI::GIProbeData) * MIN((uint64_t)RenderBuffers::MAX_GIPROBES, p_gi_probes.size()), gi_probe_data, true);
}
}
-void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count) {
+void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes) {
RENDER_TIMESTAMP("Render GI");
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
@@ -1512,7 +1512,7 @@ void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_rough
push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]);
push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0];
push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
- push_constant.max_giprobes = MIN(RenderBuffers::MAX_GIPROBES, p_gi_probe_cull_count);
+ push_constant.max_giprobes = MIN((uint64_t)RenderBuffers::MAX_GIPROBES, p_gi_probes.size());
push_constant.high_quality_vct = gi_probe_quality == RS::GI_PROBE_QUALITY_HIGH;
push_constant.use_sdfgi = rb->sdfgi != nullptr;
@@ -4061,7 +4061,7 @@ bool RendererSceneRenderRD::gi_probe_needs_update(RID p_probe) const {
return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
}
-void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) {
+void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<InstanceBase *> &p_dynamic_objects) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gi_probe);
@@ -4420,7 +4420,7 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
uint32_t light_count = 0;
- if (p_update_light_instances || p_dynamic_object_count > 0) {
+ if (p_update_light_instances || p_dynamic_objects.size() > 0) {
light_count = MIN(gi_probe_max_lights, (uint32_t)p_light_instances.size());
{
@@ -4470,7 +4470,7 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
}
}
- if (gi_probe->has_dynamic_object_data || p_update_light_instances || p_dynamic_object_count) {
+ if (gi_probe->has_dynamic_object_data || p_update_light_instances || p_dynamic_objects.size()) {
// PROCESS MIPMAPS
if (gi_probe->mipmaps.size()) {
//can update mipmaps
@@ -4563,7 +4563,7 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
gi_probe->has_dynamic_object_data = false; //clear until dynamic object data is used again
- if (p_dynamic_object_count && gi_probe->dynamic_maps.size()) {
+ if (p_dynamic_objects.size() && gi_probe->dynamic_maps.size()) {
Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe);
int multiplier = gi_probe->dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z);
@@ -4577,7 +4577,7 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
AABB probe_aabb(Vector3(), octree_size);
//this could probably be better parallelized in compute..
- for (int i = 0; i < p_dynamic_object_count; i++) {
+ for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
InstanceBase *instance = p_dynamic_objects[i];
//not used, so clear
instance->depth_layer = 0;
@@ -4648,7 +4648,12 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
CameraMatrix 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]);
- _render_material(to_world_xform * xform, cm, true, &instance, 1, gi_probe->dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size));
+ if (cull_argument.size() == 0) {
+ cull_argument.push_back(nullptr);
+ }
+ cull_argument[0] = instance;
+
+ _render_material(to_world_xform * xform, cm, true, cull_argument, gi_probe->dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size));
GIProbeDynamicPushConstant push_constant;
zeromem(&push_constant, sizeof(GIProbeDynamicPushConstant));
@@ -6001,11 +6006,11 @@ RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_g
return rb->data;
}
-void RendererSceneRenderRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
- for (int i = 0; i < p_reflection_probe_cull_count; i++) {
- RID rpi = p_reflection_probe_cull_result[i];
+void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment) {
+ for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) {
+ RID rpi = p_reflections[i];
- if (i >= (int)cluster.max_reflections) {
+ if (i >= cluster.max_reflections) {
reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set
continue;
}
@@ -6056,19 +6061,19 @@ void RendererSceneRenderRD::_setup_reflections(RID *p_reflection_probe_cull_resu
reflection_probe_instance_set_render_pass(rpi, RSG::rasterizer->get_frame_number());
}
- if (p_reflection_probe_cull_count) {
- RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, MIN(cluster.max_reflections, (unsigned int)p_reflection_probe_cull_count) * sizeof(ReflectionData), cluster.reflections, true);
+ if (p_reflections.size()) {
+ RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, MIN(cluster.max_reflections, (unsigned int)p_reflections.size()) * sizeof(ReflectionData), cluster.reflections, true);
}
}
-void RendererSceneRenderRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) {
+void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) {
uint32_t light_count = 0;
r_directional_light_count = 0;
r_positional_light_count = 0;
sky_scene_state.ubo.directional_light_count = 0;
- for (int i = 0; i < p_light_cull_count; i++) {
- RID li = p_light_cull_result[i];
+ for (int i = 0; i < (int)p_lights.size(); i++) {
+ RID li = p_lights[i];
RID base = light_instance_get_base_light(li);
ERR_CONTINUE(base.is_null());
@@ -6421,15 +6426,15 @@ void RendererSceneRenderRD::_setup_lights(RID *p_light_cull_result, int p_light_
}
}
-void RendererSceneRenderRD::_setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform) {
+void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform &p_camera_inverse_xform) {
Transform uv_xform;
uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
- p_decal_count = MIN((uint32_t)p_decal_count, cluster.max_decals);
+ uint32_t decal_count = MIN((uint32_t)p_decals.size(), cluster.max_decals);
int idx = 0;
- for (int i = 0; i < p_decal_count; i++) {
- RID di = p_decal_instances[i];
+ for (uint32_t i = 0; i < decal_count; i++) {
+ RID di = p_decals[i];
RID decal = decal_instance_get_base(di);
Transform xform = decal_instance_get_transform(di);
@@ -7097,7 +7102,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::get_singleton()->compute_list_end();
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
Color clear_color;
if (p_render_buffers.is_valid()) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
@@ -7108,17 +7113,23 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
}
//assign render indices to giprobes
- for (int i = 0; i < p_gi_probe_cull_count; i++) {
- GIProbeInstance *giprobe_inst = gi_probe_instance_owner.getornull(p_gi_probe_cull_result[i]);
+ for (uint32_t i = 0; i < (uint32_t)p_gi_probes.size(); i++) {
+ GIProbeInstance *giprobe_inst = gi_probe_instance_owner.getornull(p_gi_probes[i]);
if (giprobe_inst) {
giprobe_inst->render_index = i;
}
}
+ const PagedArray<RID> *lights = &p_lights;
+ const PagedArray<RID> *reflections = &p_reflection_probes;
+ const PagedArray<RID> *gi_probes = &p_gi_probes;
+
+ PagedArray<RID> empty;
+
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
- p_light_cull_count = 0;
- p_reflection_probe_cull_count = 0;
- p_gi_probe_cull_count = 0;
+ lights = &empty;
+ reflections = &empty;
+ gi_probes = &empty;
}
cluster.builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster
@@ -7131,17 +7142,17 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
}
} else {
//do not render reflections when rendering a reflection probe
- _setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
+ _setup_reflections(*reflections, p_cam_transform.affine_inverse(), p_environment);
}
uint32_t directional_light_count = 0;
uint32_t positional_light_count = 0;
- _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows, directional_light_count, positional_light_count);
- _setup_decals(p_decal_cull_result, p_decal_cull_count, p_cam_transform.affine_inverse());
+ _setup_lights(*lights, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows, directional_light_count, positional_light_count);
+ _setup_decals(p_decals, p_cam_transform.affine_inverse());
cluster.builder.bake_cluster(); //bake to cluster
uint32_t gi_probe_count = 0;
- _setup_giprobes(p_render_buffers, p_cam_transform, p_gi_probe_cull_result, p_gi_probe_cull_count, gi_probe_count);
+ _setup_giprobes(p_render_buffers, p_cam_transform, *gi_probes, gi_probe_count);
if (p_render_buffers.is_valid()) {
bool directional_shadows = false;
@@ -7154,7 +7165,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
_update_volumetric_fog(p_render_buffers, p_environment, p_cam_projection, p_cam_transform, p_shadow_atlas, directional_light_count, directional_shadows, positional_light_count, gi_probe_count);
}
- _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, directional_light_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_lightmap_cull_result, p_lightmap_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
+ _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, directional_light_count, *gi_probes, p_lightmaps, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
if (p_render_buffers.is_valid()) {
RENDER_TIMESTAMP("Tonemap");
@@ -7167,7 +7178,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
}
}
-void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
LightInstance *light_instance = light_instance_owner.getornull(p_light);
ERR_FAIL_COND(!light_instance);
@@ -7318,7 +7329,7 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
if (render_cubemap) {
//rendering to cubemap
- _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
+ _render_shadow(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
if (finalize_cubemap) {
//reblit
atlas_rect.size.height /= 2;
@@ -7329,7 +7340,7 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
} else {
//render shadow
- _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
+ _render_shadow(render_fb, p_instances, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
//copy to atlas
if (use_linear_depth) {
@@ -7343,11 +7354,11 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
}
}
-void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {
- _render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_framebuffer, p_region);
+void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+ _render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region);
}
-void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) {
+void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances) {
//print_line("rendering region " + itos(p_region));
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -7370,7 +7381,7 @@ void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, Ins
}
//print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(rb->sdfgi->cascades[cascade].cell_size));
- _render_sdfgi(p_render_buffers, from, size, bounds, p_cull_result, p_cull_count, rb->sdfgi->render_albedo, rb->sdfgi->render_emission, rb->sdfgi->render_emission_aniso, rb->sdfgi->render_geom_facing);
+ _render_sdfgi(p_render_buffers, from, size, bounds, p_instances, rb->sdfgi->render_albedo, rb->sdfgi->render_emission, rb->sdfgi->render_emission_aniso, rb->sdfgi->render_geom_facing);
if (cascade_next != cascade) {
RENDER_TIMESTAMP(">SDFGI Update SDF");
@@ -7684,7 +7695,7 @@ void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, Ins
}
}
-void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, InstanceBase **p_cull_result, int p_cull_count) {
+void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances) {
ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));
Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
CameraMatrix cm;
@@ -7698,16 +7709,14 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider,
RID fb = storage->particles_collision_get_heightfield_framebuffer(p_collider);
- _render_particle_collider_heightfield(fb, cam_xform, cm, p_cull_result, p_cull_count);
+ _render_particle_collider_heightfield(fb, cam_xform, cm, p_instances);
}
-void RendererSceneRenderRD::render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) {
+void RendererSceneRenderRD::render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb);
ERR_FAIL_COND(!rb->sdfgi);
- ERR_FAIL_COND(p_positional_light_cull_count == 0);
-
_sdfgi_update_cascades(p_render_buffers); //need cascades updated for this
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@@ -7743,7 +7752,7 @@ void RendererSceneRenderRD::render_sdfgi_static_lights(RID p_render_buffers, uin
int idx = 0;
- for (uint32_t j = 0; j < p_positional_light_cull_count[i]; j++) {
+ for (uint32_t j = 0; j < (uint32_t)p_positional_light_cull_result[i].size(); j++) {
if (idx == SDFGI::MAX_STATIC_LIGHTS) {
break;
}
@@ -7982,8 +7991,11 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
}
}
- InstanceBase *cull = &ins;
- _render_uv2(&cull, 1, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height));
+ if (cull_argument.size() == 0) {
+ cull_argument.push_back(nullptr);
+ }
+ cull_argument[0] = &ins;
+ _render_uv2(cull_argument, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height));
TypedArray<Image> ret;
@@ -8534,6 +8546,8 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/volumetric_fog/use_filter"));
environment_set_volumetric_fog_directional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/directional_shadow_shrink"));
environment_set_volumetric_fog_positional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/positional_shadow_shrink"));
+
+ cull_argument.set_page_pool(&cull_argument_pool);
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
@@ -8598,4 +8612,5 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
RD::get_singleton()->free(shadow_sampler);
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 1b0ae61042..ded6d99e47 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -104,17 +104,17 @@ protected:
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
- void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count);
- void _setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform);
- void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
- void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, uint32_t &r_gi_probes_used);
-
- virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
- virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0;
- virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, InstanceBase **p_cull_result, int p_cull_count) = 0;
+ void _setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count);
+ void _setup_decals(const PagedArray<RID> &p_decals, const Transform &p_camera_inverse_xform);
+ void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment);
+ void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used);
+
+ virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
+ virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0;
+ virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) = 0;
virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
@@ -134,8 +134,11 @@ protected:
void _setup_sky(RID p_environment, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size);
void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
void _draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
- void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count);
+ void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes);
+ // needed for a single argument calls (material and uv2)
+ PagedArrayPool<InstanceBase *> cull_argument_pool;
+ PagedArray<InstanceBase *> cull_argument; //need this to exist
private:
RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
double time_step = 0;
@@ -1513,7 +1516,7 @@ public:
virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const;
virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const;
virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const;
- virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count);
+ virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const PagedArray<RID> &p_directional_light_instances, const RID *p_positional_light_instances, uint32_t p_positional_light_count);
RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
/* SKY API */
@@ -1822,7 +1825,7 @@ public:
RID gi_probe_instance_create(RID p_base);
void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
bool gi_probe_needs_update(RID p_probe) const;
- void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects);
+ void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::InstanceBase *> &p_dynamic_objects);
void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; }
@@ -1897,16 +1900,16 @@ public:
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
- void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
+ void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
- void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
+ void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
- void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
+ void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count);
- void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count);
+ void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances);
+ void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result);
- void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, InstanceBase **p_cull_result, int p_cull_count);
+ void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances);
virtual void set_scene_pass(uint64_t p_pass) {
scene_pass = p_pass;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 88a0859a28..1db678a441 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -30,6 +30,7 @@
#include "renderer_scene_cull.h"
+#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "rendering_server_default.h"
#include "rendering_server_globals.h"
@@ -108,8 +109,8 @@ bool RendererSceneCull::is_camera(RID p_camera) const {
/* SCENARIO API */
-void *RendererSceneCull::_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int) {
- //RendererSceneCull *self = (RendererSceneCull*)p_self;
+void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
+ RendererSceneCull *self = (RendererSceneCull *)singleton;
Instance *A = p_A;
Instance *B = p_B;
@@ -122,90 +123,66 @@ void *RendererSceneCull::_instance_pair(void *p_self, OctreeElementID, Instance
InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- InstanceLightData::PairInfo pinfo;
- pinfo.geometry = A;
- pinfo.L = geom->lighting.push_back(B);
-
- List<InstanceLightData::PairInfo>::Element *E = light->geometries.push_back(pinfo);
+ geom->lights.insert(B);
+ light->geometries.insert(A);
if (geom->can_cast_shadows) {
light->shadow_dirty = true;
}
geom->lighting_dirty = true;
- return E; //this element should make freeing faster
- } else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ } else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- InstanceReflectionProbeData::PairInfo pinfo;
- pinfo.geometry = A;
- pinfo.L = geom->reflection_probes.push_back(B);
-
- List<InstanceReflectionProbeData::PairInfo>::Element *E = reflection_probe->geometries.push_back(pinfo);
+ geom->reflection_probes.insert(B);
+ reflection_probe->geometries.insert(A);
geom->reflection_dirty = true;
- return E; //this element should make freeing faster
- } else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ } else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- InstanceDecalData::PairInfo pinfo;
- pinfo.geometry = A;
- pinfo.L = geom->decals.push_back(B);
-
- List<InstanceDecalData::PairInfo>::Element *E = decal->geometries.push_back(pinfo);
+ geom->decals.insert(B);
+ decal->geometries.insert(A);
geom->decal_dirty = true;
- return E; //this element should make freeing faster
} else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
if (A->dynamic_gi) {
- InstanceLightmapData::PairInfo pinfo;
- pinfo.geometry = A;
- pinfo.L = geom->lightmap_captures.push_back(B);
- List<InstanceLightmapData::PairInfo>::Element *E = lightmap_data->geometries.push_back(pinfo);
- ((RendererSceneCull *)p_self)->_instance_queue_update(A, false, false); //need to update capture
- return E; //this element should make freeing faster
- } else {
- return nullptr;
+ geom->lightmap_captures.insert(A);
+ lightmap_data->geometries.insert(B);
+ ((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture
}
} else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- InstanceGIProbeData::PairInfo pinfo;
- pinfo.geometry = A;
- pinfo.L = geom->gi_probes.push_back(B);
+ geom->gi_probes.insert(B);
- List<InstanceGIProbeData::PairInfo>::Element *E;
if (A->dynamic_gi) {
- E = gi_probe->dynamic_geometries.push_back(pinfo);
+ gi_probe->dynamic_geometries.insert(A);
} else {
- E = gi_probe->geometries.push_back(pinfo);
+ gi_probe->geometries.insert(A);
}
geom->gi_probes_dirty = true;
- return E; //this element should make freeing faster
-
} else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
- return gi_probe->lights.insert(A);
+ gi_probe->lights.insert(A);
} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
RSG::storage->particles_add_collision(A->base, B);
}
-
- return nullptr;
}
-void RendererSceneCull::_instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *udata) {
- //RendererSceneCull *self = (RendererSceneCull*)p_self;
+void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
+ RendererSceneCull *self = (RendererSceneCull *)singleton;
Instance *A = p_A;
Instance *B = p_B;
@@ -218,68 +195,55 @@ void RendererSceneCull::_instance_unpair(void *p_self, OctreeElementID, Instance
InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- List<InstanceLightData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightData::PairInfo>::Element *>(udata);
-
- geom->lighting.erase(E->get().L);
- light->geometries.erase(E);
+ geom->lights.erase(B);
+ light->geometries.erase(A);
if (geom->can_cast_shadows) {
light->shadow_dirty = true;
}
geom->lighting_dirty = true;
- } else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ } else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- List<InstanceReflectionProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceReflectionProbeData::PairInfo>::Element *>(udata);
-
- geom->reflection_probes.erase(E->get().L);
- reflection_probe->geometries.erase(E);
-
+ geom->reflection_probes.erase(B);
+ reflection_probe->geometries.erase(A);
geom->reflection_dirty = true;
- } else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+
+ } else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- List<InstanceDecalData::PairInfo>::Element *E = reinterpret_cast<List<InstanceDecalData::PairInfo>::Element *>(udata);
-
- geom->decals.erase(E->get().L);
- decal->geometries.erase(E);
+ geom->decals.erase(B);
+ decal->geometries.erase(A);
geom->decal_dirty = true;
} else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
- if (udata) { //only for dynamic geometries
- InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
-
- List<InstanceLightmapData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightmapData::PairInfo>::Element *>(udata);
-
- geom->lightmap_captures.erase(E->get().L);
- lightmap_data->geometries.erase(E);
- ((RendererSceneCull *)p_self)->_instance_queue_update(A, false, false); //need to update capture
+ InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+ if (A->dynamic_gi) {
+ geom->lightmap_captures.erase(B);
+ lightmap_data->geometries.erase(A);
+ ((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture
}
} else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- List<InstanceGIProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceGIProbeData::PairInfo>::Element *>(udata);
-
- geom->gi_probes.erase(E->get().L);
+ geom->gi_probes.erase(B);
if (A->dynamic_gi) {
- gi_probe->dynamic_geometries.erase(E);
+ gi_probe->dynamic_geometries.erase(A);
} else {
- gi_probe->geometries.erase(E);
+ gi_probe->geometries.erase(A);
}
geom->gi_probes_dirty = true;
} else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
- Set<Instance *>::Element *E = reinterpret_cast<Set<Instance *>::Element *>(udata);
-
- gi_probe->lights.erase(E);
+ gi_probe->lights.erase(A);
} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
RSG::storage->particles_remove_collision(A->base, B);
}
@@ -291,8 +255,6 @@ RID RendererSceneCull::scenario_create() {
RID scenario_rid = scenario_owner.make_rid(scenario);
scenario->self = scenario_rid;
- scenario->octree.set_pair_callback(_instance_pair, this);
- scenario->octree.set_unpair_callback(_instance_unpair, this);
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);
@@ -395,9 +357,8 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
if (instance->base_type != RS::INSTANCE_NONE) {
//free anything related to that base
- if (scenario && instance->octree_id) {
- scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away
- instance->octree_id = 0;
+ if (scenario && instance->indexer_id.is_valid()) {
+ _unpair_instance(instance);
}
if (instance->mesh_instance.is_valid()) {
@@ -556,9 +517,8 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {
if (instance->scenario) {
instance->scenario->instances.remove(&instance->scenario_item);
- if (instance->octree_id) {
- instance->scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away
- instance->octree_id = 0;
+ if (instance->indexer_id.is_valid()) {
+ _unpair_instance(instance);
}
switch (instance->base_type) {
@@ -715,45 +675,12 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
instance->visible = p_visible;
- switch (instance->base_type) {
- case RS::INSTANCE_LIGHT: {
- if (RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && instance->octree_id && instance->scenario) {
- instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHT, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
- }
-
- } break;
- case RS::INSTANCE_REFLECTION_PROBE: {
- if (instance->octree_id && instance->scenario) {
- instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_REFLECTION_PROBE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
- }
-
- } break;
- case RS::INSTANCE_DECAL: {
- if (instance->octree_id && instance->scenario) {
- instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_DECAL, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
- }
-
- } break;
- case RS::INSTANCE_LIGHTMAP: {
- if (instance->octree_id && instance->scenario) {
- instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHTMAP, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
- }
-
- } break;
- case RS::INSTANCE_GI_PROBE: {
- if (instance->octree_id && instance->scenario) {
- instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_GI_PROBE, p_visible ? (RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT)) : 0);
- }
-
- } break;
- case RS::INSTANCE_PARTICLES_COLLISION: {
- if (instance->octree_id && instance->scenario) {
- instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_PARTICLES_COLLISION, p_visible ? (1 << RS::INSTANCE_PARTICLES) : 0);
- }
-
- } break;
- default: {
+ if (p_visible) {
+ if (instance->scenario != nullptr) {
+ _instance_queue_update(instance, true, false);
}
+ } else if (instance->indexer_id.is_valid()) {
+ _unpair_instance(instance);
}
}
@@ -824,21 +751,21 @@ Vector<ObjectID> RendererSceneCull::instances_cull_aabb(const AABB &p_aabb, RID
const_cast<RendererSceneCull *>(this)->update_dirty_instances(); // check dirty instances before culling
- int culled = 0;
- Instance *cull[1024];
- culled = scenario->octree.cull_aabb(p_aabb, cull, 1024);
-
- for (int i = 0; i < culled; i++) {
- Instance *instance = cull[i];
- ERR_CONTINUE(!instance);
- if (instance->object_id.is_null()) {
- continue;
+ struct CullAABB {
+ Vector<ObjectID> instances;
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ if (!p_instance->object_id.is_null()) {
+ instances.push_back(p_instance->object_id);
+ }
+ return false;
}
+ };
- instances.push_back(instance->object_id);
- }
-
- return instances;
+ CullAABB cull_aabb;
+ scenario->indexers[Scenario::INDEXER_GEOMETRY].aabb_query(p_aabb, cull_aabb);
+ scenario->indexers[Scenario::INDEXER_VOLUMES].aabb_query(p_aabb, cull_aabb);
+ return cull_aabb.instances;
}
Vector<ObjectID> RendererSceneCull::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
@@ -847,21 +774,21 @@ Vector<ObjectID> RendererSceneCull::instances_cull_ray(const Vector3 &p_from, co
ERR_FAIL_COND_V(!scenario, instances);
const_cast<RendererSceneCull *>(this)->update_dirty_instances(); // check dirty instances before culling
- int culled = 0;
- Instance *cull[1024];
- culled = scenario->octree.cull_segment(p_from, p_from + p_to * 10000, cull, 1024);
-
- for (int i = 0; i < culled; i++) {
- Instance *instance = cull[i];
- ERR_CONTINUE(!instance);
- if (instance->object_id.is_null()) {
- continue;
+ struct CullRay {
+ Vector<ObjectID> instances;
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ if (!p_instance->object_id.is_null()) {
+ instances.push_back(p_instance->object_id);
+ }
+ return false;
}
+ };
- instances.push_back(instance->object_id);
- }
-
- return instances;
+ CullRay cull_ray;
+ scenario->indexers[Scenario::INDEXER_GEOMETRY].ray_query(p_from, p_to, cull_ray);
+ scenario->indexers[Scenario::INDEXER_VOLUMES].ray_query(p_from, p_to, cull_ray);
+ return cull_ray.instances;
}
Vector<ObjectID> RendererSceneCull::instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario) const {
@@ -870,22 +797,23 @@ Vector<ObjectID> RendererSceneCull::instances_cull_convex(const Vector<Plane> &p
ERR_FAIL_COND_V(!scenario, instances);
const_cast<RendererSceneCull *>(this)->update_dirty_instances(); // check dirty instances before culling
- int culled = 0;
- Instance *cull[1024];
-
- culled = scenario->octree.cull_convex(p_convex, cull, 1024);
+ Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&p_convex[0], p_convex.size());
- for (int i = 0; i < culled; i++) {
- Instance *instance = cull[i];
- ERR_CONTINUE(!instance);
- if (instance->object_id.is_null()) {
- continue;
+ struct CullConvex {
+ Vector<ObjectID> instances;
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ if (!p_instance->object_id.is_null()) {
+ instances.push_back(p_instance->object_id);
+ }
+ return false;
}
+ };
- instances.push_back(instance->object_id);
- }
-
- return instances;
+ CullConvex cull_convex;
+ scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(p_convex.ptr(), p_convex.size(), points.ptr(), points.size(), cull_convex);
+ scenario->indexers[Scenario::INDEXER_VOLUMES].convex_query(p_convex.ptr(), p_convex.size(), points.ptr(), points.size(), cull_convex);
+ return cull_convex.instances;
}
void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) {
@@ -905,10 +833,8 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
return;
}
- if (instance->octree_id != 0) {
- //remove from octree, it needs to be re-paired
- instance->scenario->octree.erase(instance->octree_id);
- instance->octree_id = 0;
+ if (instance->indexer_id.is_valid()) {
+ _unpair_instance(instance);
_instance_queue_update(instance, true, true);
}
@@ -1102,7 +1028,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
//make sure lights are updated if it casts shadow
if (geom->can_cast_shadows) {
- for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
+ for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
light->shadow_dirty = true;
}
@@ -1124,8 +1050,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data);
//erase dependencies, since no longer a lightmap
- for (List<InstanceLightmapData::PairInfo>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) {
- Instance *geom = E->get().geometry;
+ for (Set<Instance *>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) {
+ Instance *geom = E->get();
_instance_queue_update(geom, true, false);
}
}
@@ -1138,42 +1064,81 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
p_instance->transformed_aabb = new_aabb;
- if (!p_instance->scenario) {
+ if (p_instance->scenario == nullptr || !p_instance->visible || Math::is_zero_approx(p_instance->transform.basis.determinant())) {
return;
}
- if (p_instance->octree_id == 0) {
- uint32_t base_type = 1 << p_instance->base_type;
- uint32_t pairable_mask = 0;
- bool pairable = false;
-
- if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_DECAL || p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
- pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0;
- pairable = true;
+ if (!p_instance->indexer_id.is_valid()) {
+ if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+ p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].insert(p_instance->aabb, p_instance);
+ } else {
+ p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].insert(p_instance->aabb, p_instance);
}
+ }
- if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
- pairable_mask = p_instance->visible ? (1 << RS::INSTANCE_PARTICLES) : 0;
- pairable = true;
- }
+ //move instance and repair
+ pair_pass++;
+
+ PairInstances pair;
+
+ pair.instance = p_instance;
+ pair.pair_allocator = &pair_allocator;
+ pair.pair_pass = pair_pass;
+ pair.pair_mask = 0;
+
+ if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+ pair.pair_mask |= 1 << RS::INSTANCE_LIGHT;
+ pair.pair_mask |= 1 << RS::INSTANCE_GI_PROBE;
+ pair.pair_mask |= 1 << RS::INSTANCE_LIGHTMAP;
- if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
- //lights and geometries
- pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT) : 0;
- pairable = true;
+ if (pair_volumes_to_mesh) {
+ pair.pair_mask |= 1 << RS::INSTANCE_DECAL;
+ pair.pair_mask |= 1 << RS::INSTANCE_REFLECTION_PROBE;
+ }
+ pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
+ } else if (p_instance->base_type == RS::INSTANCE_LIGHT) {
+ pair.pair_mask |= RS::INSTANCE_GEOMETRY_MASK;
+ pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
+
+ if (RSG::storage->light_get_bake_mode(p_instance->base) == RS::LIGHT_BAKE_DYNAMIC) {
+ pair.pair_mask |= (1 << RS::INSTANCE_GI_PROBE);
+ pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
}
+ } else if (pair_volumes_to_mesh && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_DECAL)) {
+ pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;
+ pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
+ } else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
+ pair.pair_mask = (1 << RS::INSTANCE_PARTICLES);
+ pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
+ } else if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
+ //lights and geometries
+ pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT);
+ pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
+ pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
+ }
- // not inside octree
- p_instance->octree_id = p_instance->scenario->octree.create(p_instance, new_aabb, 0, pairable, base_type, pairable_mask);
+ pair.pair();
+}
- } else {
- /*
- if (new_aabb==p_instance->data.transformed_aabb)
- return;
- */
+void RendererSceneCull::_unpair_instance(Instance *p_instance) {
+ if (!p_instance->indexer_id.is_valid()) {
+ return; //nothing to do
+ }
+
+ while (p_instance->pairs.first()) {
+ InstancePair *pair = p_instance->pairs.first()->self();
+ Instance *other_instance = p_instance == pair->a ? pair->b : pair->a;
+ _instance_unpair(p_instance, other_instance);
+ pair_allocator.free(pair);
+ }
- p_instance->scenario->octree.move(p_instance->octree_id, new_aabb);
+ if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+ p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].remove(p_instance->indexer_id);
+ } else {
+ p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].remove(p_instance->indexer_id);
}
+
+ p_instance->indexer_id = DynamicBVH::ID();
}
void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
@@ -1264,7 +1229,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
float accum_blend = 0.0;
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
- for (List<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) {
+ for (Set<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) {
Instance *lightmap = E->get();
bool interior = RSG::storage->lightmap_is_interior(lightmap->base);
@@ -1358,8 +1323,26 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) {
//optimize min/max
+
Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
- int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
+ Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());
+
+ geometry_instances_to_shadow_render.clear();
+
+ struct CullConvex {
+ PagedArray<RendererSceneRender::InstanceBase *> *result;
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ result->push_back(p_instance);
+ return false;
+ }
+ };
+
+ CullConvex cull_convex;
+ cull_convex.result = &geometry_instances_to_shadow_render;
+
+ p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);
+
Plane base(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2));
//check distance max and min
@@ -1367,7 +1350,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
real_t z_max = -1e20;
real_t z_min = 1e20;
- for (int i = 0; i < cull_count; i++) {
+ for (int i = 0; i < (int)instance_shadow_cull_result.size(); i++) {
Instance *instance = instance_shadow_cull_result[i];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
continue;
@@ -1583,20 +1566,34 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
light_frustum_planes.write[4] = Plane(z_vec, z_max + 1e6);
light_frustum_planes.write[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed
- int cull_count = p_scenario->octree.cull_convex(light_frustum_planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
+ geometry_instances_to_shadow_render.clear();
+ instance_shadow_cull_result.clear();
+
+ Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&light_frustum_planes[0], light_frustum_planes.size());
+
+ struct CullConvex {
+ PagedArray<Instance *> *result;
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ result->push_back(p_instance);
+ return false;
+ }
+ };
+
+ CullConvex cull_convex;
+ cull_convex.result = &instance_shadow_cull_result;
+
+ p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(light_frustum_planes.ptr(), light_frustum_planes.size(), points.ptr(), points.size(), cull_convex);
// a pre pass will need to be needed to determine the actual z-near to be used
Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
real_t cull_max = 0;
- for (int j = 0; j < cull_count; j++) {
+ for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
real_t min, max;
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
- cull_count--;
- SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
- j--;
continue;
}
@@ -1610,6 +1607,8 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
if (instance->mesh_instance.is_valid()) {
RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
}
+
+ geometry_instances_to_shadow_render.push_back(instance);
}
if (cull_max > z_max) {
@@ -1712,7 +1711,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
RSG::storage->update_mesh_instances();
- scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count, camera_plane, p_cam_projection.get_lod_multiplier(), p_screen_lod_threshold);
+ scene_render->render_shadow(light->instance, p_shadow_atlas, i, geometry_instances_to_shadow_render, camera_plane, p_cam_projection.get_lod_multiplier(), p_screen_lod_threshold);
}
} break;
@@ -1736,15 +1735,31 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
planes.write[5] = light_transform.xform(Plane(Vector3(0, 0, -z), 0));
- int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
+ geometry_instances_to_shadow_render.clear();
+ instance_shadow_cull_result.clear();
+
+ Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());
+
+ struct CullConvex {
+ PagedArray<Instance *> *result;
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ result->push_back(p_instance);
+ return false;
+ }
+ };
+
+ CullConvex cull_convex;
+ cull_convex.result = &instance_shadow_cull_result;
+
+ p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);
+
Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
- for (int j = 0; j < cull_count; j++) {
+ for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
- cull_count--;
- SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
- j--;
+ continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
animated_material_found = true;
@@ -1757,12 +1772,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
+
+ geometry_instances_to_shadow_render.push_back(instance);
}
RSG::storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
- scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count);
+ scene_render->render_shadow(light->instance, p_shadow_atlas, i, geometry_instances_to_shadow_render);
}
} else { //shadow cube
@@ -1795,15 +1812,31 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
Vector<Plane> planes = cm.get_projection_planes(xform);
- int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
+ geometry_instances_to_shadow_render.clear();
+ instance_shadow_cull_result.clear();
+
+ Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());
+
+ struct CullConvex {
+ PagedArray<Instance *> *result;
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ result->push_back(p_instance);
+ return false;
+ }
+ };
+
+ CullConvex cull_convex;
+ cull_convex.result = &instance_shadow_cull_result;
+
+ p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);
Plane near_plane(xform.origin, -xform.basis.get_axis(2));
- for (int j = 0; j < cull_count; j++) {
+
+ for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
- cull_count--;
- SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
- j--;
+ continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
animated_material_found = true;
@@ -1814,11 +1847,13 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
+
+ geometry_instances_to_shadow_render.push_back(instance);
}
RSG::storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
- scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count);
+ scene_render->render_shadow(light->instance, p_shadow_atlas, i, geometry_instances_to_shadow_render);
}
//restore the regular DP matrix
@@ -1836,15 +1871,32 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
cm.set_perspective(angle * 2.0, 1.0, 0.01, radius);
Vector<Plane> planes = cm.get_projection_planes(light_transform);
- int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
+
+ geometry_instances_to_shadow_render.clear();
+ instance_shadow_cull_result.clear();
+
+ Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());
+
+ struct CullConvex {
+ PagedArray<Instance *> *result;
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ result->push_back(p_instance);
+ return false;
+ }
+ };
+
+ CullConvex cull_convex;
+ cull_convex.result = &instance_shadow_cull_result;
+
+ p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex);
Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
- for (int j = 0; j < cull_count; j++) {
+
+ for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
- cull_count--;
- SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
- j--;
+ continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
animated_material_found = true;
@@ -1856,12 +1908,13 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
+ geometry_instances_to_shadow_render.push_back(instance);
}
RSG::storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
- scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count);
+ scene_render->render_shadow(light->instance, p_shadow_atlas, 0, geometry_instances_to_shadow_render);
} break;
}
@@ -2028,14 +2081,17 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2).normalized());
float z_far = p_cam_projection.get_z_far();
+ instance_cull_result.clear();
/* STEP 2 - CULL */
- instance_cull_count = scenario->octree.cull_convex(planes, instance_cull_result, MAX_INSTANCE_CULL);
- light_cull_count = 0;
+ {
+ CullResult cull_result;
+ cull_result.result = &instance_cull_result;
+
+ Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size());
- reflection_probe_cull_count = 0;
- decal_cull_count = 0;
- gi_probe_cull_count = 0;
- lightmap_cull_count = 0;
+ scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_result);
+ scenario->indexers[Scenario::INDEXER_VOLUMES].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_result);
+ }
//light_samplers_culled=0;
@@ -2053,83 +2109,65 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
uint64_t frame_number = RSG::rasterizer->get_frame_number();
float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
- for (int i = 0; i < instance_cull_count; i++) {
- Instance *ins = instance_cull_result[i];
+ geometry_instances_to_render.clear();
+ light_cull_result.clear();
+ lightmap_cull_result.clear();
+ reflection_probe_instance_cull_result.clear();
+ light_instance_cull_result.clear();
+ gi_probe_instance_cull_result.clear();
+ lightmap_cull_result.clear();
+ decal_instance_cull_result.clear();
- bool keep = false;
+ for (uint32_t i = 0; i < (uint32_t)instance_cull_result.size(); i++) {
+ Instance *ins = instance_cull_result[i];
if ((camera_layer_mask & ins->layer_mask) == 0) {
//failure
- } else if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) {
- if (light_cull_count < MAX_LIGHTS_CULLED) {
- InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
-
- if (!light->geometries.empty()) {
- //do not add this light if no geometry is affected by it..
- light_cull_result[light_cull_count] = ins;
- light_instance_cull_result[light_cull_count] = light->instance;
- if (p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(ins->base)) {
- scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later
- }
+ } else if (ins->base_type == RS::INSTANCE_LIGHT) {
+ InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
- light_cull_count++;
- }
+ light_cull_result.push_back(ins);
+ light_instance_cull_result.push_back(light->instance);
+ if (p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(ins->base)) {
+ scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later
}
- } else if (ins->base_type == RS::INSTANCE_REFLECTION_PROBE && ins->visible) {
- if (reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) {
- InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(ins->base_data);
-
- if (p_reflection_probe != reflection_probe->instance) {
- //avoid entering The Matrix
-
- if (!reflection_probe->geometries.empty()) {
- //do not add this light if no geometry is affected by it..
- if (reflection_probe->reflection_dirty || scene_render->reflection_probe_instance_needs_redraw(reflection_probe->instance)) {
- if (!reflection_probe->update_list.in_list()) {
- reflection_probe->render_step = 0;
- reflection_probe_render_list.add_last(&reflection_probe->update_list);
- }
+ } else if (ins->base_type == RS::INSTANCE_REFLECTION_PROBE) {
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(ins->base_data);
- reflection_probe->reflection_dirty = false;
- }
+ if (p_reflection_probe != reflection_probe->instance) {
+ //avoid entering The Matrix
- if (scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) {
- reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance;
- reflection_probe_cull_count++;
- }
+ if (reflection_probe->reflection_dirty || scene_render->reflection_probe_instance_needs_redraw(reflection_probe->instance)) {
+ if (!reflection_probe->update_list.in_list()) {
+ reflection_probe->render_step = 0;
+ reflection_probe_render_list.add_last(&reflection_probe->update_list);
}
+
+ reflection_probe->reflection_dirty = false;
}
- }
- } else if (ins->base_type == RS::INSTANCE_DECAL && ins->visible) {
- if (decal_cull_count < MAX_DECALS_CULLED) {
- InstanceDecalData *decal = static_cast<InstanceDecalData *>(ins->base_data);
-
- if (!decal->geometries.empty()) {
- //do not add this decal if no geometry is affected by it..
- decal_instance_cull_result[decal_cull_count] = decal->instance;
- decal_cull_count++;
+
+ if (scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) {
+ reflection_probe_instance_cull_result.push_back(reflection_probe->instance);
}
}
+ } else if (ins->base_type == RS::INSTANCE_DECAL) {
+ InstanceDecalData *decal = static_cast<InstanceDecalData *>(ins->base_data);
+
+ decal_instance_cull_result.push_back(decal->instance);
- } else if (ins->base_type == RS::INSTANCE_GI_PROBE && ins->visible) {
+ } else if (ins->base_type == RS::INSTANCE_GI_PROBE) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(ins->base_data);
if (!gi_probe->update_element.in_list()) {
gi_probe_update_list.add(&gi_probe->update_element);
}
- if (gi_probe_cull_count < MAX_GI_PROBES_CULLED) {
- gi_probe_instance_cull_result[gi_probe_cull_count] = gi_probe->probe_instance;
- gi_probe_cull_count++;
- }
- } else if (ins->base_type == RS::INSTANCE_LIGHTMAP && ins->visible) {
- if (lightmap_cull_count < MAX_LIGHTMAPS_CULLED) {
- lightmap_cull_result[lightmap_cull_count] = ins;
- lightmap_cull_count++;
- }
+ gi_probe_instance_cull_result.push_back(gi_probe->probe_instance);
- } else if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
- keep = true;
+ } else if (ins->base_type == RS::INSTANCE_LIGHTMAP) {
+ lightmap_cull_result.push_back(ins);
+ } else if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
+ bool keep = true;
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(ins->base_data);
@@ -2150,12 +2188,12 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
}
}
- if (geom->lighting_dirty) {
+ if (pair_volumes_to_mesh && geom->lighting_dirty) {
int l = 0;
//only called when lights AABB enter/exit this geometry
- ins->light_instances.resize(geom->lighting.size());
+ ins->light_instances.resize(geom->lights.size());
- for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
+ for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
ins->light_instances.write[l++] = light->instance;
@@ -2164,12 +2202,12 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
geom->lighting_dirty = false;
}
- if (geom->reflection_dirty) {
+ if (pair_volumes_to_mesh && geom->reflection_dirty) {
int l = 0;
//only called when reflection probe AABB enter/exit this geometry
ins->reflection_probe_instances.resize(geom->reflection_probes.size());
- for (List<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
+ for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
ins->reflection_probe_instances.write[l++] = reflection_probe->instance;
@@ -2183,7 +2221,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
//only called when reflection probe AABB enter/exit this geometry
ins->gi_probe_instances.resize(geom->gi_probes.size());
- for (List<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) {
+ for (Set<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data);
ins->gi_probe_instances.write[l++] = gi_probe->probe_instance;
@@ -2206,17 +2244,15 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
ins->depth = near_plane.distance_to(ins->transform.origin);
ins->depth_layer = CLAMP(int(ins->depth * 16 / z_far), 0, 15);
- }
- if (!keep) {
- // remove, no reason to keep
- instance_cull_count--;
- SWAP(instance_cull_result[i], instance_cull_result[instance_cull_count]);
- i--;
- ins->last_render_pass = 0; // make invalid
- } else {
- ins->last_render_pass = render_pass;
+ if (keep) {
+ geometry_instances_to_render.push_back(ins);
+ ins->last_render_pass = render_pass;
+ } else {
+ ins->last_render_pass = 0; // make invalid
+ }
}
+
ins->last_frame_pass = frame_number;
}
@@ -2224,19 +2260,13 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
/* STEP 5 - PROCESS LIGHTS */
- RID *directional_light_ptr = &light_instance_cull_result[light_cull_count];
- directional_light_count = 0;
+ directional_light_cull_result.clear();
// directional lights
{
- Instance **lights_with_shadow = (Instance **)alloca(sizeof(Instance *) * scenario->directional_lights.size());
- int directional_shadow_count = 0;
+ directional_shadow_cull_result.clear();
for (List<Instance *>::Element *E = scenario->directional_lights.front(); E; E = E->next()) {
- if (light_cull_count + directional_light_count >= MAX_LIGHTS_CULLED) {
- break;
- }
-
if (!E->get()->visible) {
continue;
}
@@ -2247,19 +2277,21 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
if (light) {
if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base) && !(RSG::storage->light_get_type(E->get()->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_is_sky_only(E->get()->base))) {
- lights_with_shadow[directional_shadow_count++] = E->get();
+ directional_shadow_cull_result.push_back(E->get());
}
//add to list
- directional_light_ptr[directional_light_count++] = light->instance;
+ directional_light_cull_result.push_back(light->instance);
}
+
+ light_instance_cull_result.push_back(light->instance);
}
- scene_render->set_directional_shadow_count(directional_shadow_count);
+ scene_render->set_directional_shadow_count(directional_shadow_cull_result.size());
- for (int i = 0; i < directional_shadow_count; i++) {
+ for (uint32_t i = 0; i < (uint32_t)directional_shadow_cull_result.size(); i++) {
RENDER_TIMESTAMP(">Rendering Directional Light " + itos(i));
- _light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
+ _light_instance_update_shadow(directional_shadow_cull_result[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
RENDER_TIMESTAMP("<Rendering Directional Light " + itos(i));
}
@@ -2269,7 +2301,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
//SortArray<Instance*,_InstanceLightsort> sorter;
//sorter.sort(light_cull_result,light_cull_count);
- for (int i = 0; i < light_cull_count; i++) {
+ for (uint32_t i = 0; i < (uint32_t)light_cull_result.size(); i++) {
Instance *ins = light_cull_result[i];
if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) {
@@ -2368,8 +2400,9 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
if (p_render_buffers.is_valid()) {
uint32_t cascade_index[8];
- uint32_t cascade_sizes[8];
- const RID *cascade_ptrs[8];
+ for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
+ sdfgi_cascade_lights[i].clear();
+ }
uint32_t cascade_count = 0;
uint32_t sdfgi_light_cull_count = 0;
@@ -2379,30 +2412,36 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
uint32_t region_cascade = scene_render->sdfgi_get_pending_region_cascade(p_render_buffers, i);
if (region_cascade != prev_cascade) {
- cascade_sizes[cascade_count] = 0;
cascade_index[cascade_count] = region_cascade;
- cascade_ptrs[cascade_count] = &sdfgi_light_cull_result[sdfgi_light_cull_count];
cascade_count++;
sdfgi_light_cull_pass++;
prev_cascade = region_cascade;
}
- uint32_t sdfgi_cull_count = scenario->octree.cull_aabb(region, instance_shadow_cull_result, MAX_INSTANCE_CULL);
+ instance_sdfgi_cull_result.clear();
+ {
+ CullResult cull_result;
+ cull_result.result = &instance_sdfgi_cull_result;
+
+ scenario->indexers[Scenario::INDEXER_GEOMETRY].aabb_query(region, cull_result);
+ scenario->indexers[Scenario::INDEXER_VOLUMES].aabb_query(region, cull_result);
+ }
- for (uint32_t j = 0; j < sdfgi_cull_count; j++) {
- Instance *ins = instance_shadow_cull_result[j];
+ geometry_instances_to_sdfgi_render.clear();
+
+ for (uint32_t j = 0; j < (uint32_t)instance_sdfgi_cull_result.size(); j++) {
+ Instance *ins = instance_sdfgi_cull_result[j];
bool keep = false;
- if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) {
+ if (ins->base_type == RS::INSTANCE_LIGHT) {
InstanceLightData *instance_light = (InstanceLightData *)ins->base_data;
if (instance_light->bake_mode != RS::LIGHT_BAKE_STATIC || region_cascade > instance_light->max_sdfgi_cascade) {
continue;
}
- if (sdfgi_light_cull_pass != instance_light->sdfgi_cascade_light_pass && sdfgi_light_cull_count < MAX_LIGHTS_CULLED) {
+ if (sdfgi_light_cull_pass != instance_light->sdfgi_cascade_light_pass) {
instance_light->sdfgi_cascade_light_pass = sdfgi_light_cull_pass;
- sdfgi_light_cull_result[sdfgi_light_cull_count++] = instance_light->instance;
- cascade_sizes[cascade_count - 1]++;
+ sdfgi_cascade_lights[cascade_count - 1].push_back(instance_light->instance);
}
} else if ((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
if (ins->baked_light) {
@@ -2413,25 +2452,22 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
}
}
- if (!keep) {
- // remove, no reason to keep
- sdfgi_cull_count--;
- SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[sdfgi_cull_count]);
- j--;
+ if (keep) {
+ geometry_instances_to_sdfgi_render.push_back(ins);
}
}
RSG::storage->update_mesh_instances();
- scene_render->render_sdfgi(p_render_buffers, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, sdfgi_cull_count);
+ scene_render->render_sdfgi(p_render_buffers, i, geometry_instances_to_sdfgi_render);
//have to save updated cascades, then update static lights.
}
if (sdfgi_light_cull_count) {
- scene_render->render_sdfgi_static_lights(p_render_buffers, cascade_count, cascade_index, cascade_ptrs, cascade_sizes);
+ scene_render->render_sdfgi_static_lights(p_render_buffers, cascade_count, cascade_index, sdfgi_cascade_lights);
}
- scene_render->sdfgi_update_probes(p_render_buffers, p_environment, directional_light_ptr, directional_light_count, scenario->dynamic_lights.ptr(), scenario->dynamic_lights.size());
+ scene_render->sdfgi_update_probes(p_render_buffers, p_environment, directional_light_cull_result, scenario->dynamic_lights.ptr(), scenario->dynamic_lights.size());
}
}
@@ -2468,7 +2504,7 @@ void RendererSceneCull::_render_scene(RID p_render_buffers, const Transform p_ca
/* PROCESS GEOMETRY AND DRAW SCENE */
RENDER_TIMESTAMP("Render Scene ");
- scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RendererSceneRender::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RendererSceneRender::InstanceBase **)lightmap_cull_result, lightmap_cull_count, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold);
+ scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, geometry_instances_to_render, light_instance_cull_result, reflection_probe_instance_cull_result, gi_probe_instance_cull_result, decal_instance_cull_result, lightmap_cull_result, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold);
}
void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
@@ -2483,7 +2519,7 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
environment = scenario->fallback_environment;
}
RENDER_TIMESTAMP("Render Empty Scene ");
- scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0, 0);
+ scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, PagedArray<RendererSceneRender::InstanceBase *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RendererSceneRender::InstanceBase *>(), RID(), RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0, 0);
#endif
}
@@ -2758,35 +2794,34 @@ void RendererSceneCull::render_probes() {
update_lights = true;
}
- instance_cull_count = 0;
- for (List<InstanceGIProbeData::PairInfo>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) {
- if (instance_cull_count < MAX_INSTANCE_CULL) {
- Instance *ins = E->get().geometry;
- if (!ins->visible) {
- continue;
- }
- InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data;
+ geometry_instances_to_render.clear();
- if (geom->gi_probes_dirty) {
- //giprobes may be dirty, so update
- int l = 0;
- //only called when reflection probe AABB enter/exit this geometry
- ins->gi_probe_instances.resize(geom->gi_probes.size());
+ for (Set<Instance *>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) {
+ Instance *ins = E->get();
+ if (!ins->visible) {
+ continue;
+ }
+ InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data;
- for (List<Instance *>::Element *F = geom->gi_probes.front(); F; F = F->next()) {
- InstanceGIProbeData *gi_probe2 = static_cast<InstanceGIProbeData *>(F->get()->base_data);
+ if (geom->gi_probes_dirty) {
+ //giprobes may be dirty, so update
+ int l = 0;
+ //only called when reflection probe AABB enter/exit this geometry
+ ins->gi_probe_instances.resize(geom->gi_probes.size());
- ins->gi_probe_instances.write[l++] = gi_probe2->probe_instance;
- }
+ for (Set<Instance *>::Element *F = geom->gi_probes.front(); F; F = F->next()) {
+ InstanceGIProbeData *gi_probe2 = static_cast<InstanceGIProbeData *>(F->get()->base_data);
- geom->gi_probes_dirty = false;
+ ins->gi_probe_instances.write[l++] = gi_probe2->probe_instance;
}
- instance_cull_result[instance_cull_count++] = E->get().geometry;
+ geom->gi_probes_dirty = false;
}
+
+ geometry_instances_to_render.push_back(E->get());
}
- scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, instance_cull_count, (RendererSceneRender::InstanceBase **)instance_cull_result);
+ scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, geometry_instances_to_render);
gi_probe_update_list.remove(gi_probe);
@@ -2800,16 +2835,32 @@ void RendererSceneCull::render_particle_colliders() {
if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) {
//update heightfield
- int cull_count = hfpc->scenario->octree.cull_aabb(hfpc->transformed_aabb, instance_cull_result, MAX_INSTANCE_CULL); //@TODO: cull mask missing
- for (int i = 0; i < cull_count; i++) {
+ instance_cull_result.clear();
+ geometry_instances_to_render.clear();
+
+ struct CullAABB {
+ PagedArray<Instance *> *result;
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ result->push_back(p_instance);
+ return false;
+ }
+ };
+
+ CullAABB cull_aabb;
+ cull_aabb.result = &instance_cull_result;
+ hfpc->scenario->indexers[Scenario::INDEXER_GEOMETRY].aabb_query(hfpc->transformed_aabb, cull_aabb);
+ hfpc->scenario->indexers[Scenario::INDEXER_VOLUMES].aabb_query(hfpc->transformed_aabb, cull_aabb);
+
+ for (int i = 0; i < (int)instance_cull_result.size(); i++) {
Instance *instance = instance_cull_result[i];
- if (!instance->visible || !((1 << instance->base_type) & (RS::INSTANCE_GEOMETRY_MASK & (~(1 << RS::INSTANCE_PARTICLES))))) { //all but particles to avoid self collision
- cull_count--;
- SWAP(instance_cull_result[i], instance_cull_result[cull_count]);
+ if (!instance || !((1 << instance->base_type) & (RS::INSTANCE_GEOMETRY_MASK & (~(1 << RS::INSTANCE_PARTICLES))))) { //all but particles to avoid self collision
+ continue;
}
+ geometry_instances_to_render.push_back(instance);
}
- scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, (RendererSceneRender::InstanceBase **)instance_cull_result, cull_count);
+ scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, geometry_instances_to_render);
}
heightfield_particle_colliders_update_list.erase(heightfield_particle_colliders_update_list.front());
}
@@ -3009,7 +3060,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
if (can_cast_shadows != geom->can_cast_shadows) {
//ability to cast shadows change, let lights now
- for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
+ for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
light->shadow_dirty = true;
}
@@ -3060,6 +3111,12 @@ void RendererSceneCull::update_dirty_instances() {
}
void RendererSceneCull::update() {
+ //optimize bvhs
+ for (uint32_t i = 0; i < scenario_owner.get_rid_count(); i++) {
+ Scenario *s = scenario_owner.get_ptr_by_index(i);
+ s->indexers[Scenario::INDEXER_GEOMETRY].optimize_incremental(indexer_update_iterations);
+ s->indexers[Scenario::INDEXER_VOLUMES].optimize_incremental(indexer_update_iterations);
+ }
scene_render->update();
update_dirty_instances();
render_particle_colliders();
@@ -3130,7 +3187,51 @@ RendererSceneCull *RendererSceneCull::singleton = nullptr;
RendererSceneCull::RendererSceneCull() {
render_pass = 1;
singleton = this;
+ pair_volumes_to_mesh = false;
+
+ instance_cull_result.set_page_pool(&instance_cull_page_pool);
+ instance_shadow_cull_result.set_page_pool(&instance_cull_page_pool);
+ instance_sdfgi_cull_result.set_page_pool(&instance_cull_page_pool);
+ light_cull_result.set_page_pool(&instance_cull_page_pool);
+ directional_shadow_cull_result.set_page_pool(&instance_cull_page_pool);
+
+ geometry_instances_to_render.set_page_pool(&base_instance_cull_page_pool);
+ geometry_instances_to_shadow_render.set_page_pool(&base_instance_cull_page_pool);
+ geometry_instances_to_sdfgi_render.set_page_pool(&base_instance_cull_page_pool);
+ lightmap_cull_result.set_page_pool(&base_instance_cull_page_pool);
+
+ reflection_probe_instance_cull_result.set_page_pool(&rid_cull_page_pool);
+ light_instance_cull_result.set_page_pool(&rid_cull_page_pool);
+ directional_light_cull_result.set_page_pool(&rid_cull_page_pool);
+ gi_probe_instance_cull_result.set_page_pool(&rid_cull_page_pool);
+ decal_instance_cull_result.set_page_pool(&rid_cull_page_pool);
+
+ for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
+ sdfgi_cascade_lights[i].set_page_pool(&rid_cull_page_pool);
+ }
+
+ indexer_update_iterations = GLOBAL_GET("rendering/spatial_indexer/update_iterations_per_frame");
}
RendererSceneCull::~RendererSceneCull() {
+ instance_cull_result.reset();
+ instance_shadow_cull_result.reset();
+ instance_sdfgi_cull_result.reset();
+ light_cull_result.reset();
+ directional_shadow_cull_result.reset();
+
+ geometry_instances_to_render.reset();
+ geometry_instances_to_shadow_render.reset();
+ geometry_instances_to_sdfgi_render.reset();
+ lightmap_cull_result.reset();
+
+ reflection_probe_instance_cull_result.reset();
+ light_instance_cull_result.reset();
+ directional_light_cull_result.reset();
+ gi_probe_instance_cull_result.reset();
+ decal_instance_cull_result.reset();
+
+ for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
+ sdfgi_cascade_lights[i].reset();
+ }
}
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 051919314e..8bf262d7c0 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -34,30 +34,25 @@
#include "core/templates/pass_func.h"
#include "servers/rendering/renderer_compositor.h"
+#include "core/math/dynamic_bvh.h"
#include "core/math/geometry_3d.h"
#include "core/math/octree.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
#include "core/templates/local_vector.h"
+#include "core/templates/paged_allocator.h"
+#include "core/templates/paged_array.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/xr/xr_interface.h"
-
class RendererSceneCull : public RendererScene {
public:
RendererSceneRender *scene_render;
enum {
- MAX_INSTANCE_CULL = 65536,
- MAX_LIGHTS_CULLED = 4096,
- MAX_REFLECTION_PROBES_CULLED = 4096,
- MAX_DECALS_CULLED = 4096,
- MAX_GI_PROBES_CULLED = 4096,
- MAX_ROOM_CULL = 32,
- MAX_LIGHTMAPS_CULLED = 4096,
- MAX_EXTERIOR_PORTALS = 128,
+ SDFGI_MAX_CASCADES = 8
};
uint64_t render_pass;
@@ -114,11 +109,17 @@ public:
struct Instance;
struct Scenario {
+ enum IndexerType {
+ INDEXER_GEOMETRY, //for geometry
+ INDEXER_VOLUMES, //for everything else
+ INDEXER_MAX
+ };
+
+ DynamicBVH indexers[INDEXER_MAX];
+
RS::ScenarioDebugMode debug;
RID self;
- Octree<Instance, true> octree;
-
List<Instance *> directional_lights;
RID environment;
RID fallback_environment;
@@ -130,13 +131,19 @@ public:
LocalVector<RID> dynamic_lights;
- Scenario() { debug = RS::SCENARIO_DEBUG_DISABLED; }
+ Scenario() {
+ indexers[INDEXER_GEOMETRY].set_index(INDEXER_GEOMETRY);
+ indexers[INDEXER_VOLUMES].set_index(INDEXER_VOLUMES);
+ debug = RS::SCENARIO_DEBUG_DISABLED;
+ }
};
+ int indexer_update_iterations = 0;
+
mutable RID_PtrOwner<Scenario> scenario_owner;
- static void *_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int);
- static void _instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *);
+ static void _instance_pair(Instance *p_A, Instance *p_B);
+ static void _instance_unpair(Instance *p_A, Instance *p_B);
static void _instance_update_mesh_instance(Instance *p_instance);
@@ -152,6 +159,17 @@ public:
/* INSTANCING API */
+ struct InstancePair {
+ Instance *a;
+ Instance *b;
+ SelfList<InstancePair> list_a;
+ SelfList<InstancePair> list_b;
+ InstancePair() :
+ list_a(this), list_b(this) {}
+ };
+
+ PagedAllocator<InstancePair> pair_allocator;
+
struct InstanceBaseData {
virtual ~InstanceBaseData() {}
};
@@ -159,7 +177,7 @@ public:
struct Instance : RendererSceneRender::InstanceBase {
RID self;
//scenario stuff
- OctreeElementID octree_id;
+ DynamicBVH::ID indexer_id;
Scenario *scenario;
SelfList<Instance> scenario_item;
@@ -188,6 +206,9 @@ public:
InstanceBaseData *base_data;
+ SelfList<InstancePair>::List pairs;
+ uint64_t pair_check;
+
virtual void dependency_deleted(RID p_dependency) {
if (p_dependency == base) {
singleton->instance_set_base(self, RID());
@@ -205,7 +226,6 @@ public:
Instance() :
scenario_item(this),
update_item(this) {
- octree_id = 0;
scenario = nullptr;
update_aabb = false;
@@ -226,6 +246,8 @@ public:
base_data = nullptr;
custom_aabb = nullptr;
+
+ pair_check = 0;
}
~Instance() {
@@ -242,21 +264,21 @@ public:
void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
struct InstanceGeometryData : public InstanceBaseData {
- List<Instance *> lighting;
+ Set<Instance *> lights;
bool lighting_dirty;
bool can_cast_shadows;
bool material_is_animated;
- List<Instance *> decals;
+ Set<Instance *> decals;
bool decal_dirty;
- List<Instance *> reflection_probes;
+ Set<Instance *> reflection_probes;
bool reflection_dirty;
- List<Instance *> gi_probes;
+ Set<Instance *> gi_probes;
bool gi_probes_dirty;
- List<Instance *> lightmap_captures;
+ Set<Instance *> lightmap_captures;
InstanceGeometryData() {
lighting_dirty = false;
@@ -271,11 +293,7 @@ public:
struct InstanceReflectionProbeData : public InstanceBaseData {
Instance *owner;
- struct PairInfo {
- List<Instance *>::Element *L; //reflection iterator in geometry
- Instance *geometry;
- };
- List<PairInfo> geometries;
+ Set<Instance *> geometries;
RID instance;
bool reflection_dirty;
@@ -294,11 +312,7 @@ public:
Instance *owner;
RID instance;
- struct PairInfo {
- List<Instance *>::Element *L; //reflection iterator in geometry
- Instance *geometry;
- };
- List<PairInfo> geometries;
+ Set<Instance *> geometries;
InstanceDecalData() {
}
@@ -307,18 +321,13 @@ public:
SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
struct InstanceLightData : public InstanceBaseData {
- struct PairInfo {
- List<Instance *>::Element *L; //light iterator in geometry
- Instance *geometry;
- };
-
RID instance;
uint64_t last_version;
List<Instance *>::Element *D; // directional light in scenario
bool shadow_dirty;
- List<PairInfo> geometries;
+ Set<Instance *> geometries;
Instance *baked_light;
@@ -339,13 +348,8 @@ public:
struct InstanceGIProbeData : public InstanceBaseData {
Instance *owner;
- struct PairInfo {
- List<Instance *>::Element *L; //gi probe iterator in geometry
- Instance *geometry;
- };
-
- List<PairInfo> geometries;
- List<PairInfo> dynamic_geometries;
+ Set<Instance *> geometries;
+ Set<Instance *> dynamic_geometries;
Set<Instance *> lights;
@@ -383,40 +387,110 @@ public:
SelfList<InstanceGIProbeData>::List gi_probe_update_list;
struct InstanceLightmapData : public InstanceBaseData {
- struct PairInfo {
- List<Instance *>::Element *L; //iterator in geometry
- Instance *geometry;
- };
- List<PairInfo> geometries;
-
+ Set<Instance *> geometries;
Set<Instance *> users;
InstanceLightmapData() {
}
};
+ uint64_t pair_pass = 1;
+
+ struct PairInstances {
+ Instance *instance = nullptr;
+ PagedAllocator<InstancePair> *pair_allocator = nullptr;
+ SelfList<InstancePair>::List pairs_found;
+ DynamicBVH *bvh = nullptr;
+ DynamicBVH *bvh2 = nullptr; //some may need to cull in two
+ uint32_t pair_mask;
+ uint64_t pair_pass;
+
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ if (instance != p_instance && instance->transformed_aabb.intersects(p_instance->transformed_aabb) && (pair_mask & (1 << p_instance->base_type))) {
+ //test is more coarse in indexer
+ p_instance->pair_check = pair_pass;
+ InstancePair *pair = pair_allocator->alloc();
+ pair->a = instance;
+ pair->b = p_instance;
+ pairs_found.add(&pair->list_a);
+ }
+ return false;
+ }
+
+ void pair() {
+ if (bvh) {
+ bvh->aabb_query(instance->transformed_aabb, *this);
+ }
+ if (bvh2) {
+ bvh2->aabb_query(instance->transformed_aabb, *this);
+ }
+ while (instance->pairs.first()) {
+ InstancePair *pair = instance->pairs.first()->self();
+ Instance *other_instance = instance == pair->a ? pair->b : pair->a;
+ if (other_instance->pair_check != pair_pass) {
+ //unpaired
+ _instance_unpair(instance, other_instance);
+ } else {
+ //kept
+ other_instance->pair_check = 0; // if kept, then put pair check to zero, so we can distinguish with the newly added ones
+ }
+
+ pair_allocator->free(pair);
+ }
+ while (pairs_found.first()) {
+ InstancePair *pair = pairs_found.first()->self();
+ pairs_found.remove(pairs_found.first());
+
+ if (pair->b->pair_check == pair_pass) {
+ //paired
+ _instance_pair(instance, pair->b);
+ }
+ pair->a->pairs.add(&pair->list_a);
+ pair->b->pairs.add(&pair->list_b);
+ }
+ }
+ };
+
+ struct CullResult {
+ PagedArray<Instance *> *result;
+ _FORCE_INLINE_ bool operator()(void *p_data) {
+ Instance *p_instance = (Instance *)p_data;
+ result->push_back(p_instance);
+ return false;
+ }
+ };
+
Set<Instance *> heightfield_particle_colliders_update_list;
- int instance_cull_count;
- Instance *instance_cull_result[MAX_INSTANCE_CULL];
- Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
- Instance *light_cull_result[MAX_LIGHTS_CULLED];
- RID sdfgi_light_cull_result[MAX_LIGHTS_CULLED];
- RID light_instance_cull_result[MAX_LIGHTS_CULLED];
+ PagedArrayPool<Instance *> instance_cull_page_pool;
+ PagedArrayPool<RendererSceneRender::InstanceBase *> base_instance_cull_page_pool;
+ PagedArrayPool<RID> rid_cull_page_pool;
+
+ PagedArray<Instance *> instance_cull_result;
+ PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_render;
+ PagedArray<Instance *> instance_shadow_cull_result;
+ PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_shadow_render;
+ PagedArray<Instance *> instance_sdfgi_cull_result;
+ PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_sdfgi_render;
+ PagedArray<Instance *> light_cull_result;
+ PagedArray<RendererSceneRender::InstanceBase *> lightmap_cull_result;
+ PagedArray<Instance *> directional_shadow_cull_result;
+ PagedArray<RID> reflection_probe_instance_cull_result;
+ PagedArray<RID> light_instance_cull_result;
+ PagedArray<RID> directional_light_cull_result;
+ PagedArray<RID> gi_probe_instance_cull_result;
+ PagedArray<RID> decal_instance_cull_result;
+
+ PagedArray<RID> sdfgi_cascade_lights[SDFGI_MAX_CASCADES];
+
uint64_t sdfgi_light_cull_pass = 0;
- int light_cull_count;
int directional_light_count;
- RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
- RID decal_instance_cull_result[MAX_DECALS_CULLED];
- int reflection_probe_cull_count;
- int decal_cull_count;
- RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED];
- int gi_probe_cull_count;
- Instance *lightmap_cull_result[MAX_LIGHTS_CULLED];
- int lightmap_cull_count;
RID_PtrOwner<Instance> instance_owner;
+ bool pair_volumes_to_mesh; // used in traditional forward, unnecesary on clustered
+
virtual RID instance_create();
virtual void instance_set_base(RID p_instance, RID p_base);
@@ -460,6 +534,7 @@ public:
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
+ void _unpair_instance(Instance *p_instance);
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_lod_threshold);
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index b6bdcab88f..f8b70e3ad4 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -32,6 +32,7 @@
#define RENDERINGSERVERSCENERENDER_H
#include "core/math/camera_matrix.h"
+#include "core/templates/paged_array.h"
#include "servers/rendering/renderer_storage.h"
class RendererSceneRender {
@@ -55,7 +56,7 @@ public:
virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0;
- virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count) = 0;
+ virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const PagedArray<RID> &p_directionals, const RID *p_positional_light_instances, uint32_t p_positional_light_count) = 0;
/* SKY API */
@@ -231,17 +232,17 @@ public:
virtual RID gi_probe_instance_create(RID p_gi_probe) = 0;
virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
virtual bool gi_probe_needs_update(RID p_probe) const = 0;
- virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) = 0;
+ virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::InstanceBase *> &p_dynamic_objects) = 0;
virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
- virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) = 0;
+ virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) = 0;
- virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) = 0;
- virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) = 0;
- virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) = 0;
- virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, InstanceBase **p_cull_result, int p_cull_count) = 0;
+ virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) = 0;
+ virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances) = 0;
+ virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_lights) = 0;
+ virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances) = 0;
virtual void set_scene_pass(uint64_t p_pass) = 0;
virtual void set_time(double p_time, double p_step) = 0;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 3eff92d916..0a3e82ea22 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2359,6 +2359,9 @@ RenderingServer::RenderingServer() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/volumetric_fog/directional_shadow_shrink", PropertyInfo(Variant::INT, "rendering/volumetric_fog/directional_shadow_shrink", PROPERTY_HINT_RANGE, "32,2048,1"));
GLOBAL_DEF("rendering/volumetric_fog/positional_shadow_shrink", 512);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/volumetric_fog/positional_shadow_shrink", PropertyInfo(Variant::INT, "rendering/volumetric_fog/positional_shadow_shrink", PROPERTY_HINT_RANGE, "32,2048,1"));
+
+ GLOBAL_DEF("rendering/spatial_indexer/update_iterations_per_frame", 10);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/spatial_indexer/update_iterations_per_frame", PropertyInfo(Variant::INT, "rendering/spatial_indexer/update_iterations_per_frame", PROPERTY_HINT_RANGE, "0,1024,1"));
}
RenderingServer::~RenderingServer() {