shithub: qk1

Download patch

ref: 0e95c99e5645c8754782168c8e78243482746372
parent: b85143c529f1ca238611290e73fae27320479b0b
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Sat Dec 16 08:42:05 EST 2023

32-bit zbuffer and more precise zspans drawing

This significantly reduces z-fighting (especiall apparent on ad_tears)
and makes torch behind a wall on ad_azad invisible from afar.

--- a/d_local.h
+++ b/d_local.h
@@ -33,7 +33,7 @@
 	int				u, v, count;
 } sspan_t;
 
-typedef u16int uzint;
+typedef s32int uzint;
 
 extern cvar_t	d_subdiv16;
 
--- a/d_part.c
+++ b/d_part.c
@@ -37,7 +37,7 @@
 
 	pz = d_pzbuffer + d_zwidth*v + u;
 	pdest = d_viewbuffer + d_scantable[v] + u;
-	izi = zi * 0x8000;
+	izi = zi * 0x8000 * 0x10000;
 
 	zi = 1024.0 * d_pix_scale / Length(local);
 	pix = clamp(zi, d_pix_min, d_pix_max) * r_part_scale.value;
--- a/d_polyse.c
+++ b/d_polyse.c
@@ -117,7 +117,7 @@
 		// valid triangle coordinates for filling can include the bottom and
 		// right clip edges, due to the fill rule; these shouldn't be drawn
 		if (fv->u < r_refdef.vrectright && fv->v < r_refdef.vrectbottom){
-			z = fv->zi >> 16;
+			z = fv->zi;
 			zbuf = zspantable[fv->v] + fv->u;
 			if(z >= *zbuf){
 				pixel_t p = addlight(skintable[fv->t >> 16][fv->s >> 16], fv->l[0], fv->l[1], fv->l[2]);
@@ -305,7 +305,7 @@
 	if ((lp2->v == lp1->v) && (lp2->u < lp1->u))
 		goto nodraw;
 
-	z = new.zi >> 16;
+	z = new.zi;
 	zbuf = zspantable[new.v] + new.u;
 	if (z >= *zbuf){
 		pixel_t p = addlight(skintable[new.t >> 16][new.s >> 16], l[0], l[1], l[2]);
@@ -549,7 +549,7 @@
 
 			do
 			{
-				if ((lzi >> 16) >= *lpz){
+				if (lzi >= *lpz){
 					pixel_t p = addlight(*lptex, llight[0], llight[1], llight[2]);
 					if(r_drawflags & DRAW_BLEND){
 						*lpdest = blendalpha(
@@ -560,7 +560,7 @@
 					}else{
 						*lpdest = p;
 						// gel mapping	*lpdest = gelmap[*lpdest];
-						*lpz = lzi >> 16;
+						*lpz = lzi;
 					}
 				}
 				lpdest++;
--- a/d_scan.c
+++ b/d_scan.c
@@ -63,7 +63,7 @@
 	do{
 		sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
 		tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
-		if(*r_turb_z <= (izi >> 16) || (r_drawflags & DRAW_BLEND) == 0)
+		if(*r_turb_z <= izi || (r_drawflags & DRAW_BLEND) == 0)
 			*r_turb_pdest = blendalpha(*(r_turb_pbase + (tturb<<6) + sturb), *r_turb_pdest, alpha);
 		r_turb_s += r_turb_sstep;
 		r_turb_t += r_turb_tstep;
@@ -140,7 +140,7 @@
 				// can't step off polygon), clamp, calculate s and t steps across
 				// span by division, biasing steps low so we don't run off the
 				// texture
-				spancountminus1 = (float)(r_turb_spancount - 1);
+				spancountminus1 = r_turb_spancount - 1;
 				sdivz += d_sdivzstepu * spancountminus1;
 				tdivz += d_tdivzstepu * spancountminus1;
 				zi += d_zistepu * spancountminus1;
@@ -242,7 +242,7 @@
 				// can't step off polygon), clamp, calculate s and t steps across
 				// span by division, biasing steps low so we don't run off the
 				// texture
-				spancountminus1 = (float)(spancount - 1);
+				spancountminus1 = spancount - 1;
 				sdivz += d_sdivzstepu * spancountminus1;
 				tdivz += d_tdivzstepu * spancountminus1;
 				zi += d_zistepu * spancountminus1;
@@ -284,50 +284,44 @@
 void
 D_DrawZSpans(espan_t *pspan)
 {
-	int			count, doublecount, izistep, izi;
-	uzint		*pdest;
-	unsigned	ltemp;
-	double		zi;
-	float		du, dv;
+	int			count, spancount, izi, izistep;
+	uzint		*pz;
+	double		zi, du, dv, spancountminus1;
+	double		zistepu;
 
 	if((r_drawflags & DRAW_BLEND) != 0)
 		return;
 
-	// FIXME: check for clamping/range problems
-	// we count on FP exceptions being turned off to avoid range problems
+	zistepu = d_zistepu * 16;
 	izistep = (int)(d_zistepu * 0x8000 * 0x10000);
 
 	do{
-		pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
+		pz = d_pzbuffer + d_zwidth*pspan->v + pspan->u;
+
 		count = pspan->count;
 
-		// calculate the initial 1/z
-		du = (float)pspan->u;
-		dv = (float)pspan->v;
+		// calculate the initial s/z, t/z, 1/z, s, and t and clamp
+		du = pspan->u;
+		dv = pspan->v;
 
 		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
-		// we count on FP exceptions being turned off to avoid range problems
-		izi = (int)(zi * 0x8000 * 0x10000);
 
-		if((uintptr)pdest & 0x02){
-			*pdest++ = (short)(izi >> 16);
-			izi += izistep;
-			count--;
-		}
+		do{
+			spancount = min(count, 16);
+			count -= spancount;
 
-		if((doublecount = count >> 1) > 0){
-			do{
-				ltemp = izi >> 16;
-				izi += izistep;
-				ltemp |= izi & 0xFFFF0000;
-				izi += izistep;
-				*(int *)pdest = ltemp;
-				pdest += 2;
-			}while (--doublecount > 0);
-		}
+			if(count){
+				zi += zistepu;
+			}else{
+				spancountminus1 = spancount - 1;
+				zi += d_zistepu * spancountminus1;
+			}
 
-		if(count & 1)
-			*pdest = (short)(izi >> 16);
-
+			izi = (int)(zi * 0x8000 * 0x10000);
+			while(spancount-- > 0){
+				*pz++ = izi;
+				izi += izistep;
+			}
+		}while(count > 0);
 	}while((pspan = pspan->pnext) != nil);
 }
--- a/d_sprite.c
+++ b/d_sprite.c
@@ -137,11 +137,11 @@
 				btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
 				if (opaque(btemp))
 				{
-					if (*pz <= (izi >> 16)){	/* FIXME: segfault: assumed 32bit ptr? */
+					if (*pz <= izi){
 						if(r_drawflags & DRAW_BLEND){
 							*pdest = blendalpha(btemp, *pdest, alpha);
 						}else{
-							*pz = izi >> 16;
+							*pz = izi;
 							*pdest = btemp;
 						}
 					}
--- a/span_alpha.c
+++ b/span_alpha.c
@@ -8,7 +8,7 @@
 	if(alpha != 255){
 		do{
 			pix = pbase[(s >> 16) + (t >> 16) * cachewidth];
-			if(opaque(pix) && *pz <= (izi >> 16))
+			if(opaque(pix) && *pz <= izi)
 				*pdest = blendalpha(pix, *pdest, alpha);
 			pdest++;
 			pz++;
@@ -19,9 +19,9 @@
 	}else{
 		do{
 			pix = pbase[(s >> 16) + (t >> 16) * cachewidth];
-			if(opaque(pix) && *pz <= (izi >> 16)){
+			if(opaque(pix) && *pz <= izi){
 				*pdest = pix;
-				*pz = izi >> 16;
+				*pz = izi;
 			}
 			pdest++;
 			pz++;