summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2023-11-09 16:28:00 +0000
committerrodri <rgl@antares-labs.eu>2023-11-09 16:28:00 +0000
commit65bcb3493e643608ca4fbc77baf2ebef9a1244e6 (patch)
tree72aeb13303567ae58f8e281ce4992b2c20b738ee
parent26b6967a3701eb7a87f561ab60df5161d6d3f5bd (diff)
downloadtinyrend-65bcb3493e643608ca4fbc77baf2ebef9a1244e6.tar.gz
tinyrend-65bcb3493e643608ca4fbc77baf2ebef9a1244e6.tar.bz2
tinyrend-65bcb3493e643608ca4fbc77baf2ebef9a1244e6.zip
Lesson 1: Triangle rasterization and back-face culling—Triangle shader
-rw-r--r--main.c83
-rw-r--r--mkfile1
2 files changed, 73 insertions, 11 deletions
diff --git a/main.c b/main.c
index 2aaeb01..2581117 100644
--- a/main.c
+++ b/main.c
@@ -16,8 +16,9 @@ Memimage *red, *green, *blue;
Channel *drawc;
void resized(void);
+uvlong nanosec(void);
-void*
+void *
emalloc(ulong n)
{
void *p;
@@ -29,7 +30,7 @@ emalloc(ulong n)
return p;
}
-void*
+void *
erealloc(void *p, ulong n)
{
void *np;
@@ -47,7 +48,7 @@ erealloc(void *p, ulong n)
return np;
}
-Image*
+Image *
eallocimage(Display *d, Rectangle r, ulong chan, int repl, ulong col)
{
Image *i;
@@ -58,7 +59,7 @@ eallocimage(Display *d, Rectangle r, ulong chan, int repl, ulong col)
return i;
}
-Memimage*
+Memimage *
eallocmemimage(Rectangle r, ulong chan)
{
Memimage *i;
@@ -70,7 +71,19 @@ eallocmemimage(Rectangle r, ulong chan)
return i;
}
-Memimage*
+int
+min(int a, int b)
+{
+ return a < b? a: b;
+}
+
+int
+max(int a, int b)
+{
+ return a > b? a: b;
+}
+
+Memimage *
rgb(ulong c)
{
Memimage *i;
@@ -87,10 +100,12 @@ pixel(Memimage *dst, Point p, Memimage *src)
{
Rectangle r;
- r.min = addpt(dst->r.min, p);
- r.max = addpt(r.min, Pt(1,1));
+ if(dst == nil || src == nil)
+ return;
- memimagedraw(dst, r, src, ZP, nil, ZP, SoverD);
+ r = rectaddpt(Rect(0,0,1,1), p);
+
+ memimagedraw(dst, rectaddpt(r, dst->r.min), src, ZP, nil, ZP, SoverD);
}
void
@@ -183,16 +198,54 @@ filltriangle(Memimage *dst, Point p0, Point p1, Point p2, Memimage *src)
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₁₂);
-
+ /* first half */
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);
+ /* second half */
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);
}
void
+shade(Memimage *dst, Memimage *(*shader)(Point))
+{
+ Point p;
+ Memimage *c;
+
+ p = ZP;
+ for(; p.y < Dy(dst->r); p.y++)
+ for(p.x = 0; p.x < Dx(dst->r); p.x++)
+ if((c = shader(p)) != nil)
+ pixel(dst, p, c);
+}
+
+Memimage *
+triangleshader(Point p)
+{
+ Triangle2 t;
+ Rectangle bbox;
+ Point3 bc;
+
+ t.p0 = Pt2(240,200,1);
+ t.p1 = Pt2(400,40,1);
+ t.p2 = Pt2(240,40,1);
+
+ bbox = Rect(
+ min(min(t.p0.x, t.p1.x), t.p2.x),
+ min(min(t.p0.y, t.p1.y), t.p2.y),
+ max(max(t.p0.x, t.p1.x), t.p2.x),
+ max(max(t.p0.y, t.p1.y), t.p2.y)
+ );
+ if(!ptinrect(p, bbox))
+ return nil;
+
+ bc = barycoords(t, Pt2(p.x,p.y,1));
+ if(bc.x < 0 || bc.y < 0 || bc.z < 0)
+ return nil;
+ return red;
+}
+
+void
redraw(void)
{
lockdisplay(display);
@@ -244,6 +297,7 @@ threadmain(int argc, char *argv[])
Mousectl *mc;
Keyboardctl *kc;
Rune r;
+ uvlong t0, t1;
GEOMfmtinstall();
ARGBEGIN{
@@ -267,9 +321,11 @@ threadmain(int argc, char *argv[])
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);
+
filltriangle(fb, Pt(30,10), Pt(45, 45), Pt(5, 100), blue);
triangle(fb, Pt(30,10), Pt(45, 45), Pt(5, 100), red);
filltriangle(fb, Pt(300,120), Pt(200,350), Pt(50, 210), blue);
@@ -277,6 +333,11 @@ threadmain(int argc, char *argv[])
filltriangle(fb, Pt(400,230), Pt(450,180), Pt(150, 320), blue);
triangle(fb, Pt(400,230), Pt(450,180), Pt(150, 320), red);
+ t0 = nanosec();
+ shade(fb, triangleshader);
+ t1 = nanosec();
+ fprint(2, "shader took %lludns\n", t1-t0);
+
drawc = chancreate(sizeof(void*), 1);
display->locking = 1;
diff --git a/mkfile b/mkfile
index f877b5a..ed46965 100644
--- a/mkfile
+++ b/mkfile
@@ -4,5 +4,6 @@ BIN=/$objtype/bin
TARG=tinyrend
OFILES=\
main.$O\
+ nanosec.$O\
</sys/src/cmd/mkone