From 1b7c80a21d88fc1c98dabfb54b6a707b7c6b982c Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Fri, 17 Feb 2023 16:44:17 +0100 Subject: [PATCH] Moved tessellation LOD stuff entirely into face culling function. This means tessellation will now also be applied to brush model faces. --- ps1bsp.h | 2 +- world.c | 38 ++++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/ps1bsp.h b/ps1bsp.h index 653f3be..0d9f952 100755 --- a/ps1bsp.h +++ b/ps1bsp.h @@ -105,7 +105,7 @@ typedef struct typedef struct ps1bsp_face_s { unsigned short planeId; - unsigned char side; + char side; // TODO: not sure if we should make separate lists for triangles and non-triangle polygons here // Could potentially improve drawing performance but at the cost of more memory use per face diff --git a/world.c b/world.c index ef6a9a0..a93c189 100644 --- a/world.c +++ b/world.c @@ -64,7 +64,7 @@ static INLINE short world_pointPlaneDist(const VECTOR *point, const ps1bsp_plane return (short)m_pointPlaneDist2(point, &plane->normal, plane->dist); } -static INLINE short world_cull_backface(const world_t *world, const ps1bsp_face_t *face) +static INLINE short world_cull_backface(const world_t *world, ps1bsp_face_t *face) { // Backface culling using the face's plane and center point // This eliminates the need for normal clipping per polygon @@ -77,7 +77,7 @@ static INLINE short world_cull_backface(const world_t *world, const ps1bsp_face_ const ps1bsp_plane_t *plane = &world->planes[face->planeId]; int planeDot = m_dot12(&cam_vec, &plane->normal); if ((planeDot >= 0) ^ face->side) - return 0; + return 1; // Check if the face is behind the camera // NOTE: disabling the behind-the-camera check does *not* actually solve the problem of polygons disappearing when too close to the camera! @@ -93,24 +93,35 @@ static INLINE short world_cull_backface(const world_t *world, const ps1bsp_face_ if (frustum_pointInside((SVECTOR*)vert)) { // TODO: use a simplified formula with only face area to determine tessellation LOD - return 1; + face->flags &= ~3; + face->flags |= 1; + return 0; } } // Face really isn't visible - return 0; + return 1; } // Flip angle for faces that are on the opposite side of their plane - char flip = 2 * face->side - 1; - planeDot = planeDot * flip; + planeDot = planeDot * (2 * face->side - 1); // Calculate an LOD value for this face, based on camera position & direction, face normal & area and distance. // This is used to determine how many tessellation subdivisions are necessary to prevent texture warping. int vecLenSqr = m_dot12(&cam_vec, &cam_vec); int lod = (planeDot * vecLenSqr) / (camDot + 1); lod = (lod << 6) / (face->center.pad + 1); - return (short)lod; + + // Use flags to store the selected LOD level + face->flags &= ~3; + if (lod < 64) + face->flags |= 1; + else if (lod < 128) + face->flags |= 2; + // else if (lod < 256) + // face->flags |= 3; + + return 0; } static u_short world_leafAtPoint(const world_t *world, const VECTOR *point) @@ -272,7 +283,7 @@ static ps1bsp_face_t *world_sortModelFaces(const world_t* world, const ps1bsp_mo face->drawFrame = frameNum; // Cull faces that are facing away from the camera - if (!world_cull_backface(world, face)) + if (world_cull_backface(world, face)) continue; if (!firstFace) @@ -319,18 +330,9 @@ static ps1bsp_face_t *world_sortFaces(const world_t *world, const ps1bsp_leaf_t // Cull faces that are facing away from the camera // This also returns an LOD value used to determine tessellation level - short lod = world_cull_backface(world, face); - if (!lod) + if (world_cull_backface(world, face)) continue; - face->flags &= ~3; - if (lod < 64) - face->flags |= 1; - else if (lod < 128) - face->flags |= 2; - // else if (lod < 256) - // face->flags |= 3; - // Sort the faces to draw in front-to-back order face->nextFace = firstFace; firstFace = face;