summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2023-11-09 14:27:11 +0000
committerrodri <rgl@antares-labs.eu>2023-11-09 14:27:11 +0000
commitbc074b6ec9315ff530cfdf286d7860ba16881121 (patch)
treef4267dcc88850528e7c5caa3e5d947069652be99
parentf1ab29519b23f896b4b5ac078b8edc9c1dd7b828 (diff)
downloadtinyrend-bc074b6ec9315ff530cfdf286d7860ba16881121.tar.gz
tinyrend-bc074b6ec9315ff530cfdf286d7860ba16881121.tar.bz2
tinyrend-bc074b6ec9315ff530cfdf286d7860ba16881121.zip
Lesson 1: Triangle rasterization and back-face culling—First attempt
-rw-r--r--main.c79
1 files changed, 69 insertions, 10 deletions
diff --git a/main.c b/main.c
index 8b80de1..e23be2b 100644
--- a/main.c
+++ b/main.c
@@ -8,9 +8,12 @@
#include <keyboard.h>
#include <geometry.h>
+typedef Point Triangle[3];
+
Memimage *fb;
-Memimage *red;
+Memimage *red, *green, *blue;
+Channel *drawc;
void resized(void);
@@ -137,12 +140,60 @@ bresenham(Memimage *dst, Point p0, Point p1, Memimage *src)
}
}
+int
+ycoordsort(void *a, void *b)
+{
+ return ((Point*)a)->y - ((Point*)b)->y;
+}
+
void
triangle(Memimage *dst, Point p0, Point p1, Point p2, Memimage *src)
{
- bresenham(dst, p0, p1, src);
- bresenham(dst, p1, p2, src);
- bresenham(dst, p2, p0, src);
+ Triangle t;
+
+ t[0] = p0;
+ t[1] = p1;
+ t[2] = p2;
+
+ qsort(t, nelem(t), sizeof(Point), ycoordsort);
+
+ bresenham(dst, t[0], t[1], src);
+ bresenham(dst, t[1], t[2], src);
+ bresenham(dst, t[2], t[0], green);
+}
+
+void
+filltriangle(Memimage *dst, Point p0, Point p1, Point p2, Memimage *src)
+{
+ int y;
+ double m₀₂, m₀₁, m₁₂;
+ Point dp₀₂, dp₀₁, dp₁₂;
+ Triangle t;
+
+ t[0] = p0;
+ t[1] = p1;
+ t[2] = p2;
+
+ qsort(t, nelem(t), sizeof(Point), ycoordsort);
+
+ dp₀₂ = subpt(t[2], t[0]);
+ m₀₂ = (double)dp₀₂.x/dp₀₂.y;
+ dp₀₁ = subpt(t[1], t[0]);
+ m₀₁ = (double)dp₀₁.x/dp₀₁.y;
+ dp₁₂ = subpt(t[2], t[1]);
+ m₁₂ = (double)dp₁₂.x/dp₁₂.y;
+
+ fprint(2, "%P %P %P\n", t[0], t[1], t[2]);
+ fprint(2, "m₀₂ %g m₀₁ %g m₁₂ %g\n", m₀₂, m₀₁, m₁₂);
+
+ for(y = t[0].y; y <= t[1].y; y++)
+ bresenham(dst, Pt(t[0].x + (y-t[0].y)*m₀₂,y), Pt(t[0].x + (y-t[0].y)*m₀₁,y), src);
+ for(; y <= t[2].y; y++)
+ bresenham(dst, Pt(t[0].x + (y-t[0].y)*m₀₂,y), Pt(t[1].x + (y-t[1].y)*m₁₂,y), src);
+
+ bresenham(dst, t[0], t[1], src);
+ bresenham(dst, t[1], t[2], src);
+ bresenham(dst, t[2], t[0], green);
}
void
@@ -218,21 +269,28 @@ threadmain(int argc, char *argv[])
fb = eallocmemimage(screen->r, screen->chan);
red = rgb(DRed);
+ green = rgb(DGreen);
+ blue = rgb(DBlue);
bresenham(fb, Pt(40,40), Pt(300,300), red);
bresenham(fb, Pt(80,80), Pt(100,200), red);
bresenham(fb, Pt(80,80), Pt(200,100), red);
- triangle(fb, Pt(30,10), Pt(45, 45), Pt(5, 100), red);
+ filltriangle(fb, Pt(30,10), Pt(45, 45), Pt(5, 100), red);
+ triangle(fb, Pt(300,120), Pt(350,200), Pt(50, 210), red);
+ triangle(fb, Pt(300,130), Pt(350,80), Pt(50, 220), red);
+
+ drawc = chancreate(sizeof(void*), 1);
display->locking = 1;
unlockdisplay(display);
- redraw();
+ nbsend(drawc, nil);
for(;;){
- enum { MOUSE, RESIZE, KEYBOARD };
+ enum { MOUSE, RESIZE, KEYBOARD, DRAW };
Alt a[] = {
{mc->c, &mc->Mouse, CHANRCV},
{mc->resizec, nil, CHANRCV},
{kc->c, &r, CHANRCV},
+ {drawc, nil, CHANRCV},
{nil, nil, CHANEND}
};
@@ -246,9 +304,10 @@ threadmain(int argc, char *argv[])
case KEYBOARD:
key(r);
break;
+ case DRAW:
+ redraw();
+ break;
}
-
- redraw();
}
}
@@ -259,5 +318,5 @@ resized(void)
if(getwindow(display, Refnone) < 0)
sysfatal("couldn't resize");
unlockdisplay(display);
- redraw();
+ nbsend(drawc, nil);
}