shithub: qk1

Download patch

ref: 81829a02f3745b7914ed8f6f95632a3757c71073
parent: 62d09d745f581e35daf37ebcc85c387de720940a
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed Nov 1 22:00:06 EDT 2023

rendering: sort alpha-blended entities to draw back-to-front

--- a/r_main.c
+++ b/r_main.c
@@ -114,6 +114,8 @@
 void CreatePassages (void);
 void SetVisibilityByPassages (void);
 
+static entity_t *ent_reject;
+
 /*
 ==================
 R_InitTextures
@@ -502,6 +504,7 @@
 		return 0;
 
 	currententity = e;
+	VectorCopy(modelorg, oldorigin);
 
 	switch(e->model->type){
 	case mod_sprite:
@@ -544,7 +547,6 @@
 		break;
 
 	case mod_brush:
-		VectorCopy(modelorg, oldorigin);
 		insubmodel = true;
 		r_dlightframecount = r_framecount;
 		clmodel = e->model;
@@ -604,18 +606,18 @@
 
 			e->topnode = nil;
 		}
-
-		// put back world rotation and frustum clipping		
-		// FIXME: R_RotateBmodel should just work off base_vxx
-		VectorCopy(base_vpn, vpn);
-		VectorCopy(base_vup, vup);
-		VectorCopy(base_vright, vright);
-		VectorCopy(base_modelorg, modelorg);
-		VectorCopy(oldorigin, modelorg);
-		R_TransformFrustum();
 		break;
 	}
 
+	// put back world rotation and frustum clipping		
+	// FIXME: R_RotateBmodel should just work off base_vxx
+	VectorCopy(base_vpn, vpn);
+	VectorCopy(base_vup, vup);
+	VectorCopy(base_vright, vright);
+	VectorCopy(base_modelorg, modelorg);
+	VectorCopy(oldorigin, modelorg);
+	R_TransformFrustum();
+
 	return 1;
 }
 
@@ -656,7 +658,7 @@
 	j = R_LightPoint (currententity->origin);
 
 	if (j < 24)
-		j = 24;		// allways give some light on gun
+		j = 24;		// always give some light on gun
 	r_viewlighting.ambientlight = j;
 	r_viewlighting.shadelight = j;
 
@@ -691,6 +693,7 @@
 */
 void R_EdgeDrawing (void)
 {
+	entity_t *e;
 	int i;
 
 	R_BeginEdgeFrame();
@@ -699,13 +702,30 @@
 	else{
 		R_RenderWorld();
 		for(i = 0; i < cl_numvisedicts; i++){
-			if(cl_visedicts[i]->model->type == mod_brush)
-				R_DrawEntity(cl_visedicts[i]);
+			e = cl_visedicts[i];
+			if(e->model->type == mod_brush && !R_DrawEntity(e)){
+				e->last_reject = ent_reject;
+				ent_reject = e;
+			}
 		}
 	}
 	R_ScanEdges();
 }
 
+static int
+R_SortEntities(void *a_, void *b_)
+{
+	entity_t *a, *b;
+	vec3_t v[2];
+
+	a = *(entity_t**)a_;
+	b = *(entity_t**)b_;
+	// FIXME(sigrid): this is the most dumb way, also incorrect
+	VectorSubtract(r_refdef.vieworg, a->origin, v[0]);
+	VectorSubtract(r_refdef.vieworg, b->origin, v[1]);
+	return Length(v[1]) - Length(v[0]);
+}
+
 /*
 ================
 R_RenderView
@@ -715,8 +735,9 @@
 */
 void R_RenderView (void)
 {
-	int i;
 	static byte	warpbuffer[WARP_WIDTH * WARP_HEIGHT];
+	entity_t *e;
+	int i;
 
 	r_warpbuffer = warpbuffer;
 
@@ -731,19 +752,26 @@
 
 	if (!cl_entities[0].model || !cl.worldmodel)
 		fatal ("R_RenderView: NULL worldmodel");
+	ent_reject = nil;
 	R_EdgeDrawing ();
 
 	for(i = 0; i < cl_numvisedicts; i++){
-		if(cl_visedicts[i]->model->type != mod_brush)
-			R_DrawEntity(cl_visedicts[i]);
+		e = cl_visedicts[i];
+		if(e->model->type != mod_brush && !R_DrawEntity(e)){
+			e->last_reject = ent_reject;
+			ent_reject = e;
+		}
 	}
 
 	R_DrawViewModel ();
-
 	R_DrawParticles ();
 
 	r_drawflags = DRAW_BLEND;
 	R_EdgeDrawing();
+	for(i = 0, e = ent_reject; e != nil; e = e->last_reject, i++)
+		cl_visedicts[i] = e;
+	cl_numvisedicts = i;
+	qsort(cl_visedicts, cl_numvisedicts, sizeof(*cl_visedicts), R_SortEntities);
 	for(i = 0; i < cl_numvisedicts; i++)
 		R_DrawEntity(cl_visedicts[i]);
 	r_drawflags = 0;
--- a/render.h
+++ b/render.h
@@ -48,6 +48,8 @@
 											//  that splits bmodel, or NULL if
 											//  not split
 
+	struct entity_s			*last_reject;
+
 	byte alpha;
 } entity_t;