Browse Source

Moved tessellation LOD stuff entirely into face culling function.

This means tessellation will now also be applied to brush model faces.
master
Nico de Poel 3 years ago
parent
commit
1b7c80a21d
  1. 2
      ps1bsp.h
  2. 38
      world.c

2
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

38
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;

Loading…
Cancel
Save