Skip to content

Commit 06827c9

Browse files
committed
Merge pull request #107839 from Rudolph-B/Occlusion-Culling-Optimization
Minor Optimization to Occlusion Culling
2 parents f6aa5ba + 56e0463 commit 06827c9

File tree

5 files changed

+32
-47
lines changed

5 files changed

+32
-47
lines changed

core/math/vector3.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,6 @@ Vector3 Vector3::rotated(const Vector3 &p_axis, real_t p_angle) const {
4545
return r;
4646
}
4747

48-
Vector3 Vector3::clamp(const Vector3 &p_min, const Vector3 &p_max) const {
49-
return Vector3(
50-
CLAMP(x, p_min.x, p_max.x),
51-
CLAMP(y, p_min.y, p_max.y),
52-
CLAMP(z, p_min.z, p_max.z));
53-
}
54-
55-
Vector3 Vector3::clampf(real_t p_min, real_t p_max) const {
56-
return Vector3(
57-
CLAMP(x, p_min, p_max),
58-
CLAMP(y, p_min, p_max),
59-
CLAMP(z, p_min, p_max));
60-
}
61-
6248
void Vector3::snap(const Vector3 &p_step) {
6349
x = Math::snapped(x, p_step.x);
6450
y = Math::snapped(y, p_step.y);

core/math/vector3.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,20 @@ struct [[nodiscard]] Vector3 {
106106
return Vector3(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar));
107107
}
108108

109+
Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const {
110+
return Vector3(
111+
CLAMP(x, p_min.x, p_max.x),
112+
CLAMP(y, p_min.y, p_max.y),
113+
CLAMP(z, p_min.z, p_max.z));
114+
}
115+
116+
Vector3 clampf(real_t p_min, real_t p_max) const {
117+
return Vector3(
118+
CLAMP(x, p_min, p_max),
119+
CLAMP(y, p_min, p_max),
120+
CLAMP(z, p_min, p_max));
121+
}
122+
109123
_FORCE_INLINE_ real_t length() const;
110124
_FORCE_INLINE_ real_t length_squared() const;
111125

