summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2024-05-21 16:59:33 +0000
committerrodri <rgl@antares-labs.eu>2024-05-21 16:59:33 +0000
commite2e203e6fa64a9e57c8d4ba4cea4deec89d8f0c1 (patch)
tree2efb6edd3f707b302d54d91c7184ddba973ee670
parentd3516b11559657935d70829c672f29393e857b8e (diff)
downloadlibgraphics-e2e203e6fa64a9e57c8d4ba4cea4deec89d8f0c1.tar.gz
libgraphics-e2e203e6fa64a9e57c8d4ba4cea4deec89d8f0c1.tar.bz2
libgraphics-e2e203e6fa64a9e57c8d4ba4cea4deec89d8f0c1.zip
fix line rasterization.
-rw-r--r--clip.c35
-rw-r--r--render.c11
-rw-r--r--xform.c3
3 files changed, 31 insertions, 18 deletions
diff --git a/clip.c b/clip.c
index 18019fc..bcfcabf 100644
--- a/clip.c
+++ b/clip.c
@@ -53,6 +53,21 @@ cleanpoly(Polygon *p)
p->n = 0;
}
+static void
+fprintpoly(int fd, Polygon *p)
+{
+ int i;
+
+ for(i = 0; i < p->n; i++)
+ fprint(fd, "%d/%lud p %V\n", i, p->n, p->v[i].p);
+}
+
+static int
+eqpt3(Point3 a, Point3 b)
+{
+ return vec3len(subpt3(a, b)) < 1e-6;
+}
+
/*
* references:
* - James F. Blinn, Martin E. Newell, “Clipping Using Homogeneous Coordinates”,
@@ -76,9 +91,9 @@ clipprimitive(Primitive *p)
double d0, d1, perc;
Polygon Vin, Vout;
Vertex *v0, *v1, v; /* edge verts and new vertex (line-plane intersection) */
- int i, j, nt;
+ int i, j, np;
- nt = 0;
+ np = 0;
memset(&Vin, 0, sizeof Vin);
memset(&Vout, 0, sizeof Vout);
for(i = 0; i < p[0].type+1; i++)
@@ -119,30 +134,30 @@ allin:
cleanpoly(&Vout);
else switch(p[0].type){
case PLine:
- /* TODO fix line clipping (they disappear instead, why?) */
p[0].v[0] = dupvertex(&Vout.v[0]);
- p[0].v[1] = dupvertex(&Vout.v[1]);
+ p[0].v[1] = eqpt3(Vout.v[0].p, Vout.v[1].p)? dupvertex(&Vout.v[2]): dupvertex(&Vout.v[1]);
cleanpoly(&Vout);
+ np = 1;
break;
case PTriangle:
/* triangulate */
- for(i = 0; i < Vout.n-2; i++, nt++){
+ for(i = 0; i < Vout.n-2; i++, np++){
/*
* when performing fan triangulation, indices 0 and 2
* are referenced on every triangle, so duplicate them
* to avoid complications during rasterization.
*/
- memmove(&p[nt], &p[0], sizeof *p);
- p[nt].v[0] = i < Vout.n-2-1? dupvertex(&Vout.v[0]): Vout.v[0];
- p[nt].v[1] = Vout.v[i+1];
- p[nt].v[2] = i < Vout.n-2-1? dupvertex(&Vout.v[i+2]): Vout.v[i+2];
+ memmove(&p[np], &p[0], sizeof *p);
+ p[np].v[0] = i < Vout.n-2-1? dupvertex(&Vout.v[0]): Vout.v[0];
+ p[np].v[1] = Vout.v[i+1];
+ p[np].v[2] = i < Vout.n-2-1? dupvertex(&Vout.v[i+2]): Vout.v[i+2];
}
break;
}
free(Vout.v);
free(Vin.v);
- return nt;
+ return np;
}
static int
diff --git a/render.c b/render.c
index f0fffd7..400c268 100644
--- a/render.c
+++ b/render.c
@@ -119,11 +119,12 @@ rasterize(Rastertask *task)
dplen = hypot(dp.x, dp.y);
perc = dplen == 0? 0: hypot(Δp.x, Δp.y)/dplen;
- /* TODO it seems depth testing messes with the output. find out why */
+ if(steep) swapi(&p.x, &p.y);
+
z = flerp(prim.v[0].p.z, prim.v[1].p.z, perc);
depth = fclamp(z, 0, 1);
- if(depth <= params->fb->zb[p.x + p.y*Dx(params->fb->r)])
- continue;
+ if(!ptinrect(p, params->fb->r) || depth <= params->fb->zb[p.x + p.y*Dx(params->fb->r)])
+ goto discard;
params->fb->zb[p.x + p.y*Dx(params->fb->r)] = depth;
/* interpolate z⁻¹ and get actual z */
@@ -134,15 +135,13 @@ rasterize(Rastertask *task)
perc *= prim.v[0].p.w * z;
lerpvertex(&fsp.v, &prim.v[0], &prim.v[1], perc);
- if(steep) swapi(&p.x, &p.y);
-
fsp.p = p;
c = params->fshader(&fsp);
memfillcolor(params->frag, col2ul(c));
pixel(params->fb->cb, p, params->frag);
delvattrs(&fsp.v);
-
+discard:
if(steep) swapi(&p.x, &p.y);
e += Δe;
diff --git a/xform.c b/xform.c
index aba2089..b6e4397 100644
--- a/xform.c
+++ b/xform.c
@@ -145,13 +145,12 @@ perspective(Matrix3 m, double fovy, double a, double n, double f)
double cotan;
cotan = 1/tan(fovy/2);
- identity3(m);
+ memset(m, 0, 4*4*sizeof(double));
m[0][0] = cotan/a;
m[1][1] = cotan;
m[2][2] = (f+n)/(f-n);
m[2][3] = 2*f*n/(f-n);
m[3][2] = -1;
- m[3][3] = 0;
}
void