shithub: libgraphics

Download patch

ref: c69735e24f7c5926ed63ff8c5292be282aa8b240
parent: b1335875b19a4db2ae028f8d790784cddcffe8b5
author: rodri <rgl@antares-labs.eu>
date: Fri Jun 14 11:01:15 EDT 2024

fix the barycoords routine to avoid reporting false degenerates.

added a normals buffer for debugging.

--- a/fb.c
+++ b/fb.c
@@ -31,6 +31,17 @@
 }
 
 static void
+framebufctl_drawnormals(Framebufctl *ctl, Image *dst)
+{
+	Framebuf *fb;
+
+	qlock(ctl);
+	fb = ctl->getfb(ctl);
+	loadimage(dst, rectaddpt(fb->r, dst->r.min), (uchar*)fb->nb, Dx(fb->r)*Dy(fb->r)*4);
+	qunlock(ctl);
+}
+
+static void
 framebufctl_swap(Framebufctl *ctl)
 {
 	qlock(ctl);
@@ -45,6 +56,7 @@
 
 	/* address the back buffer—resetting the front buffer is VERBOTEN */
 	fb = ctl->getbb(ctl);
+	memset(fb->nb, 0, Dx(fb->r)*Dy(fb->r)*4);
 	memsetd(fb->zb, Inf(-1), Dx(fb->r)*Dy(fb->r));
 	memset(fb->cb, 0, Dx(fb->r)*Dy(fb->r)*4);
 }
@@ -71,6 +83,7 @@
 	fb->cb = emalloc(Dx(r)*Dy(r)*4);
 	fb->zb = emalloc(Dx(r)*Dy(r)*sizeof(*fb->zb));
 	memsetd(fb->zb, Inf(-1), Dx(r)*Dy(r));
+	fb->nb = emalloc(Dx(r)*Dy(r)*4);
 	fb->r = r;
 	return fb;
 }
@@ -94,6 +107,7 @@
 	fc->fb[1] = mkfb(r);
 	fc->draw = framebufctl_draw;
 	fc->memdraw = framebufctl_memdraw;
+	fc->drawnormals = framebufctl_drawnormals;
 	fc->swap = framebufctl_swap;
 	fc->reset = framebufctl_reset;
 	fc->getfb = framebufctl_getfb;
--- a/graphics.h
+++ b/graphics.h
@@ -227,6 +227,7 @@
 {
 	ulong *cb;	/* color buffer */
 	double *zb;	/* z/depth buffer */
+	ulong *nb;	/* normals buffer (DBG only) */
 	Rectangle r;
 };
 
@@ -238,6 +239,7 @@
 
 	void (*draw)(Framebufctl*, Image*);
 	void (*memdraw)(Framebufctl*, Memimage*);
+	void (*drawnormals)(Framebufctl*, Image*);
 	void (*swap)(Framebufctl*);
 	void (*reset)(Framebufctl*);
 	Framebuf *(*getfb)(Framebufctl*);
--- a/render.c
+++ b/render.c
@@ -46,6 +46,15 @@
 	dst[Dx(fb->r)*p.y + p.x] = col2ul(c);
 }
 
+static void
+pixeln(Framebuf *fb, Point p, Color c)
+{
+	ulong *dst;
+
+	dst = fb->nb;
+	dst[Dx(fb->r)*p.y + p.x] = col2ul(c);
+}
+
 static int
 isvisible(Point3 p)
 {
@@ -67,6 +76,21 @@
 	return sa <= 0;
 }
 
+static Point3
+_barycoords(Triangle2 t, Point2 p)
+{
+	Point2 p0p1 = subpt2(t.p1, t.p0);
+	Point2 p0p2 = subpt2(t.p2, t.p0);
+	Point2 pp0  = subpt2(t.p0, p);
+
+	Point3 v = crossvec3(Vec3(p0p2.x, p0p1.x, pp0.x), Vec3(p0p2.y, p0p1.y, pp0.y));
+
+	/* handle degenerate triangles—i.e. the ones where every point lies on the same line */
+	if(fabs(v.z) < 1e-5)
+		return Pt3(-1,-1,-1,1);
+	return Pt3(1 - (v.x + v.y)/v.z, v.y/v.z, v.x/v.z, 1);
+}
+
 static void
 rasterize(Rastertask *task)
 {
@@ -178,7 +202,7 @@
 
 		for(p.y = bbox.min.y; p.y < bbox.max.y; p.y++)
 			for(p.x = bbox.min.x; p.x < bbox.max.x; p.x++){
-				bc = barycoords(t, Pt2(p.x,p.y,1));
+				bc = _barycoords(t, Pt2(p.x,p.y,1));
 				if(bc.x < 0 || bc.y < 0 || bc.z < 0)
 					continue;
 
@@ -198,6 +222,8 @@
 				fsp.p = p;
 				c = params->fshader(&fsp);
 				pixel(params->fb, p, c);
+				fsp.v.n.w = 1;
+				pixeln(params->fb, p, fsp.v.n);
 				delvattrs(&fsp.v);
 			}
 		break;