summaryrefslogtreecommitdiff
path: root/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'render.c')
-rw-r--r--render.c246
1 files changed, 165 insertions, 81 deletions
diff --git a/render.c b/render.c
index 04c39dd..95fc5d9 100644
--- a/render.c
+++ b/render.c
@@ -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
}