silicon_sse: fix over-cull of straddling objects in frustumCullBBox
si_frustumCullBBox (0x686000, center+radius variant) was culling any bounding volume whose center had view-space z < 0, but an object whose center is behind the camera can still have its front extent inside the frustum (think of standing next to a big WMO -- the building's center can be a few units behind you while its front wall is still in frame). Use the bounding sphere rather than the center point: only cull when the closest point of the sphere is itself behind the camera, i.e. center.z + |radius| < 0. Straddling cases now fall through to the near-plane passthrough and get rendered. si_frustumCullBBox8 (0x686180, 8-corner variant) already does the right thing here -- it only returns "all behind" when every transformed corner has z < 0, which is a true convex-hull test for an AABB.
This commit is contained in:
@@ -577,9 +577,12 @@ pub fn si_frustumCullBBox(bbox: u32, flags: u32, radius_bits: u32) callconv(FC)
|
||||
// z=0, so skip col2 term
|
||||
const extent = @mulAdd(V4, rv, loadV4(m2 + 16), @mulAdd(V4, rv, loadV4(m2), loadV4(m2 + 48)));
|
||||
|
||||
// Behind-camera check (unless flags & 8)
|
||||
// Behind-camera check (unless flags & 8). Use the bounding sphere, not
|
||||
// just the center: an object whose center is behind the camera can still
|
||||
// have its front extent in frame. Cull only if the entire sphere is
|
||||
// behind the camera (closest point still has z < 0).
|
||||
if ((flags & 0x8) == 0) {
|
||||
if (center[2] < 0.0) return 2;
|
||||
if (center[2] + @abs(radius) < 0.0) return 2;
|
||||
if (center[2] < @as(*align(1) const f32, @ptrFromInt(0x80FED4)).*) return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user