summaryrefslogtreecommitdiffstats
path: root/modules/raycast/raycast_occlusion_cull.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/raycast/raycast_occlusion_cull.cpp')
-rw-r--r--modules/raycast/raycast_occlusion_cull.cpp63
1 files changed, 62 insertions, 1 deletions
diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp
index 5005000eae..1153832feb 100644
--- a/modules/raycast/raycast_occlusion_cull.cpp
+++ b/modules/raycast/raycast_occlusion_cull.cpp
@@ -536,6 +536,64 @@ void RaycastOcclusionCull::buffer_set_size(RID p_buffer, const Vector2i &p_size)
buffers[p_buffer].resize(p_size);
}
+Projection RaycastOcclusionCull::_jitter_projection(const Projection &p_cam_projection, const Size2i &p_viewport_size) {
+ if (!_jitter_enabled) {
+ return p_cam_projection;
+ }
+
+ // Prevent divide by zero when using NULL viewport.
+ if ((p_viewport_size.x <= 0) || (p_viewport_size.y <= 0)) {
+ return p_cam_projection;
+ }
+
+ Projection p = p_cam_projection;
+
+ int32_t frame = Engine::get_singleton()->get_frames_drawn();
+ frame %= 9;
+
+ Vector2 jitter;
+
+ switch (frame) {
+ default:
+ break;
+ case 1: {
+ jitter = Vector2(-1, -1);
+ } break;
+ case 2: {
+ jitter = Vector2(1, -1);
+ } break;
+ case 3: {
+ jitter = Vector2(-1, 1);
+ } break;
+ case 4: {
+ jitter = Vector2(1, 1);
+ } break;
+ case 5: {
+ jitter = Vector2(-0.5f, -0.5f);
+ } break;
+ case 6: {
+ jitter = Vector2(0.5f, -0.5f);
+ } break;
+ case 7: {
+ jitter = Vector2(-0.5f, 0.5f);
+ } break;
+ case 8: {
+ jitter = Vector2(0.5f, 0.5f);
+ } break;
+ }
+
+ // The multiplier here determines the divergence from center,
+ // and is to some extent a balancing act.
+ // Higher divergence gives fewer false hidden, but more false shown.
+ // False hidden is obvious to viewer, false shown is not.
+ // False shown can lower percentage that are occluded, and therefore performance.
+ jitter *= Vector2(1 / (float)p_viewport_size.x, 1 / (float)p_viewport_size.y) * 0.05f;
+
+ p.add_jitter_offset(jitter);
+
+ return p;
+}
+
void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) {
if (!buffers.has(p_buffer)) {
return;
@@ -550,7 +608,9 @@ void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_
Scenario &scenario = scenarios[buffer.scenario_rid];
scenario.update();
- buffer.update_camera_rays(p_cam_transform, p_cam_projection, p_cam_orthogonal);
+ Projection jittered_proj = _jitter_projection(p_cam_projection, buffer.get_occlusion_buffer_size());
+
+ buffer.update_camera_rays(p_cam_transform, jittered_proj, p_cam_orthogonal);
scenario.raycast(buffer.camera_rays, buffer.camera_ray_masks.ptr(), buffer.camera_rays_tile_count);
buffer.sort_rays(-p_cam_transform.basis.get_column(2), p_cam_orthogonal);
@@ -596,6 +656,7 @@ void RaycastOcclusionCull::_init_embree() {
RaycastOcclusionCull::RaycastOcclusionCull() {
raycast_singleton = this;
int default_quality = GLOBAL_GET("rendering/occlusion_culling/bvh_build_quality");
+ _jitter_enabled = GLOBAL_GET("rendering/occlusion_culling/jitter_projection");
build_quality = RS::ViewportOcclusionCullingBuildQuality(default_quality);
}