summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2020-12-24 14:01:19 -0300
committerGitHub <noreply@github.com>2020-12-24 14:01:19 -0300
commit545c89461464ee14b2b806dd2dd2c0eef110e181 (patch)
tree346e4cf91f69044485311a2037105690aa8c48aa
parentecda989c85e953ced7c19f161b38c6b054d3acec (diff)
parent1bebb2ba057a8baa2f560362142bae5123b962af (diff)
Merge pull request #44656 from reduz/cull-fixes-and-optimizations
Cull fixes and optimizations
-rw-r--r--core/math/aabb.h27
-rw-r--r--core/math/dynamic_bvh.cpp9
-rw-r--r--core/math/dynamic_bvh.h2
-rw-r--r--core/math/math_funcs.h17
-rw-r--r--servers/rendering/renderer_scene_cull.cpp27
-rw-r--r--servers/rendering/renderer_scene_render.h1
6 files changed, 74 insertions, 9 deletions
diff --git a/core/math/aabb.h b/core/math/aabb.h
index 474304eae2..24908ae59d 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -107,6 +107,9 @@ public:
Variant intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const;
Variant intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const;
+ _FORCE_INLINE_ void quantize(float p_unit);
+ _FORCE_INLINE_ AABB quantized(float p_unit) const;
+
_FORCE_INLINE_ void set_end(const Vector3 &p_end) {
size = p_end - position;
}
@@ -427,4 +430,28 @@ void AABB::grow_by(real_t p_amount) {
size.z += 2.0 * p_amount;
}
+void AABB::quantize(float p_unit) {
+ size += position;
+
+ position.x -= Math::fposmodp(position.x, p_unit);
+ position.y -= Math::fposmodp(position.y, p_unit);
+ position.z -= Math::fposmodp(position.z, p_unit);
+
+ size.x -= Math::fposmodp(size.x, p_unit);
+ size.y -= Math::fposmodp(size.y, p_unit);
+ size.z -= Math::fposmodp(size.z, p_unit);
+
+ size.x += p_unit;
+ size.y += p_unit;
+ size.z += p_unit;
+
+ size -= position;
+}
+
+AABB AABB::quantized(float p_unit) const {
+ AABB ret = *this;
+ ret.quantize(p_unit);
+ return ret;
+}
+
#endif // AABB_H
diff --git a/core/math/dynamic_bvh.cpp b/core/math/dynamic_bvh.cpp
index a53f8d1eb8..e66de5037d 100644
--- a/core/math/dynamic_bvh.cpp
+++ b/core/math/dynamic_bvh.cpp
@@ -351,17 +351,17 @@ void DynamicBVH::_update(Node *leaf, int lookahead) {
_insert_leaf(root, leaf);
}
-void DynamicBVH::update(const ID &p_id, const AABB &p_box) {
- ERR_FAIL_COND(!p_id.is_valid());
+bool DynamicBVH::update(const ID &p_id, const AABB &p_box) {
+ ERR_FAIL_COND_V(!p_id.is_valid(), false);
Node *leaf = p_id.node;
Volume volume;
volume.min = p_box.position;
volume.max = p_box.position + p_box.size;
- if ((leaf->volume.min == volume.min) && (leaf->volume.max == volume.max)) {
+ if (leaf->volume.min.is_equal_approx(volume.min) && leaf->volume.max.is_equal_approx(volume.max)) {
// noop
- return;
+ return false;
}
Node *base = _remove_leaf(leaf);
@@ -375,6 +375,7 @@ void DynamicBVH::update(const ID &p_id, const AABB &p_box) {
}
leaf->volume = volume;
_insert_leaf(base, leaf);
+ return true;
}
void DynamicBVH::remove(const ID &p_id) {
diff --git a/core/math/dynamic_bvh.h b/core/math/dynamic_bvh.h
index cdea51c674..968badc093 100644
--- a/core/math/dynamic_bvh.h
+++ b/core/math/dynamic_bvh.h
@@ -281,7 +281,7 @@ public:
void optimize_top_down(int bu_threshold = 128);
void optimize_incremental(int passes);
ID insert(const AABB &p_box, void *p_userdata);
- void update(const ID &p_id, const AABB &p_box);
+ bool update(const ID &p_id, const AABB &p_box);
void remove(const ID &p_id);
void get_elements(List<ID> *r_elements);
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 827637bf2b..471aa58996 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -198,6 +198,23 @@ public:
value += 0.0;
return value;
}
+ static _ALWAYS_INLINE_ float fposmodp(float p_x, float p_y) {
+ float value = Math::fmod(p_x, p_y);
+ if (value < 0) {
+ value += p_y;
+ }
+ value += 0.0;
+ return value;
+ }
+ static _ALWAYS_INLINE_ double fposmodp(double p_x, double p_y) {
+ double value = Math::fmod(p_x, p_y);
+ if (value < 0) {
+ value += p_y;
+ }
+ value += 0.0;
+ return value;
+ }
+
static _ALWAYS_INLINE_ int posmod(int p_x, int p_y) {
int value = p_x % p_y;
if ((value < 0 && p_y > 0) || (value > 0 && p_y < 0)) {
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 8bb9e6b8b0..be2eb71581 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -1065,20 +1065,37 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
p_instance->transformed_aabb = new_aabb;
if (p_instance->scenario == nullptr || !p_instance->visible || Math::is_zero_approx(p_instance->transform.basis.determinant())) {
+ p_instance->prev_transformed_aabb = p_instance->transformed_aabb;
return;
}
+ //quantize to improve moving object performance
+ AABB bvh_aabb = p_instance->transformed_aabb;
+
+ if (p_instance->indexer_id.is_valid() && bvh_aabb != p_instance->prev_transformed_aabb) {
+ //assume motion, see if bounds need to be quantized
+ AABB motion_aabb = bvh_aabb.merge(p_instance->prev_transformed_aabb);
+ float motion_longest_axis = motion_aabb.get_longest_axis_size();
+ float longest_axis = p_instance->transformed_aabb.get_longest_axis_size();
+
+ if (motion_longest_axis < longest_axis * 2) {
+ //moved but not a lot, use motion aabb quantizing
+ float quantize_size = Math::pow(2.0, Math::ceil(Math::log(motion_longest_axis) / Math::log(2.0))) * 0.5; //one fifth
+ bvh_aabb.quantize(quantize_size);
+ }
+ }
+
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->transformed_aabb, p_instance);
+ p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].insert(bvh_aabb, p_instance);
} else {
- p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].insert(p_instance->transformed_aabb, p_instance);
+ p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].insert(bvh_aabb, p_instance);
}
} else {
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
- p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].update(p_instance->indexer_id, p_instance->transformed_aabb);
+ p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].update(p_instance->indexer_id, bvh_aabb);
} else {
- p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].update(p_instance->indexer_id, p_instance->transformed_aabb);
+ p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].update(p_instance->indexer_id, bvh_aabb);
}
}
@@ -1124,6 +1141,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
}
pair.pair();
+
+ p_instance->prev_transformed_aabb = p_instance->transformed_aabb;
}
void RendererSceneCull::_unpair_instance(Instance *p_instance) {
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index f8b70e3ad4..19ab7a392b 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -172,6 +172,7 @@ public:
AABB aabb;
AABB transformed_aabb;
+ AABB prev_transformed_aabb;
struct InstanceShaderParameter {
int32_t index = -1;