From 50f15bac90638da401d27229969dc502c75d1320 Mon Sep 17 00:00:00 2001 From: rodri Date: Fri, 2 Aug 2024 17:57:42 +0000 Subject: fix line interpolation during rasterization. vertex attributes were not being updated after clipping with their corresponding work rectangles, nor when reordering the points before rasterization, which caused serious artifacts. --- clip.c | 34 +++++++++++++++++++++++++++++++--- internal.h | 3 ++- render.c | 6 +++--- vertex.c | 10 ++++++++++ 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/clip.c b/clip.c index a7750cf..9988ce1 100644 --- a/clip.c +++ b/clip.c @@ -193,11 +193,37 @@ outcode(Point p, Rectangle r) return code; } +/* lerp vertex attributes to match the new positions */ +void +adjustverts(Point *p0, Point *p1, Vertex *v0, Vertex *v1) +{ + Vertex v[2]; + Point3 dp; + Point Δp; + double len, perc; + + dp = subpt3(v1->p, v0->p); + len = hypot(dp.x, dp.y); + + Δp = subpt(Pt(v0->p.x, v0->p.y), *p0); + perc = len == 0? 0: hypot(Δp.x, Δp.y)/len; + lerpvertex(&v[0], v0, v1, perc); + + Δp = subpt(Pt(v0->p.x, v0->p.y), *p1); + perc = len == 0? 0: hypot(Δp.x, Δp.y)/len; + lerpvertex(&v[1], v0, v1, perc); + + delvattrs(v0); + delvattrs(v1); + *v0 = dupvertex(&v[0]); + *v1 = dupvertex(&v[1]); +} + /* * Cohen-Sutherland rectangle-line clipping */ int -rectclipline(Rectangle r, Point *p0, Point *p1) +rectclipline(Rectangle r, Point *p0, Point *p1, Vertex *v0, Vertex *v1) { int code0, code1; int Δx, Δy; @@ -211,14 +237,16 @@ rectclipline(Rectangle r, Point *p0, Point *p1) code0 = outcode(*p0, r); code1 = outcode(*p1, r); - if(lineisinside(code0, code1)) + if(lineisinside(code0, code1)){ + adjustverts(p0, p1, v0, v1); return 0; - else if(lineisoutside(code0, code1)) + }else if(lineisoutside(code0, code1)) return -1; if(ptisinside(code0)){ swappt(p0, p1); swapi(&code0, &code1); + swapvertex(v0, v1); } if(code0 & CLIPL){ diff --git a/internal.h b/internal.h index f34776a..777ace8 100644 --- a/internal.h +++ b/internal.h @@ -45,6 +45,7 @@ void rmfbctl(Framebufctl*); /* vertex */ Vertex dupvertex(Vertex*); +void swapvertex(Vertex*, Vertex*); void lerpvertex(Vertex*, Vertex*, Vertex*, double); void berpvertex(Vertex*, Vertex*, Vertex*, Vertex*, Point3); void delvattrs(Vertex*); @@ -52,7 +53,7 @@ void fprintvattrs(int, Vertex*); /* clip */ int clipprimitive(Primitive*, Primitive*); -int rectclipline(Rectangle, Point*, Point*); +int rectclipline(Rectangle, Point*, Point*, Vertex*, Vertex*); /* util */ int min(int, int); diff --git a/render.c b/render.c index 98dd0e9..549ee1a 100644 --- a/render.c +++ b/render.c @@ -128,7 +128,7 @@ rasterize(Rastertask *task) p0 = Pt(prim.v[0].p.x, prim.v[0].p.y); p1 = Pt(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, &prim.v[0], &prim.v[1]) < 0) break; /* transpose the points */ @@ -140,8 +140,8 @@ rasterize(Rastertask *task) /* make them left-to-right */ if(p0.x > p1.x){ - swapi(&p0.x, &p1.x); - swapi(&p0.y, &p1.y); + swappt(&p0, &p1); + swapvertex(&prim.v[0], &prim.v[1]); } dp = subpt(p1, p0); diff --git a/vertex.c b/vertex.c index 970bbbc..92c6b0a 100644 --- a/vertex.c +++ b/vertex.c @@ -43,6 +43,16 @@ dupvertex(Vertex *v) return nv; } +void +swapvertex(Vertex *a, Vertex *b) +{ + Vertex t; + + t = *a; + *a = *b; + *b = t; +} + /* * linear attribute interpolation */ -- cgit v1.2.3