Browse Source

Some micro-optimizations in the face drawing code. The PS1 really does favor simple counters over pointer arithmetic.

unrollquadloop
Nico de Poel 3 years ago
parent
commit
812bcb6a63
  1. 52
      draw.h
  2. 26
      world.c

52
draw.h

@ -170,20 +170,25 @@ static INLINE void draw_quadstrip_textured(STVECTOR *verts, u_char numVerts, u_s
return;
// Draw the face as a quad strip
const STVECTOR *v0, *v1, *v2, *v3;
const STVECTOR *head = verts;
const STVECTOR *tail = verts + numVerts;
u_char i0, i1, i2, i3;
u_char head = 0;
u_char tail = numVerts;
// Initialize the first two vertices
v2 = --tail;
v3 = head++;
i2 = --tail;
i3 = head++;
STVECTOR *v0, *v1, *v2, *v3;
for (u_char quadIdx = 0; quadIdx < numQuads; ++quadIdx)
{
v0 = v2;
v1 = v3;
v2 = --tail;
v3 = head++;
i0 = i2;
i1 = i3;
i2 = --tail;
i3 = head++;
v0 = &verts[i0];
v1 = &verts[i1];
v2 = &verts[i2];
// Naively draw the quad with GTE, nothing special or optimized about this
gte_ldv3(v0, v1, v2);
@ -194,7 +199,7 @@ static INLINE void draw_quadstrip_textured(STVECTOR *verts, u_char numVerts, u_s
gte_stotz(&p);
short depth = p >> 2;
if (depth <= 0 || depth >= OTLEN)
continue;
return;
// Draw a flat-shaded untextured colored quad
POLY_GT4 *poly = (POLY_GT4*)mem_prim(sizeof(POLY_GT4));
@ -203,6 +208,8 @@ static INLINE void draw_quadstrip_textured(STVECTOR *verts, u_char numVerts, u_s
gte_stsxy1(&poly->x1);
gte_stsxy2(&poly->x2);
v3 = &verts[i3];
// Transform the fourth vertex to complete the quad
gte_ldv0(v3);
gte_rtps();
@ -234,20 +241,25 @@ static INLINE void draw_quadstrip_water(STVECTOR *verts, u_char numVerts, u_shor
return;
// Draw the face as a quad strip
const STVECTOR *v0, *v1, *v2, *v3;
const STVECTOR *head = verts;
const STVECTOR *tail = verts + numVerts;
u_char i0, i1, i2, i3;
u_char head = 0;
u_char tail = numVerts;
// Initialize the first two vertices
v2 = --tail;
v3 = head++;
i2 = --tail;
i3 = head++;
const STVECTOR *v0, *v1, *v2, *v3;
for (u_char quadIdx = 0; quadIdx < numQuads; ++quadIdx)
{
v0 = v2;
v1 = v3;
v2 = --tail;
v3 = head++;
i0 = i2;
i1 = i3;
i2 = --tail;
i3 = head++;
v0 = &verts[i0];
v1 = &verts[i1];
v2 = &verts[i2];
// Naively draw the quad with GTE, nothing special or optimized about this
gte_ldv3(v0, v1, v2);
@ -267,6 +279,8 @@ static INLINE void draw_quadstrip_water(STVECTOR *verts, u_char numVerts, u_shor
gte_stsxy1(&poly->x1);
gte_stsxy2(&poly->x2);
v3 = &verts[i3];
// Transform the fourth vertex to complete the quad
gte_ldv0(v3);
gte_rtps();

26
world.c

@ -79,17 +79,17 @@ static INLINE char world_cull_backface(const world_t *world, const ps1bsp_face_t
cam_vec.vy = face->center.vy - cam_pos.vy;
cam_vec.vz = face->center.vz - cam_pos.vz;
// Check if the face's plane points towards the camera
const ps1bsp_plane_t *plane = &world->planes[face->planeId];
*dot = world_planeDot(&cam_vec, plane);
if ((*dot >= 0) ^ face->side)
return 1;
// Check if the face is behind the camera
// TODO: this may cull faces close to the camera, use VectorNormalS to normalize and check for angles < -60 degrees
// TODO: or, just check against all corners of the face...
short camDot = m_dot12(cam_vec, cam_dir);
if (camDot < 0)
return 1;
// Check if the face's plane points towards the camera
const ps1bsp_plane_t *plane = &world->planes[face->planeId];
*dot = world_planeDot(&cam_vec, plane);
return ((*dot >= 0) ^ face->side);
return camDot < 0;
}
static void world_drawface_fast(const world_t *world, const ps1bsp_face_t *face)
@ -107,7 +107,9 @@ static void world_drawface_fast(const world_t *world, const ps1bsp_face_t *face)
for (u_char vertIdx = 0; vertIdx < face->numFaceVertices; ++vertIdx, ++faceVertex, ++curVert)
{
const ps1bsp_vertex_t *vert = &world->vertices[faceVertex->index];
*curVert = *((SVECTOR*)vert);
curVert->vx = vert->x;
curVert->vy = vert->y;
curVert->vz = vert->z;
curVert->pad = (unsigned short)(size_t)face & 0xFF; // TODO: apply averaged light * color value
}
@ -135,7 +137,9 @@ static void world_drawface_lit(const world_t *world, const ps1bsp_face_t *face)
for (u_char vertIdx = 0; vertIdx < poly->numPolyVertices; ++vertIdx, ++polyVertex, ++curVert)
{
const ps1bsp_vertex_t *vert = &world->vertices[polyVertex->index];
*curVert = *((SVECTOR*)vert);
curVert->vx = vert->x;
curVert->vy = vert->y;
curVert->vz = vert->z;
curVert->pad = polyVertex->light;
}
@ -169,7 +173,9 @@ static void world_drawface_textured(const world_t *world, const ps1bsp_face_t *f
for (u_char vertIdx = 0; vertIdx < poly->numPolyVertices; ++vertIdx, ++polyVertex, ++curVert)
{
const ps1bsp_vertex_t *vert = &world->vertices[polyVertex->index];
*((SVECTOR*)curVert) = *((SVECTOR*)vert);
curVert->vx = vert->x;
curVert->vy = vert->y;
curVert->vz = vert->z;
curVert->u = (u_short)polyVertex->u;
curVert->v = (u_short)polyVertex->v;
curVert->pad = polyVertex->light;

Loading…
Cancel
Save