From 8404d84e36612d1927dfbbea999d04c9028aab90 Mon Sep 17 00:00:00 2001 From: Florent Guiocheau Date: Mon, 2 Dec 2024 13:16:44 +0100 Subject: [PATCH] Optimize Occlusion jitter --- modules/raycast/raycast_occlusion_cull.cpp | 35 ++++++++++------------ modules/raycast/raycast_occlusion_cull.h | 4 +-- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp index ce780ca565cd..4fcbe857b687 100644 --- a/modules/raycast/raycast_occlusion_cull.cpp +++ b/modules/raycast/raycast_occlusion_cull.cpp @@ -80,23 +80,22 @@ void RaycastOcclusionCull::RaycastHZBuffer::resize(const Size2i &p_size) { memset(camera_ray_masks.ptr(), ~0, camera_rays_tile_count * TILE_RAYS * sizeof(uint32_t)); } -void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) { +void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D &p_cam_transform, const Vector3 &p_near_bottom_left, const Vector2 p_near_extents, float p_z_far, bool p_cam_orthogonal) { CameraRayThreadData td; td.thread_count = WorkerThreadPool::get_singleton()->get_thread_count(); - td.z_near = p_cam_projection.get_z_near(); - td.z_far = p_cam_projection.get_z_far() * 1.05f; + td.z_near = -p_near_bottom_left.z; + td.z_far = p_z_far * 1.05f; td.camera_pos = p_cam_transform.origin; td.camera_dir = -p_cam_transform.basis.get_column(2); td.camera_orthogonal = p_cam_orthogonal; // Calculate the world coordinates of the viewport. - Vector2 viewport_half = p_cam_projection.get_viewport_half_extents(); - td.pixel_corner = p_cam_transform.xform(Vector3(-viewport_half.x, -viewport_half.y, -p_cam_projection.get_z_near())); - Vector3 top_corner_world = p_cam_transform.xform(Vector3(-viewport_half.x, viewport_half.y, -p_cam_projection.get_z_near())); - Vector3 left_corner_world = p_cam_transform.xform(Vector3(viewport_half.x, -viewport_half.y, -p_cam_projection.get_z_near())); + td.pixel_corner = p_cam_transform.xform(p_near_bottom_left); + Vector3 top_corner_world = p_cam_transform.xform(p_near_bottom_left + Vector3(0, p_near_extents.y, 0)); + Vector3 right_corner_world = p_cam_transform.xform(p_near_bottom_left + Vector3(p_near_extents.x, 0, 0)); - td.pixel_u_interp = left_corner_world - td.pixel_corner; + td.pixel_u_interp = right_corner_world - td.pixel_corner; td.pixel_v_interp = top_corner_world - td.pixel_corner; debug_tex_range = td.z_far; @@ -526,18 +525,16 @@ 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) { +Vector2 RaycastOcclusionCull::_jitter_half_extents(const Vector2 &p_half_extents, const Size2i &p_viewport_size) { if (!_jitter_enabled) { - return p_cam_projection; + return p_half_extents; } // Prevent divide by zero when using NULL viewport. if ((p_viewport_size.x <= 0) || (p_viewport_size.y <= 0)) { - return p_cam_projection; + return p_half_extents; } - Projection p = p_cam_projection; - int32_t frame = Engine::get_singleton()->get_frames_drawn(); frame %= 9; @@ -577,11 +574,9 @@ Projection RaycastOcclusionCull::_jitter_projection(const Projection &p_cam_proj // 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; + jitter *= Vector2(p_half_extents.x / (float)p_viewport_size.x, p_half_extents.y / (float)p_viewport_size.y) * 0.5f; - p.add_jitter_offset(jitter); - - return p; + return p_half_extents + jitter; } void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) { @@ -598,9 +593,11 @@ void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_ Scenario &scenario = scenarios[buffer.scenario_rid]; scenario.update(); - Projection jittered_proj = _jitter_projection(p_cam_projection, buffer.get_occlusion_buffer_size()); + Vector2 viewport_half = p_cam_projection.get_viewport_half_extents(); + Vector2 jitter_viewport_half = _jitter_half_extents(viewport_half, buffer.get_occlusion_buffer_size()); + Vector3 near_bottom_left = Vector3(-jitter_viewport_half.x, -jitter_viewport_half.y, -p_cam_projection.get_z_near()); - buffer.update_camera_rays(p_cam_transform, jittered_proj, p_cam_orthogonal); + buffer.update_camera_rays(p_cam_transform, near_bottom_left, 2 * viewport_half, p_cam_projection.get_z_far(), 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); diff --git a/modules/raycast/raycast_occlusion_cull.h b/modules/raycast/raycast_occlusion_cull.h index 347f3be2c996..2726b0caadf8 100644 --- a/modules/raycast/raycast_occlusion_cull.h +++ b/modules/raycast/raycast_occlusion_cull.h @@ -76,7 +76,7 @@ class RaycastOcclusionCull : public RendererSceneOcclusionCull { virtual void clear() override; virtual void resize(const Size2i &p_size) override; void sort_rays(const Vector3 &p_camera_dir, bool p_orthogonal); - void update_camera_rays(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal); + void update_camera_rays(const Transform3D &p_cam_transform, const Vector3 &p_near_bottom_left, const Vector2 p_near_extents, float p_z_far, bool p_cam_orthogonal); ~RaycastHZBuffer(); }; @@ -166,7 +166,7 @@ class RaycastOcclusionCull : public RendererSceneOcclusionCull { bool _jitter_enabled = false; void _init_embree(); - Projection _jitter_projection(const Projection &p_cam_projection, const Size2i &p_viewport_size); + Vector2 _jitter_half_extents(const Vector2 &p_half_extents, const Size2i &p_viewport_size); public: virtual bool is_occluder(RID p_rid) override;