@@ -151,8 +165,6 @@ struct [[nodiscard]] Vector3 {
151165
_FORCE_INLINE_ Vector3 sign() const;
152166
_FORCE_INLINE_ Vector3 ceil() const;
153167
_FORCE_INLINE_ Vector3 round() const;
154-
Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const;
155-
Vector3 clampf(real_t p_min, real_t p_max) const;
156168

157169
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const;
158170
_FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const;

servers/rendering/renderer_scene_cull.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2824,6 +2824,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
28242824

28252825
Transform3D inv_cam_transform = cull_data.cam_transform.inverse();
28262826
float z_near = cull_data.camera_matrix->get_z_near();
2827+
bool is_orthogonal = cull_data.camera_matrix->is_orthogonal();
28272828

28282829
for (uint64_t i = p_from; i < p_to; i++) {
28292830
bool mesh_visible = false;
@@ -2838,7 +2839,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
28382839
#define VIS_RANGE_CHECK ((idata.visibility_index == -1) || _visibility_range_check<false>(cull_data.scenario->instance_visibility[idata.visibility_index], cull_data.cam_transform.origin, cull_data.visibility_viewport_mask) == 0)
28392840
#define VIS_PARENT_CHECK (_visibility_parent_check(cull_data, idata))
28402841
#define VIS_CHECK (visibility_check < 0 ? (visibility_check = (visibility_flags != InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK || (VIS_RANGE_CHECK && VIS_PARENT_CHECK))) : visibility_check)
2841-
#define OCCLUSION_CULLED (cull_data.occlusion_buffer != nullptr && (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING) == 0 && cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near, cull_data.scenario->instance_data[i].occlusion_timeout))
2842+
#define OCCLUSION_CULLED (cull_data.occlusion_buffer != nullptr && (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING) == 0 && cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near, is_orthogonal, cull_data.scenario->instance_data[i].occlusion_timeout))
28422843

28432844
if (!HIDDEN_BY_VISIBILITY_CHECKS) {
28442845
if ((LAYER_CHECK && IN_FRUSTUM(cull_data.cull->frustum) && VIS_CHECK && !OCCLUSION_CULLED) || (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_ALL_CULLING)) {

servers/rendering/renderer_scene_occlusion_cull.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,8 @@
3232

3333
RendererSceneOcclusionCull *RendererSceneOcclusionCull::singleton = nullptr;
3434

35-
const Vector3 RendererSceneOcclusionCull::HZBuffer::corners[8] = {
36-
Vector3(0, 0, 0),
37-
Vector3(0, 0, 1),
38-
Vector3(0, 1, 0),
39-
Vector3(0, 1, 1),
40-
Vector3(1, 0, 0),
41-
Vector3(1, 0, 1),
42-
Vector3(1, 1, 0),
43-
Vector3(1, 1, 1)
44-
};
45-
4635
bool RendererSceneOcclusionCull::HZBuffer::occlusion_jitter_enabled = false;
4736

48-
bool RendererSceneOcclusionCull::HZBuffer::is_empty() const {
49-
return sizes.is_empty();
50-
}
51-
5237
void RendererSceneOcclusionCull::HZBuffer::clear() {
5338
if (sizes.is_empty()) {
5439
return; // Already cleared

servers/rendering/renderer_scene_occlusion_cull.h

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ class RendererSceneOcclusionCull {
4141
public:
4242
class HZBuffer {
4343
protected:
44-
static const Vector3 corners[8];
45-
4644
LocalVector<float> data;
4745
LocalVector<Size2i> sizes;
4846
LocalVector<float *> mips;
@@ -55,7 +53,7 @@ class RendererSceneOcclusionCull {
5553
uint64_t occlusion_frame = 0;
5654
Size2i occlusion_buffer_size;
5755

58-
_FORCE_INLINE_ bool _is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const Projection &p_cam_projection, real_t p_near) const {
56+
_FORCE_INLINE_ bool _is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const Projection &p_cam_projection, real_t p_near, bool p_is_orthogonal) const {
5957
if (is_empty()) {
6058
return false;
6159
}
@@ -79,27 +77,27 @@ class RendererSceneOcclusionCull {
7977
Vector2 rect_max = Vector2(FLT_MIN, FLT_MIN);
8078

8179
for (int j = 0; j < 8; j++) {
82-
const Vector3 &c = RendererSceneOcclusionCull::HZBuffer::corners[j];
83-
Vector3 nc = Vector3(1, 1, 1) - c;
84-
Vector3 corner = Vector3(p_bounds[0] * c.x + p_bounds[3] * nc.x, p_bounds[1] * c.y + p_bounds[4] * nc.y, p_bounds[2] * c.z + p_bounds[5] * nc.z);
80+
// Bitmask to cycle through the corners of the AABB.
81+
Vector3 corner = Vector3(
82+
j & 4 ? p_bounds[0] : p_bounds[3],
83+
j & 2 ? p_bounds[1] : p_bounds[4],
84+
j & 1 ? p_bounds[2] : p_bounds[5]);
8585
Vector3 view = p_cam_inv_transform.xform(corner);
8686

8787
// When using an orthogonal camera, the closest point of an AABB to the camera is guaranteed to be a corner.
88-
if (p_cam_projection.is_orthogonal()) {
88+
if (p_is_orthogonal) {
8989
min_depth = MIN(min_depth, -view.z);
9090
}
9191

92-
Plane vp = Plane(view, 1.0);
93-
Plane projected = p_cam_projection.xform4(vp);
92+
Vector3 projected = p_cam_projection.xform(view);
9493

95-
float w = projected.d;
96-
if (w < 1.0) {
94+
if (-view.z < 0.0) {
9795
rect_min = Vector2(0.0f, 0.0f);
9896
rect_max = Vector2(1.0f, 1.0f);
9997
break;
10098
}
10199

102-
Vector2 normalized = Vector2(projected.normal.x / w * 0.5f + 0.5f, projected.normal.y / w * 0.5f + 0.5f);
100+
Vector2 normalized = Vector2(projected.x * 0.5f + 0.5f, projected.y * 0.5f + 0.5f);
103101
rect_min = rect_min.min(normalized);
104102
rect_max = rect_max.max(normalized);
105103
}
@@ -159,7 +157,10 @@ class RendererSceneOcclusionCull {
159157
public:
160158
static bool occlusion_jitter_enabled;
161159

162-
bool is_empty() const;
160+
_FORCE_INLINE_ bool is_empty() const {
161+
return sizes.is_empty();
162+
}
163+
163164
virtual void clear();
164165
virtual void resize(const Size2i &p_size);
165166

@@ -168,8 +169,8 @@ class RendererSceneOcclusionCull {
168169
// Thin wrapper around _is_occluded(),
169170
// allowing occlusion timers to delay the disappearance
170171
// of objects to prevent flickering when using jittering.
171-
_FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const Projection &p_cam_projection, real_t p_near, uint64_t &r_occlusion_timeout) const {
172-
bool occluded = _is_occluded(p_bounds, p_cam_position, p_cam_inv_transform, p_cam_projection, p_near);
172+
_FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const Projection &p_cam_projection, real_t p_near, bool p_is_orthogonal, uint64_t &r_occlusion_timeout) const {
173+
bool occluded = _is_occluded(p_bounds, p_cam_position, p_cam_inv_transform, p_cam_projection, p_near, p_is_orthogonal);
173174

174175
// Special case, temporal jitter disabled,
175176
// so we don't use occlusion timers.

0 commit comments

Comments
 (0)