shithub: libgraphics

Download patch

ref: 30f55036b9214b18ea8a0a101aa3b19a1623a365
parent: 54c7d78159661381c0cdae906ff6e338f321c707
author: rodri <rgl@antares-labs.eu>
date: Fri Mar 6 21:15:05 EST 2026

compute the correct tiled triangle bbox to avoid walking the æther

--- a/clip.c
+++ b/clip.c
@@ -131,25 +131,30 @@
 	return np;
 }
 
-static int
-ptisinside(int code)
-{
-	return !code;
-}
+/* TODO bring these back when we get inline */
+//static int
+//ptisinside(int code)
+//{
+//	return !code;
+//}
+//
+//static int
+//lineisinside(int code0, int code1)
+//{
+//	return !(code0|code1);
+//}
+//
+//static int
+//lineisoutside(int code0, int code1)
+//{
+//	return code0 & code1;
+//}
 
-static int
-lineisinside(int code0, int code1)
-{
-	return !(code0|code1);
-}
+#define ptisinside(c)		(!c)
+#define lineisinside(c0, c1)	(!(c0|c1))
+#define lineisoutside(c0, c1)	(c0&c1)
 
 static int
-lineisoutside(int code0, int code1)
-{
-	return code0 & code1;
-}
-
-static int
 outcode(Point p, Rectangle r)
 {
 	int code;
@@ -208,9 +213,9 @@
 		code1 = outcode(*p1, r);
 
 		if(lineisinside(code0, code1))
-			return 0;
+			return 1;
 		else if(lineisoutside(code0, code1))
-			return -1;
+			return 0;
 
 		if(ptisinside(code0)){
 			SWAP(Point, p0, p1);
--- a/graphics.h
+++ b/graphics.h
@@ -276,10 +276,9 @@
 struct Shadertab
 {
 	char		*name;
-	Vertexattrs;				/* uniforms */
-
 	Point3		(*vs)(Shaderparams*);	/* vertex shader */
 	Color		(*fs)(Shaderparams*);	/* fragment shader */
+	Vertexattrs;				/* uniforms */
 };
 
 struct Rendertime
@@ -331,7 +330,7 @@
 {
 	QLock;
 	Astk		*stk;	/* framebuffer fragment stacks */
-	Astk*		*act;	/* active fragment stacks */
+	Astk		**act;	/* active fragment stacks */
 	ulong		nact;
 };
 
--- a/internal.h
+++ b/internal.h
@@ -159,3 +159,7 @@
 
 /* void SWAP(type, type *a, type *b) */
 #define SWAP(t, a, b) {t tmp; tmp = *(a); *(a) = *(b); *(b) = tmp;}
+
+#define RECTXRECT(a, b)\
+	((a).min.x < (b).max.x && (b).min.x < (a).max.x\
+	&& (a).min.y < (b).max.y && (b).min.y < (a).max.y)
--- a/render.c
+++ b/render.c
@@ -255,7 +255,7 @@
 	p0 = (Point){prim->v[0].p.x, prim->v[0].p.y};
 	p1 = (Point){prim->v[1].p.x, prim->v[1].p.y};
 	/* clip it against our wr */
-	if(_rectclipline(task->wr, &p0, &p1) < 0)
+	if(!_rectclipline(task->wr, &p0, &p1))
 		return;
 
 	_adjustlineverts(&p0, &p1, prim->v+0, prim->v+1);
@@ -289,8 +289,8 @@
 
 		z = flerp(prim->v[0].p.z, prim->v[1].p.z, perc);
 		/* TODO get rid of the bounds check and make sure the clipping doesn't overflow */
-		if(!ptinrect(p, sp->fb->r) ||
-		   ((ropts & RODepth) && z <= getdepth(zr, p)))
+		if(!ptinrect(p, sp->fb->r)
+		|| ((ropts & RODepth) && z <= getdepth(zr, p)))
 			goto discard;
 
 		/* interpolate z⁻¹ and get actual z */
@@ -373,6 +373,39 @@
 	∇->pcz.dy = fberp(prim->v[0].p.w, prim->v[1].p.w, prim->v[2].p.w, ∇->bc.dy);
 }
 
+static Rectangle
+mktribbox(Point3 p0, Point3 p1, Point3 p2, Rectangle wr)
+{
+	Point l[6];
+	Rectangle r;
+	int i;
+
+	l[0] = (Point){p0.x+0.5, p0.y+0.5};
+	l[1] = (Point){p1.x+0.5, p1.y+0.5};
+	l[2] = l[1];
+	l[3] = (Point){p2.x+0.5, p2.y+0.5};
+	l[4] = l[3];
+	l[5] = l[0];
+
+	r.min = (Point){ 100000, 100000};
+	r.max = (Point){-100000,-100000};
+	for(i = 0; i < 6; i += 2)
+		if(_rectclipline(wr, l+i, l+i+1)){
+			r.min.x = min(r.min.x, l[i].x); r.min.x = min(r.min.x, l[i+1].x);
+			r.min.y = min(r.min.y, l[i].y); r.min.y = min(r.min.y, l[i+1].y);
+			r.max.x = max(r.max.x, l[i].x); r.max.x = max(r.max.x, l[i+1].x);
+			r.max.y = max(r.max.y, l[i].y); r.max.y = max(r.max.y, l[i+1].y);
+		}
+	r.max.x++;
+	r.max.y++;
+	/* simplified rectclip(2) */
+	if(r.min.x < wr.min.x) r.min.x = wr.min.x;
+	if(r.min.y < wr.min.y) r.min.y = wr.min.y;
+	if(r.max.x > wr.max.x) r.max.x = wr.max.x;
+	if(r.max.y > wr.max.y) r.max.y = wr.max.y;
+	return r;
+}
+
 static void
 rasterizetri(Rastertask *task)
 {
@@ -395,6 +428,8 @@
 
 	ropts = sp->camera->rendopts;
 
+	task->wr = mktribbox(prim->v[0].p, prim->v[1].p, prim->v[2].p, task->wr);
+
 	/* perspective divide vertex attributes */
 	_mulvertex(prim->v+0, prim->v[0].p.w);
 	_mulvertex(prim->v+1, prim->v[1].p.w);
@@ -425,6 +460,13 @@
 		z = ∇.z.f0;
 		pcz = ∇.pcz.f0;
 	for(p.x = task->wr.min.x; p.x < task->wr.max.x; p.x++){
+//		if(p.x == task->wr.min.x || p.x == task->wr.max.x-1
+//		|| p.y == task->wr.min.y || p.y == task->wr.max.y-1){
+//			pixel(cr, p, (Color){1,0,0,1}, 0);
+//			putdepth(zr, p, 1);
+//			task->clipr->min = minpt(task->clipr->min, p);
+//			task->clipr->max = maxpt(task->clipr->max, p);
+//		}
 		if(bc.x < 0 || bc.y < 0 || bc.z < 0)
 			goto discard;
 
@@ -674,7 +716,7 @@
 				bbox.max.y = max(p->v[0].p.y, p->v[1].p.y)+1;
 
 				for(i = 0; i < nproc; i++)
-					if(rectXrect(bbox, wr[i])){
+					if(RECTXRECT(bbox, wr[i])){
 						rtask.wr = wr[i];
 						rtask.clipr = &task.job->cliprects[i];
 						rtask.p = *p;
@@ -713,9 +755,8 @@
 					bbox.max.y = max(max(p->v[0].p.y, p->v[1].p.y), p->v[2].p.y)+1;
 
 					for(i = 0; i < nproc; i++)
-						if(rectXrect(bbox, wr[i])){
-							rtask.wr = bbox;
-							rectclip(&rtask.wr, wr[i]);
+						if(RECTXRECT(bbox, wr[i])){
+							rtask.wr = wr[i];
 							rtask.clipr = &task.job->cliprects[i];
 							rtask.p = *p;
 							send(taskchans[i], &rtask);
--