diff options
author | quou <quou@disroot.org> | 2024-07-07 19:52:51 +1000 |
---|---|---|
committer | quou <quou@disroot.org> | 2024-07-13 16:38:52 +1000 |
commit | 18b4f4c51aceb21f6ea8cad48d7582f40605e994 (patch) | |
tree | a2610e63cc4d4ab3a589084c7f4009e858ac8ca1 /render.c | |
parent | 80078a8335bef14e417d219aa8006a6c926370ef (diff) |
Better triangle fill and texture mapping.
Diffstat (limited to 'render.c')
-rw-r--r-- | render.c | 246 |
1 files changed, 165 insertions, 81 deletions
@@ -1,6 +1,7 @@ #include "maths.h" #include "plat.h" #include "render.h" +#include <stdlib.h> static int font_w = 960; static unsigned font_data[] = { @@ -122,6 +123,14 @@ Colour blend_mod(Colour dst, Colour src, Colour mod) { return dst; } +Colour col_mul(Colour a, Colour b) { + Colour r; + r.r = (a.r * b.r) >> 8; + r.g = (a.g * b.g) >> 8; + r.b = (a.b * b.b) >> 8; + r.a = (a.a * b.a) >> 8; + return r; +} void ren_begin(Renderer* r, Colour* t, int* d, int w, int h) { r->t = t; @@ -234,25 +243,84 @@ int tri_hand( (v2[0] - v0[0]) * (v1[1] - v0[1]) > 0; } -#define max_tri_ec 8 +Colour sample_tex( + const Bitmap* t, + int u, + int v +) { + int x = (u * t->w) >> fbits; + int y = (v * t->h) >> fbits; + x &= t->w - 1; + y &= t->h - 1; + return t->p[x + y * t->w]; +} + +typedef struct { + int x, y; + int dx, dy; + int sx, sy; + int e; +} Line; + +void init_line( + Line* l, + const int* f, + const int* t +) { + const int dx = abs(t[0] - f[0]); + const int dy = -abs(t[1] - f[1]); + l->e = dx + dy; + l->dx = dx; + l->dy = dy; + l->sx = f[0] < t[0]? 1: -1; + l->sy = f[1] < t[1]? 1: -1; + l->x = f[0]; + l->y = f[1]; +} + +void init_lerp( + Line* l, + int a, int b, + int x, int y +) { + int f[2], t[2]; + f[0] = a; + f[1] = x; + t[0] = b; + t[1] = y; + init_line(l, f, t); +} + +void step_line( + Line* l +) { + const int e2 = l->e * 2; + const int dx = l->dx; + const int dy = l->dy; + if (e2 > dy) { + l->e += dy; + l->x += l->sx; + } + if (e2 <= dx) { + l->e += dx; + l->y += l->sy; + } +} void ren_tri( Renderer* r, - Colour c, const int* iv0, const int* iv1, const int* iv2, - Tri_Mode mode + const Bitmap* tex ) { - int ec, sx, ex, x, y, me, ms, e, ha; - int sb = 0, * d; - int v0[max_tri_ec], v1[max_tri_ec], v2[max_tri_ec]; - switch (mode) { - case tri_mode_flat: - ec = 2; - break; - default: assert(0); - } +#define ic 6 +#define ec 8 + int ha, i; + int v0[ec], v1[ec], v2[ec]; + Line ne, fe; /* near and far edges */ + Line ni[ic], fi[ic]; /* near and far interpolants */ + Line xi[ic]; /* scanline interpolant */ vec_cpy(v0, iv0, ec); vec_cpy(v1, iv1, ec); vec_cpy(v2, iv2, ec); @@ -263,80 +331,96 @@ void ren_tri( if (v0[1] > v1[1]) swap_vert(v0, v1, ec); ha = tri_hand(v0, v1, v2); - sb = v1[1] == v2[1]; - if (v0[1] == v1[1]) goto rb; if (ha) { - ms = - ((v2[0] - v0[0]) << fbits) / - (v2[1] - v0[1]); - me = - ((v1[0] - v0[0]) << fbits) / - (v1[1] - v0[1]); - sx = v0[0] << fbits; - ex = v0[0] << fbits; + init_line(&ne, v0, v2); + init_line(&fe, v0, v1); + for (i = 0; i < ic; i++) { + init_lerp( + &ni[i], + v0[2 + i], v2[2 + i], + v0[1], v2[1] + ); + init_lerp( + &fi[i], + v0[2 + i], v1[2 + i], + v0[1], v1[1] + ); + } } else { - ms = - ((v1[0] - v0[0]) << fbits) / - (v1[1] - v0[1]); - me = - ((v2[0] - v0[0]) << fbits) / - (v2[1] - v0[1]); - sx = v0[0] << fbits; - ex = v0[0] << fbits; - } - for ( - y = v0[1]; - y <= v1[1]; - y++, sx += ms, ex += me - ) for ( - x = sx >> fbits, - e = ex >> fbits; - x < e; - x++ - ) { - d = &r->d[x + y * r->w]; - if (*d > v0[2]) { - *d = v0[2]; - r->t[x + y * r->w] = c; - } + init_line(&ne, v0, v1); + init_line(&fe, v0, v2); + for (i = 0; i < ic; i++) { + init_lerp( + &ni[i], + v0[2 + i], v1[2 + i], + v0[1], v1[1] + ); + init_lerp( + &fi[i], + v0[2 + i], v2[2 + i], + v0[1], v2[1] + ); } -rb: - if (sb) return; + } +#define scanline\ + int x;\ + for (i = 0; i < ic; i++)\ + init_lerp(\ + &xi[i],\ + ni[i].x, fi[i].x,\ + ne.x, fe.x\ + );\ + for (x = ne.x; x < fe.x; x++) {\ + Colour col;\ + col.r = (xi[3].x * 255) >> fbits;\ + col.g = (xi[4].x * 255) >> fbits;\ + col.b = (xi[5].x * 255) >> fbits;\ + col.a = 0xff;\ + if (xi[0].x < r->d[x + fe.y * r->w]) { \ + r->t[x + fe.y * r->w] = col_mul(\ + sample_tex(tex, xi[1].x, xi[2].x),\ + col\ + );\ + r->d[x + fe.y * r->w] = xi[0].x; \ + } \ + for (i = 0; i < ic; i++)\ + while (xi[i].y != x)\ + step_line(&xi[i]);\ + }\ + step_line(&fe);\ + for (i = 0; i < ic; i++)\ + while (fi[i].y != fe.y)\ + step_line(&fi[i]);\ + while (ne.y != fe.y)\ + step_line(&ne);\ + for (i = 0; i < ic; i++)\ + while (ni[i].y != ne.y)\ + step_line(&ni[i]); + while (fe.y < v1[1]) { + scanline + } if (ha) { - ms = ((v2[0] - v0[0]) << fbits) / - (v2[1] - v0[1]); - me = - ((v2[0] - v1[0]) << fbits) / - (v2[1] - v1[1]); - sx = - (v0[0] << fbits) + (v1[1] - v0[1]) * ms + 1; - ex = v1[0] << fbits; + init_line(&fe, v1, v2); + for (i = 0; i < ic; i++) + init_lerp( + &fi[i], + v1[2 + i], v2[2 + i], + v1[1], v2[1] + ); } else { - me = - ((v2[0] - v0[0]) << fbits) / - (v2[1] - v0[1]); - ms = - ((v2[0] - v1[0]) << fbits) / - (v2[1] - v1[1]); - sx = v1[0] << fbits; - ex = - (v0[0] << fbits) + (v1[1] - v0[1]) * me + 1; + init_line(&ne, v1, v2); + for (i = 0; i < ic; i++) + init_lerp( + &ni[i], + v1[2 + i], v2[2 + i], + v1[1], v2[1] + ); } - for ( - y = v1[1]; - y <= v2[1]; - y++, sx += ms, ex += me - ) for ( - x = sx >> fbits, - e = ex >> fbits; - x < e; - x++ - ) { - d = &r->d[x + y * r->w]; - if (*d > v0[2]) { - *d = v0[2]; - r->t[x + y * r->w] = c; - } - } + while (fe.y < v2[1]) { + scanline + } +#undef scanline +#undef ic +#undef ec } |