From 24097f5aacbf46ec1500ab84a60bade28b53a301 Mon Sep 17 00:00:00 2001 From: quou Date: Mon, 15 Jul 2024 21:08:33 +1000 Subject: Screen space clipping and backface culling. --- render.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 125 insertions(+), 39 deletions(-) (limited to 'render.c') diff --git a/render.c b/render.c index e0061fa..e225bb6 100644 --- a/render.c +++ b/render.c @@ -149,14 +149,19 @@ Colour col_mul(Colour a, Colour b) { void ren_begin(Renderer* r, Colour* t, int* d, int w, int h) { r->t = t; - r->w = w; - r->h = h; + r->vp[2] = w; + r->vp[3] = h; r->d = d; r->clip.x = 0; r->clip.y = 0; r->clip.w = w; r->clip.h = h; + r->vp[0] = 0; + r->vp[1] = 0; + r->vp[2] = w; + r->vp[3] = h; r->asp = (w << fbits) / h; + r->n = 8; } void ren_end(Renderer* r) { @@ -165,21 +170,21 @@ void ren_end(Renderer* r) { void ren_clear(Renderer* r) { Colour* d = r->t, b = { 0 }; - int i = 0, e = r->w * r->h; + int i = 0, e = r->vp[2] * r->vp[3]; for (i = 0; i < e; i++, d++) *d = b; } void ren_clearc(Renderer* r, Colour c) { Colour* d = r->t; - int i = 0, e = r->w * r->h; + int i = 0, e = r->vp[2] * r->vp[3]; for (i = 0; i < e; i++, d++) *d = c; } void ren_cleard(Renderer* r, int depth) { int* d = r->d; - int i = 0, e = r->w * r->h; + int i = 0, e = r->vp[2] * r->vp[3]; for (i = 0; i < e; i++, d++) *d = depth; } @@ -191,9 +196,9 @@ void ren_clip(Renderer* r, const Rect* c) { void ren_point(Renderer* r, Colour c, int x, int y) { if (x < 0) return; if (y < 0) return; - if (x >= r->w) return; - if (y >= r->h) return; - r->t[x + y * r->w] = c; + if (x >= r->vp[2]) return; + if (y >= r->vp[3]) return; + r->t[x + y * r->vp[2]] = c; } #define imp_ren_char(chw, chh, fw, data) \ @@ -207,8 +212,8 @@ void ren_point(Renderer* r, Colour c, int x, int y) { rect_clips(&re, &sub, &r->clip); \ ex = re.x + re.w; \ ey = re.y + re.h; \ - dst = r->t + (re.x + re.y * r->w); \ - s = r->w - re.w; \ + dst = r->t + (re.x + re.y * r->vp[2]); \ + s = r->vp[2] - re.w; \ for (j = re.y, l = sub.y; j < ey; j++, l++) { \ for (i = re.x, k = sub.x; i < ex; i++, k++) { \ int si = k + l * fw; \ @@ -296,6 +301,16 @@ int tri_hand( (v2[0] - v0[0]) * (v1[1] - v0[1]) > 0; } +int tri_winding( + const int* v0, + const int* v1, + const int* v2 +) { + return + (v1[1] - v0[1]) * (v2[0] - v1[0]) - + (v1[0] - v0[0]) * (v2[1] - v1[1]); +} + Colour sample_tex( const Bitmap* t, int u, @@ -370,10 +385,13 @@ void ren_tri( #define ic 6 #define ec 8 int ha, i; + const int fcx = r->clip.x + r->clip.w; + const int fcy = r->clip.y + r->clip.h; 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 */ + if (tri_winding(iv0, iv1, iv2) > 0) return; vec_cpy(v0, iv0, ec); vec_cpy(v1, iv1, ec); vec_cpy(v2, iv2, ec); @@ -415,30 +433,36 @@ void ren_tri( ); } } + if (v0[1] > fcy) return; + if (v1[1] > fcy) v1[1] = fcy; #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; \ - } \ + int x, ex = mini(fe.x, fcx);\ + if (fe.y >= r->clip.y) { \ for (i = 0; i < ic; i++)\ - while (xi[i].y != x)\ - step_line(&xi[i]);\ + init_lerp(\ + &xi[i],\ + ni[i].x, fi[i].x,\ + ne.x, fe.x\ + );\ + for (x = ne.x; x < ex; x++) {\ + Colour col;\ + if (x >= r->clip.x) { \ + 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->vp[2]]) { \ + r->t[x + fe.y * r->vp[2]] = col_mul(\ + sample_tex(tex, xi[1].x, xi[2].x),\ + col\ + );\ + r->d[x + fe.y * r->vp[2]] = 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++)\ @@ -469,6 +493,7 @@ void ren_tri( v1[1], v2[1] ); } + if (v2[1] > fcy) v2[1] = fcy; while (fe.y < v2[1]) { scanline } @@ -477,6 +502,67 @@ void ren_tri( #undef ec } +#define max_clip 6 + +void ren_tri3( + Renderer* r, + const int* iv0, + const int* iv1, + const int* iv2, + const Bitmap* tex +) { +#define ec 8 +#define ec2 (ec * 2) + int tri[ec2 * 3]; + int tc = 1, i; + vec_cpy(&tri[0], iv0, ec); + vec_cpy(&tri[8], iv1, ec); + vec_cpy(&tri[16], iv2, ec); + for (i = 0; i < tc; i++) { + int ti = i * ec, j; + for (j = 0; j < 3; j++) { + int vi = ti + j * ec; + persp(&tri[vi], r->asp); + ndc2clip(r->vp, &tri[vi]); + } + if (!tri_os(r, &tri[0], &tri[8], &tri[16])) + continue; + ren_tri( + r, + &tri[ti], + &tri[ti + 8], + &tri[ti + 16], + tex + ); + } +#undef ec +#undef ec2 +} + +int tri_os( + const Renderer* r, + const int* v0, + const int* v1, + const int* v2 +) { + return + point_os(r, v0[0], v0[1]) || + point_os(r, v1[0], v1[1]) || + point_os(r, v2[0], v2[1]); +} + +int point_os( + const Renderer* r, + int x, + int y +) { + return + x >= r->vp[0] && + y >= r->vp[1] && + x < r->vp[2] && + y < r->vp[3]; +} + void ren_mesh( Renderer* r, const Mesh* m, @@ -485,19 +571,19 @@ void ren_mesh( int vc = m->vc; int tri[8 * 3]; int n[4]; - int i, asp = r->asp; + int i; for (i = 0; i < vc; i += 3) { int j; for (j = 0; j < 3; j++) { Mesh_Vert v = m->verts[i + j]; int* wv = &tri[j * 8]; - wv[0] = m->p[v.p * 3 + 0]; - wv[1] = m->p[v.p * 3 + 1]; - wv[2] = m->p[v.p * 3 + 2]; + vec_cpy(wv, &m->p[v.p * 3], 3); wv[3] = f1; mtx_apply(mtx_peek(), wv); - persp(wv, asp); - ndc2clip((int*)&r->clip, wv); + } + for (j = 0; j < 3; j++) { + Mesh_Vert v = m->verts[i + j]; + int* wv = &tri[j * 8]; n[0] = m->n[v.n * 3 + 0]; n[1] = m->n[v.n * 3 + 1]; n[2] = m->n[v.n * 3 + 2]; @@ -521,7 +607,7 @@ void ren_mesh( wv[7] = l; } } - ren_tri(r, &tri[0], &tri[8], &tri[16], tex); + ren_tri3(r, &tri[0], &tri[8], &tri[16], tex); } } -- cgit v1.2.3-54-g00ecf