shithub: libgraphics

Download patch

ref: ec46c4ef5d7ebfcd08de2b7f1d336075ce4be0b2
parent: fb9a4985351424bcc5f44efc36cb39d8bc45e33e
author: rodri <rgl@antares-labs.eu>
date: Thu Apr 3 12:57:42 EDT 2025

perform perspective division outside of the raster loop.

also interpolate tangents for each vertex.

--- a/internal.h
+++ b/internal.h
@@ -71,6 +71,7 @@
 Vertex _dupvertex(Vertex*);
 void _lerpvertex(Vertex*, Vertex*, Vertex*, double);
 void _berpvertex(Vertex*, Vertex*, Vertex*, Vertex*, Point3);
+void _perspdiv(Vertex*, double);
 void _delvattrs(Vertex*);
 void _fprintvattrs(int, Vertex*);
 void _addvattr(Vertexattrs*, char*, int, void*);
--- a/render.c
+++ b/render.c
@@ -307,6 +307,10 @@
 		t.p1 = Pt2(prim->v[1].p.x, prim->v[1].p.y, 1);
 		t.p2 = Pt2(prim->v[2].p.x, prim->v[2].p.y, 1);
 
+		_perspdiv(prim->v+0, prim->v[0].p.w);
+		_perspdiv(prim->v+1, prim->v[1].p.w);
+		_perspdiv(prim->v+2, prim->v[2].p.w);
+
 		for(p.y = task->wr.min.y; p.y < task->wr.max.y; p.y++)
 		for(p.x = task->wr.min.x; p.x < task->wr.max.x; p.x++){
 			bc = _barycoords(t, Pt2(p.x+0.5,p.y+0.5,1));
@@ -322,9 +326,7 @@
 			pcz = 1.0/(pcz < ε1? ε1: pcz);
 
 			/* perspective-correct attribute interpolation  */
-			bc = modulapt3(bc, Vec3(prim->v[0].p.w*pcz,
-						prim->v[1].p.w*pcz,
-						prim->v[2].p.w*pcz));
+			bc = mulpt3(bc, pcz);
 			_berpvertex(fsp.v, &prim->v[0], &prim->v[1], &prim->v[2], bc);
 
 			fsp.p = p;
--- a/vertex.c
+++ b/vertex.c
@@ -57,6 +57,7 @@
 	v->n = lerp3(v0->n, v1->n, t);
 	v->c = lerp3(v0->c, v1->c, t);
 	v->uv = lerp2(v0->uv, v1->uv, t);
+	v->tangent = lerp3(v0->tangent, v1->tangent, t);
 	v->mtl = v0->mtl != nil? v0->mtl: v1->mtl;
 	for(i = 0; i < v0->nattrs; i++){
 		va.id = v0->attrs[i].id;
@@ -82,6 +83,7 @@
 	v->n = berp3(v0->n, v1->n, v2->n, bc);
 	v->c = berp3(v0->c, v1->c, v2->c, bc);
 	v->uv = berp2(v0->uv, v1->uv, v2->uv, bc);
+	v->tangent = berp3(v0->tangent, v1->tangent, v2->tangent, bc);
 	v->mtl = v0->mtl != nil? v0->mtl: v1->mtl != nil? v1->mtl: v2->mtl;
 	for(i = 0; i < v0->nattrs; i++){
 		va.id = v0->attrs[i].id;
@@ -91,6 +93,26 @@
 		else
 			va.n = fberp(v0->attrs[i].n, v1->attrs[i].n, v2->attrs[i].n, bc);
 		addvattr(v, &va);
+	}
+}
+
+/*
+ * perspective divide vertex attributes
+ */
+void
+_perspdiv(Vertex *v, double z⁻¹)
+{
+	Vertexattr *va;
+
+	v->n = mulpt3(v->n, z⁻¹);
+	v->c = mulpt3(v->c, z⁻¹);
+	v->uv = mulpt2(v->uv, z⁻¹);
+	v->tangent = mulpt3(v->tangent, z⁻¹);
+	for(va = v->attrs; va < v->attrs + v->nattrs; va++){
+		if(va->type == VAPoint)
+			va->p = mulpt3(va->p, z⁻¹);
+		else
+			va->n *= z⁻¹;
 	}
 }