ref: 62d09d745f581e35daf37ebcc85c387de720940a
parent: 8ae888bc499914bd20bd663159222e7f3100e788
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed Nov 1 20:13:55 EDT 2023
rendering: don't recurse the world nodes twice Instead, build an array of nodes rejected from rendering when recursing, those are later drawn just by iterating over. The array is dynamically resized to fit as many nodes as needed.
--- a/r_bsp.c
+++ b/r_bsp.c
@@ -21,6 +21,16 @@
int r_currentbkey;
+typedef struct nodereject_t nodereject_t;
+
+struct nodereject_t {
+ mnode_t *node;
+ int clipflags;
+};
+
+static nodereject_t *node_rejects;
+static int num_node_rejects, max_node_rejects = 128;
+
typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t;
#define MAX_BMODEL_VERTS 6000
@@ -419,7 +429,7 @@
*/
void R_RecursiveWorldNode (mnode_t *node, int clipflags)
{
- int i, c, side, *pindex;
+ int i, c, side, *pindex, rejected;
vec3_t acceptpt, rejectpt;
mplane_t *plane;
msurface_t *surf, **mark;
@@ -515,21 +525,31 @@
if(c){
surf = cl.worldmodel->surfaces + node->firstsurface;
+ rejected = 0;
if(dot < -BACKFACE_EPSILON){
do{
if((surf->flags & SURF_PLANEBACK) && surf->visframe == r_framecount)
- R_RenderFace (surf, clipflags);
+ rejected |= !R_RenderFace(surf, clipflags);
surf++;
}while(--c);
}else if(dot > BACKFACE_EPSILON){
do{
if(!(surf->flags & SURF_PLANEBACK) && surf->visframe == r_framecount)
- R_RenderFace(surf, clipflags);
+ rejected |= !R_RenderFace(surf, clipflags);
surf++;
}while(--c);
}
+ if(rejected){
+ if(node_rejects == nil || num_node_rejects >= max_node_rejects){
+ max_node_rejects *= 2;
+ node_rejects = realloc(node_rejects, sizeof(*node_rejects)*max_node_rejects);
+ }
+ node_rejects[num_node_rejects].node = node;
+ node_rejects[num_node_rejects++].clipflags = clipflags;
+ }
+
// all surfaces on the same node share the same sequence number
r_currentkey++;
}
@@ -556,7 +576,26 @@
clmodel = currententity->model;
r_pcurrentvertbase = clmodel->vertexes;
+ num_node_rejects = 0;
R_RecursiveWorldNode (clmodel->nodes, 15);
}
+void
+R_RenderWorldRejects(void)
+{
+ model_t *clmodel;
+ nodereject_t *rej;
+ msurface_t *surf;
+ int i;
+ currententity = &cl_entities[0];
+ VectorCopy (r_origin, modelorg);
+ clmodel = currententity->model;
+ r_pcurrentvertbase = clmodel->vertexes;
+
+ for(rej = node_rejects; rej < node_rejects+num_node_rejects; rej++){
+ surf = cl.worldmodel->surfaces + rej->node->firstsurface;
+ for(i = 0; i < rej->node->numsurfaces; i++, surf++)
+ R_RenderFace(surf, rej->clipflags);
+ }
+}
--- a/r_draw.c
+++ b/r_draw.c
@@ -384,7 +384,7 @@
R_RenderFace
================
*/
-void R_RenderFace (msurface_t *fa, int clipflags)
+int R_RenderFace (msurface_t *fa, int clipflags)
{
int i, lindex;
unsigned mask;
@@ -395,20 +395,18 @@
clipplane_t *pclip;
if((surfdrawflags(fa->flags) | entdrawflags(currententity)) ^ r_drawflags)
- return;
+ return 0;
// skip out if no more surfs
- if ((surface_p) >= surf_max)
- {
+ if (surface_p >= surf_max){
r_outofsurfaces++;
- return;
+ return 1;
}
// ditto if not enough edges left, or switch to auxedges if possible
- if ((edge_p + fa->numedges + 4) >= edge_max)
- {
+ if (edge_p + fa->numedges + 4 >= edge_max){
r_outofedges += fa->numedges;
- return;
+ return 1;
}
c_faceclip++;
@@ -550,7 +548,7 @@
// if no edges made it out, return without posting the surface
if (!r_emitted)
- return;
+ return 1;
r_polycount++;
@@ -577,6 +575,8 @@
//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg);
surface_p++;
+
+ return 1;
}
--- a/r_local.h
+++ b/r_local.h
@@ -83,6 +83,7 @@
//=============================================================================
void R_RenderWorld (void);
+void R_RenderWorldRejects(void);
//=============================================================================
@@ -115,7 +116,7 @@
void R_DrawSprite (void);
-void R_RenderFace (msurface_t *fa, int clipflags);
+int R_RenderFace (msurface_t *fa, int clipflags);
void R_RenderPoly (msurface_t *fa, int clipflags);
void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf);
void R_TransformPlane (mplane_t *p, float *normal, float *dist);
--- a/r_main.c
+++ b/r_main.c
@@ -694,8 +694,10 @@
int i;
R_BeginEdgeFrame();
- R_RenderWorld();
- if((r_drawflags & DRAW_BLEND) == 0){
+ if(r_drawflags & DRAW_BLEND)
+ R_RenderWorldRejects();
+ else{
+ R_RenderWorld();
for(i = 0; i < cl_numvisedicts; i++){
if(cl_visedicts[i]->model->type == mod_brush)
R_DrawEntity(cl_visedicts[i]);