From 951f6115c16c3ab482c19705344295c90af1625b Mon Sep 17 00:00:00 2001 From: quou Date: Sat, 27 Jul 2024 11:15:21 +1000 Subject: clipping and viewport improvements. --- 3de.c | 13 ++++++-- maths.c | 4 +-- rect.c | 44 +++++++++++++++++++++++++ rect.h | 2 ++ render.c | 111 +++++++++++++++++++++++++++++++++++++++------------------------ render.h | 10 ++++-- 6 files changed, 136 insertions(+), 48 deletions(-) diff --git a/3de.c b/3de.c index eb7a8f8..e18b643 100644 --- a/3de.c +++ b/3de.c @@ -43,6 +43,12 @@ void draw_tri(Renderer* r, int x, int y) { ren_tri(r, v0, v1, v2, tex); } +void draw_line(Renderer* r, int x, int y) { + int s[] = { 100, 100 }; + int e[] = { x, y }; + ren_line(r, make_red(), s, e); +} + int entrypoint(int argc, const char** argv, Arena* a) { App* app; Renderer r = { 0 }; @@ -83,10 +89,12 @@ int entrypoint(int argc, const char** argv, Arena* a) { while (app->o) { fps_begin(&f); while (f.now >= f.next) { + Rect clip = { 30, 80, 400, 800 }; app_begin(app); update_player(&p, &s); ren_begin(&r, app->fb, depth, app->w, app->h); - ren_clear(&r); + ren_clip(&r, &clip); + ren_clearc(&r, make_blue()); ren_cleard(&r, f1 * 300); sprintf(buf, "FPS: %d", app->fps); ren_texts(&r, blue, 3, 3, buf); @@ -94,10 +102,11 @@ int entrypoint(int argc, const char** argv, Arena* a) { ren_texts(&r, blue, 3, 8, buf); sprintf(buf, "MOUSE: %d, %d", app->mx, app->my); ren_texts(&r, blue, 3, 13, buf); + draw_line(&r, app->mx, app->my); push_player_cam(&p); draw_gun(&r); pop_player_cam(); - /*draw_tri(&r, app->mx, app->my);*/ + draw_tri(&r, app->mx, app->my); ren_end(&r); app_end(app); fps_update(&f); diff --git a/maths.c b/maths.c index 706c12b..70b354e 100644 --- a/maths.c +++ b/maths.c @@ -290,8 +290,8 @@ int* persp(int* v, int asp) { } int* ndc2clip(const int* c, int* p) { - register int hw = c[2] >> 1; - register int hh = c[3] >> 1; + register int hw = c[0] >> 1; + register int hh = c[1] >> 1; p[0] = ((hw << fbits) * p[0]) >> fbits; p[1] = ((hh << fbits) * -p[1]) >> fbits; p[0] >>= fbits; diff --git a/rect.c b/rect.c index c72c66e..e3d3948 100644 --- a/rect.c +++ b/rect.c @@ -19,6 +19,24 @@ Rect* rect_clip(Rect* r, const Rect* c) { return r; } +Rect* rect_clipr(Rect* r, const int* c) { + int n; + int x = r->x, y = r->y; + if ((n = c[0] - r->x) > 0) { + r->w -= n; + r->x += n; + } + if ((n = c[1] - r->y) > 0) { + r->h -= n; + r->y += n; + } + if ((n = x + r->w - c[2]) > 0) + r->w -= n; + if ((n = y + r->h - c[3]) > 0) + r->h -= n; + return r; +} + Rect* rect_clips(Rect* r, Rect* s, const Rect* c) { int n; int x = r->x, y = r->y; @@ -44,3 +62,29 @@ Rect* rect_clips(Rect* r, Rect* s, const Rect* c) { } return r; } + +Rect* rect_clipsr(Rect* r, Rect* s, const int* c) { + int n; + int x = r->x, y = r->y; + if ((n = c[0] - r->x) > 0) { + r->w -= n; + r->x += n; + s->w -= n; + s->x += n; + } + if ((n = c[1] - r->y) > 0) { + r->h -= n; + r->y += n; + s->h -= n; + s->y += n; + } + if ((n = x + r->w - c[2]) > 0) { + r->w -= n; + s->w -= n; + } + if ((n = y + r->h - c[3]) > 0) { + r->h -= n; + s->h -= n; + } + return r; +} diff --git a/rect.h b/rect.h index b055607..74f3084 100644 --- a/rect.h +++ b/rect.h @@ -6,6 +6,8 @@ typedef struct { } Rect; Rect* rect_clip(Rect* r, const Rect* c); +Rect* rect_clipr(Rect* r, const int* c); Rect* rect_clips(Rect* r, Rect* s, const Rect* c); +Rect* rect_clipsr(Rect* r, Rect* s, const int* c); #endif diff --git a/render.c b/render.c index 233c084..c8b673b 100644 --- a/render.c +++ b/render.c @@ -149,17 +149,13 @@ Colour col_mul(Colour a, Colour b) { void ren_begin(Renderer* r, Colour* t, int* d, int w, int h) { r->t = t; - r->vp[2] = w; - r->vp[3] = h; + r->vp[0] = w; + r->vp[1] = 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->clip[0] = 0; + r->clip[1] = 0; + r->clip[2] = w; + r->clip[3] = h; r->asp = (w << fbits) / h; r->n = 256; } @@ -169,36 +165,49 @@ void ren_end(Renderer* r) { } void ren_clear(Renderer* r) { - Colour* d = r->t, b = { 0 }; - int i = 0, e = r->vp[2] * r->vp[3]; - for (i = 0; i < e; i++, d++) - *d = b; + Colour c = { 0 }; + ren_clearc(r, c); } void ren_clearc(Renderer* r, Colour c) { - Colour* d = r->t; - int i = 0, e = r->vp[2] * r->vp[3]; - for (i = 0; i < e; i++, d++) - *d = c; + Colour* d = &r->t[r->clip[0] + r->clip[1] * r->vp[0]]; + int s = r->vp[0] - (r->clip[2] - r->clip[0]), y; + for (y = r->clip[1]; y < r->clip[3]; y++) { + int x; + for (x = r->clip[0]; x < r->clip[2]; x++) { + *d = c; + d++; + } + d += s; + } } void ren_cleard(Renderer* r, int depth) { - int* d = r->d; - int i = 0, e = r->vp[2] * r->vp[3]; - for (i = 0; i < e; i++, d++) - *d = depth; + int* d = &r->d[r->clip[0] + r->clip[1] * r->vp[0]]; + int s = r->vp[0] - (r->clip[2] - r->clip[0]), y; + for (y = r->clip[1]; y < r->clip[3]; y++) { + int x; + for (x = r->clip[0]; x < r->clip[2]; x++) { + *d = depth; + d++; + } + d += s; + } } void ren_clip(Renderer* r, const Rect* c) { - r->clip = *c; + r->clip[0] = c->x; + r->clip[1] = c->y; + r->clip[2] = c->x + c->w; + r->clip[3] = c->y + c->h; } void ren_point(Renderer* r, Colour c, int x, int y) { - if (x < 0) return; - if (y < 0) return; - if (x >= r->vp[2]) return; - if (y >= r->vp[3]) return; - r->t[x + y * r->vp[2]] = c; + if (x < r->clip[0]) return; + if (y < r->clip[1]) return; + if (x >= r->clip[2]) return; + if (y >= r->clip[3]) return; + r->t[x + y * r->vp[0]] = c; } #define imp_ren_char(chw, chh, fw, data) \ @@ -209,11 +218,11 @@ void ren_point(Renderer* r, Colour c, int x, int y) { re.x = x; \ re.y = y; \ sub.x = (ch - ' ') * chw; \ - rect_clips(&re, &sub, &r->clip); \ + rect_clipsr(&re, &sub, r->clip); \ ex = re.x + re.w; \ ey = re.y + re.h; \ - dst = r->t + (re.x + re.y * r->vp[2]); \ - s = r->vp[2] - re.w; \ + dst = r->t + (re.x + re.y * r->vp[0]); \ + s = r->vp[0] - 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; \ @@ -416,6 +425,24 @@ void step_line( } } +void ren_line( + Renderer* r, + Colour c, + const int* s, + const int* e +) { + Line l; + init_line(&l, s, e); + while (l.x != e[0] && l.y != e[1]) { + Colour* dst = &r->t[l.x + l.y * r->vp[0]]; + if (l.x < r->clip[0] || l.y < r->clip[1]) goto step; + if (l.x >= r->clip[2] || l.y >= r->clip[3]) goto step; + *dst = blend(*dst, c); +step: + step_line(&l); + } +} + void ren_tri( Renderer* r, const int* iv0, @@ -426,8 +453,8 @@ 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; + const int fcx = r->clip[2]; + const int fcy = r->clip[3]; int v0[ec], v1[ec], v2[ec]; Line ne, fe; /* near and far edges */ Line ni[ic], fi[ic]; /* near and far interpolants */ @@ -478,7 +505,7 @@ void ren_tri( if (v1[1] > fcy) v1[1] = fcy; #define scanline\ int x, ex = mini(fe.x, fcx);\ - if (fe.y >= r->clip.y) { \ + if (fe.y >= r->clip[1]) { \ for (i = 0; i < ic; i++)\ init_lerp(\ &xi[i],\ @@ -487,17 +514,17 @@ void ren_tri( );\ for (x = ne.x; x < ex; x++) {\ Colour col;\ - if (x >= r->clip.x) { \ + if (x >= r->clip[0]) { \ 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(\ + if (xi[0].x < r->d[x + fe.y * r->vp[0]]) { \ + r->t[x + fe.y * r->vp[0]] = col_mul(\ sample_tex(tex, xi[1].x, xi[2].x),\ col\ );\ - r->d[x + fe.y * r->vp[2]] = xi[0].x; \ + r->d[x + fe.y * r->vp[0]] = xi[0].x; \ } \ } \ for (i = 0; i < ic; i++)\ @@ -605,10 +632,10 @@ int point_os( int y ) { return - x >= r->vp[0] && - y >= r->vp[1] && - x < r->vp[2] && - y < r->vp[3]; + x >= r->clip[0] && + y >= r->clip[1] && + x < r->clip[2] && + y < r->clip[3]; } void ren_mesh( diff --git a/render.h b/render.h index 996ba37..2299a30 100644 --- a/render.h +++ b/render.h @@ -42,8 +42,8 @@ typedef struct { Colour* t; int* d; int asp, n; - int vp[4]; - Rect clip; + int vp[2]; + int clip[4]; } Renderer; int tri_os( @@ -95,6 +95,12 @@ void ren_texts( int y, const char* t ); +void ren_line( + Renderer* r, + Colour c, + const int* s, + const int* e +); /* Vertex format: * x y z u v r g b * All fixed point values with 9 bits of precision. -- cgit v1.2.3-54-g00ecf