summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2024-08-02 17:57:42 +0000
committerrodri <rgl@antares-labs.eu>2024-08-02 17:57:42 +0000
commit50f15bac90638da401d27229969dc502c75d1320 (patch)
tree2f8bf3b8df50292938d5bca01eb3c0ef3ff1f12f
parent3bf0f4fdcf9e1a61881c20ee8162924f952ba8e0 (diff)
downloadlibgraphics-50f15bac90638da401d27229969dc502c75d1320.tar.gz
libgraphics-50f15bac90638da401d27229969dc502c75d1320.tar.bz2
libgraphics-50f15bac90638da401d27229969dc502c75d1320.zip
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.
-rw-r--r--clip.c34
-rw-r--r--internal.h3
-rw-r--r--render.c6
-rw-r--r--vertex.c10
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
*/