shithub: qk1

Download patch

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]);