diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp index 9f95307cf1c..88691be8a38 100644 --- a/modules/raycast/raycast_occlusion_cull.cpp +++ b/modules/raycast/raycast_occlusion_cull.cpp @@ -525,14 +525,14 @@ void RaycastOcclusionCull::buffer_set_size(RID p_buffer, const Vector2i &p_size) buffers[p_buffer].resize(p_size); } -Vector2 RaycastOcclusionCull::_jitter_half_extents(const Vector2 &p_half_extents, const Size2i &p_viewport_size) { +Vector2 RaycastOcclusionCull::_get_jitter(const Rect2 &p_viewport_rect, const Size2i &p_buffer_size) { if (!_jitter_enabled) { - return p_half_extents; + return Vector2(); } // Prevent divide by zero when using NULL viewport. - if ((p_viewport_size.x <= 0) || (p_viewport_size.y <= 0)) { - return p_half_extents; + if ((p_buffer_size.x <= 0) || (p_buffer_size.y <= 0)) { + return Vector2(); } int32_t frame = Engine::get_singleton()->get_frames_drawn(); @@ -568,8 +568,8 @@ Vector2 RaycastOcclusionCull::_jitter_half_extents(const Vector2 &p_half_extents jitter = Vector2(0.5f, 0.5f); } break; } - - jitter *= Vector2(p_half_extents.x / (float)p_viewport_size.x, p_half_extents.y / (float)p_viewport_size.y); + Vector2 half_extents = p_viewport_rect.get_size() * 0.5; + jitter *= Vector2(half_extents.x / (float)p_buffer_size.x, half_extents.y / (float)p_buffer_size.y); // The multiplier here determines the jitter magnitude in pixels. // It seems like a value of 0.66 matches well the above jittering pattern as it generates subpixel samples at 0, 1/3 and 2/3 @@ -578,7 +578,16 @@ Vector2 RaycastOcclusionCull::_jitter_half_extents(const Vector2 &p_half_extents // False shown can lower percentage that are occluded, and therefore performance. jitter *= 0.66f; - return p_half_extents + jitter; + return jitter; +} + +Rect2 _get_viewport_rect(const Projection &p_cam_projection) { + // NOTE: This assumes a rectangular projection plane, i.e. that: + // - the matrix is a projection across z-axis (i.e. is invertible and columns[0][1], [0][3], [1][0] and [1][3] == 0) + // - the projection plane is rectangular (i.e. columns[0][2] and [1][2] == 0 if columns[2][3] != 0) + Size2 half_extents = p_cam_projection.get_viewport_half_extents(); + Point2 bottom_left = -half_extents * Vector2(p_cam_projection.columns[3][0] * p_cam_projection.columns[3][3] + p_cam_projection.columns[2][0] * p_cam_projection.columns[2][3] + 1, p_cam_projection.columns[3][1] * p_cam_projection.columns[3][3] + p_cam_projection.columns[2][1] * p_cam_projection.columns[2][3] + 1); + return Rect2(bottom_left, 2 * half_extents); } void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) { @@ -595,11 +604,12 @@ void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_ Scenario &scenario = scenarios[buffer.scenario_rid]; scenario.update(); - 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()); + Rect2 vp_rect = _get_viewport_rect(p_cam_projection); + Vector2 bottom_left = vp_rect.position; + bottom_left += _get_jitter(vp_rect, buffer.get_occlusion_buffer_size()); + Vector3 near_bottom_left = Vector3(bottom_left.x, bottom_left.y, -p_cam_projection.get_z_near()); - buffer.update_camera_rays(p_cam_transform, near_bottom_left, 2 * viewport_half, p_cam_projection.get_z_far(), p_cam_orthogonal); + buffer.update_camera_rays(p_cam_transform, near_bottom_left, vp_rect.get_size(), 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 f5b7011abb8..590308c05ff 100644 --- a/modules/raycast/raycast_occlusion_cull.h +++ b/modules/raycast/raycast_occlusion_cull.h @@ -162,7 +162,7 @@ private: bool _jitter_enabled = false; void _init_embree(); - Vector2 _jitter_half_extents(const Vector2 &p_half_extents, const Size2i &p_viewport_size); + Vector2 _get_jitter(const Rect2 &p_viewport_rect, const Size2i &p_buffer_size); public: virtual bool is_occluder(RID p_rid) override;