summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-07-15 21:08:33 +1000
committerquou <quou@disroot.org>2024-07-15 21:08:33 +1000
commit24097f5aacbf46ec1500ab84a60bade28b53a301 (patch)
tree44fabe537357779f06a03e91fc20a5d996ba5296
parent680cab5cf1778958e7257f19957ac2b5d46d45dc (diff)
Screen space clipping and backface culling.
-rw-r--r--render.c164
-rw-r--r--render.h24
2 files changed, 147 insertions, 41 deletions
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);
}
}
diff --git a/render.h b/render.h
index 3c8938f..e51478f 100644
--- a/render.h
+++ b/render.h
@@ -37,10 +37,23 @@ typedef struct Mesh {
typedef struct {
Colour* t;
int* d;
- int w, h, asp;
+ int asp, n;
+ int vp[4];
Rect clip;
} Renderer;
+int tri_os(
+ const Renderer* r,
+ const int* v0,
+ const int* v1,
+ const int* v2
+);
+int point_os(
+ const Renderer* r,
+ int x,
+ int y
+);
+
void ren_begin(Renderer* r, Colour* t, int* d, int w, int h);
void ren_end(Renderer* r);
void ren_clear(Renderer* r);
@@ -86,7 +99,14 @@ void ren_tri(
const int* v1,
const int* v2,
const Bitmap* tex
-);
+); /* Unsafe for 3D. Clips against the r->clip */
+void ren_tri3(
+ Renderer* r,
+ const int* v0,
+ const int* v1,
+ const int* v2,
+ const Bitmap* tex
+); /* Does perspective calculation and clips against the near. */
void ren_mesh(
Renderer* r,
const Mesh* mesh,