Browse Source

Use face bounding quad to check if it may be partially inside the frustum, and force tessellation if it is.

I really don't like the additional CPU load required to do this, but it is necessary to reduce the amount of near-camera polygon clipping.
master
Nico de Poel 3 years ago
parent
commit
2122ae3421
  1. BIN
      n64e1m1.ps1bsp
  2. BIN
      n64e2m2.ps1bsp
  3. BIN
      n64start.ps1bsp
  4. 7
      ps1bsp.h
  5. 16
      world.c

BIN
n64e1m1.ps1bsp

BIN
n64e2m2.ps1bsp

BIN
n64start.ps1bsp

7
ps1bsp.h

@ -106,10 +106,14 @@ typedef struct ps1bsp_face_s
unsigned short planeId; unsigned short planeId;
unsigned char side; unsigned 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
// Used for high-quality tesselated textured drawing // Used for high-quality tesselated textured drawing
unsigned short firstPolygon; unsigned short firstPolygon;
unsigned char numPolygons; unsigned char numPolygons;
unsigned char totalQuads;
unsigned char totalPrimitives; // Used for early primitive buffer checks
// Used for low-quality untextured vertex colored drawing // Used for low-quality untextured vertex colored drawing
unsigned short firstFaceVertex; unsigned short firstFaceVertex;
@ -120,6 +124,7 @@ typedef struct ps1bsp_face_s
// Used for backface culling // Used for backface culling
SVECTOR center; SVECTOR center;
unsigned short bounds[4];
// Run-time data // Run-time data
const struct ps1bsp_face_s* nextFace; // For chaining faces in drawing order const struct ps1bsp_face_s* nextFace; // For chaining faces in drawing order

16
world.c

@ -85,7 +85,21 @@ static INLINE short world_cull_backface(const world_t *world, const ps1bsp_face_
// UPDATE: tessellation does solve this, to an extent. However we must also make sure not to discard faces partially inside the frustum, and force tessellation on those. // UPDATE: tessellation does solve this, to an extent. However we must also make sure not to discard faces partially inside the frustum, and force tessellation on those.
int camDot = m_dot12(&cam_vec, &cam_dir); int camDot = m_dot12(&cam_vec, &cam_dir);
if (camDot < 0) if (camDot < 0)
{
// Check if the face may be partially inside the frustum. If so, we draw it with a high amount of tessellation.
for (int i = 0; i < 4; ++i)
{
const ps1bsp_vertex_t *vert = &world->vertices[face->bounds[i]];
if (frustum_pointInside((SVECTOR*)vert))
{
// TODO: use a simplified formula with only face area to determine tessellation LOD
return 1;
}
}
// Face really isn't visible
return 0; return 0;
}
// Flip angle for faces that are on the opposite side of their plane // Flip angle for faces that are on the opposite side of their plane
char flip = 2 * face->side - 1; char flip = 2 * face->side - 1;
@ -191,7 +205,7 @@ static void world_drawFaces(const world_t *world, const ps1bsp_face_t *firstFace
for (const ps1bsp_face_t *face = firstFace; face != NULL; face = face->nextFace) for (const ps1bsp_face_t *face = firstFace; face != NULL; face = face->nextFace)
{ {
// Early primitive buffer check // Early primitive buffer check
if (!mem_checkprim(sizeof(POLY_GT4), face->totalQuads))
if (!mem_checkprim(sizeof(POLY_GT4), face->totalPrimitives))
break; break;
world_drawface(world, face, curOT); world_drawface(world, face, curOT);

Loading…
Cancel
Save