2 RetroRay - integrated standalone vintage modeller/renderer
3 Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
24 /*#define DEBUG_OVERDRAW PACK_RGB(10, 10, 10)*/
26 #define FILL_POLY_BITS 0x03
29 /* mode bits: 00-wire 01-flat 10-gouraud 11-reserved
31 * bit 3-4: blend mode: 00-none 01-alpha 10-additive 11-reserved
34 void (*fillfunc[])(struct pvertex*, int) = {
45 polyfill_alpha_gouraud,
47 polyfill_alpha_tex_wire,
48 polyfill_alpha_tex_flat,
49 polyfill_alpha_tex_gouraud,
55 polyfill_add_tex_wire,
56 polyfill_add_tex_flat,
57 polyfill_add_tex_gouraud,
58 0, 0, 0, 0, 0, 0, 0, 0, 0,
61 polyfill_gouraud_zbuf,
63 polyfill_tex_wire_zbuf,
64 polyfill_tex_flat_zbuf,
65 polyfill_tex_gouraud_zbuf,
67 polyfill_alpha_wire_zbuf,
68 polyfill_alpha_flat_zbuf,
69 polyfill_alpha_gouraud_zbuf,
71 polyfill_alpha_tex_wire_zbuf,
72 polyfill_alpha_tex_flat_zbuf,
73 polyfill_alpha_tex_gouraud_zbuf,
75 polyfill_add_wire_zbuf,
76 polyfill_add_flat_zbuf,
77 polyfill_add_gouraud_zbuf,
79 polyfill_add_tex_wire_zbuf,
80 polyfill_add_tex_flat_zbuf,
81 polyfill_add_tex_gouraud_zbuf,
82 0, 0, 0, 0, 0, 0, 0, 0, 0
85 struct pimage pfill_fb, pfill_tex;
89 static struct pvertex *edgebuf, *left, *right;
90 static int edgebuf_size;
94 #define CHECKEDGE(x) \
97 assert(x < fbheight); \
103 void polyfill_fbheight(int height)
105 int newsz = (height * 2 + EDGEPAD * 3) * sizeof *edgebuf;
107 if(newsz > edgebuf_size) {
109 if(!(edgebuf = malloc(newsz))) {
110 fprintf(stderr, "failed to allocate edge table buffer (%d bytes)\n", newsz);
113 edgebuf_size = newsz;
115 left = edgebuf + EDGEPAD;
116 right = edgebuf + height + EDGEPAD * 2;
119 memset(edgebuf, 0xaa, EDGEPAD * sizeof *edgebuf);
120 memset(edgebuf + height + EDGEPAD, 0xaa, EDGEPAD * sizeof *edgebuf);
121 memset(edgebuf + height * 2 + EDGEPAD * 2, 0xaa, EDGEPAD * sizeof *edgebuf);
128 void polyfill(int mode, struct pvertex *verts, int nverts)
131 if(!fillfunc[mode]) {
132 fprintf(stderr, "polyfill mode %d not implemented\n", mode);
137 fillfunc[mode](verts, nverts);
140 void polyfill_wire(struct pvertex *verts, int nverts)
145 void polyfill_tex_wire(struct pvertex *verts, int nverts)
147 polyfill_wire(verts, nverts); /* TODO */
150 void polyfill_alpha_wire(struct pvertex *verts, int nverts)
152 polyfill_wire(verts, nverts); /* TODO */
155 void polyfill_alpha_tex_wire(struct pvertex *verts, int nverts)
157 polyfill_wire(verts, nverts); /* TODO */
160 void polyfill_add_wire(struct pvertex *verts, int nverts)
162 polyfill_wire(verts, nverts); /* TODO */
165 void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
167 polyfill_wire(verts, nverts); /* TODO */
170 void polyfill_wire_zbuf(struct pvertex *verts, int nverts)
172 draw_line_zbuf(verts);
175 void polyfill_tex_wire_zbuf(struct pvertex *verts, int nverts)
177 polyfill_wire_zbuf(verts, nverts); /* TODO */
180 void polyfill_alpha_wire_zbuf(struct pvertex *verts, int nverts)
182 polyfill_wire_zbuf(verts, nverts); /* TODO */
185 void polyfill_alpha_tex_wire_zbuf(struct pvertex *verts, int nverts)
187 polyfill_wire_zbuf(verts, nverts); /* TODO */
190 void polyfill_add_wire_zbuf(struct pvertex *verts, int nverts)
192 polyfill_wire_zbuf(verts, nverts); /* TODO */
195 void polyfill_add_tex_wire_zbuf(struct pvertex *verts, int nverts)
197 polyfill_wire_zbuf(verts, nverts); /* TODO */
201 #define VNEXT(p) (((p) == vlast) ? varr : (p) + 1)
202 #define VPREV(p) ((p) == varr ? vlast : (p) - 1)
203 #define VSUCC(p, side) ((side) == 0 ? VNEXT(p) : VPREV(p))
205 /* extra bits of precision to use when interpolating colors.
206 * try tweaking this if you notice strange quantization artifacts.
208 #define COLOR_SHIFT 12
211 #define POLYFILL polyfill_flat
217 #include "polytmpl.h"
220 #define POLYFILL polyfill_gouraud
226 #include "polytmpl.h"
229 #define POLYFILL polyfill_tex_flat
235 #include "polytmpl.h"
238 #define POLYFILL polyfill_tex_gouraud
244 #include "polytmpl.h"
247 #define POLYFILL polyfill_alpha_flat
253 #include "polytmpl.h"
256 #define POLYFILL polyfill_alpha_gouraud
262 #include "polytmpl.h"
265 #define POLYFILL polyfill_alpha_tex_flat
271 #include "polytmpl.h"
274 #define POLYFILL polyfill_alpha_tex_gouraud
280 #include "polytmpl.h"
283 #define POLYFILL polyfill_add_flat
289 #include "polytmpl.h"
292 #define POLYFILL polyfill_add_gouraud
298 #include "polytmpl.h"
301 #define POLYFILL polyfill_add_tex_flat
307 #include "polytmpl.h"
310 #define POLYFILL polyfill_add_tex_gouraud
316 #include "polytmpl.h"
319 /* ---- zbuffer variants ----- */
321 #define POLYFILL polyfill_flat_zbuf
327 #include "polytmpl.h"
330 #define POLYFILL polyfill_gouraud_zbuf
336 #include "polytmpl.h"
339 #define POLYFILL polyfill_tex_flat_zbuf
345 #include "polytmpl.h"
348 #define POLYFILL polyfill_tex_gouraud_zbuf
354 #include "polytmpl.h"
357 #define POLYFILL polyfill_alpha_flat_zbuf
363 #include "polytmpl.h"
366 #define POLYFILL polyfill_alpha_gouraud_zbuf
372 #include "polytmpl.h"
375 #define POLYFILL polyfill_alpha_tex_flat_zbuf
381 #include "polytmpl.h"
384 #define POLYFILL polyfill_alpha_tex_gouraud_zbuf
390 #include "polytmpl.h"
393 #define POLYFILL polyfill_add_flat_zbuf
399 #include "polytmpl.h"
402 #define POLYFILL polyfill_add_gouraud_zbuf
408 #include "polytmpl.h"
411 #define POLYFILL polyfill_add_tex_flat_zbuf
417 #include "polytmpl.h"
420 #define POLYFILL polyfill_add_tex_gouraud_zbuf
426 #include "polytmpl.h"
430 void draw_line(struct pvertex *verts)
432 int32_t x0, y0, x1, y1;
433 int i, dx, dy, x_inc, y_inc, error;
434 uint32_t *fb = pfill_fb.pixels;
435 uint32_t color = PACK_RGB(verts[0].r, verts[0].g, verts[0].b);
437 x0 = verts[0].x >> 8;
438 y0 = verts[0].y >> 8;
439 x1 = verts[1].x >> 8;
440 y1 = verts[1].y >> 8;
442 fb += y0 * pfill_fb.width + x0;
454 y_inc = pfill_fb.width;
456 y_inc = -pfill_fb.width;
462 for(i=0; i<=dx; i++) {
473 for(i=0; i<=dy; i++) {
485 void draw_line_zbuf(struct pvertex *verts)
487 int32_t x0, y0, x1, y1, z0, z1, z, dz, zslope;
488 int i, dx, dy, x_inc, y_inc, error;
489 uint32_t *fb = pfill_fb.pixels;
490 uint32_t *zptr = pfill_zbuf;
491 uint32_t color = PACK_RGB(verts[0].r, verts[0].g, verts[0].b);
493 x0 = verts[0].x >> 8;
494 y0 = verts[0].y >> 8;
495 x1 = verts[1].x >> 8;
496 y1 = verts[1].y >> 8;
500 fb += y0 * pfill_fb.width + x0;
501 zptr += y0 * pfill_fb.width + x0;
514 y_inc = pfill_fb.width;
516 y_inc = -pfill_fb.width;
523 zslope = dx ? (dz << 8) / (verts[1].x - verts[0].x) : 0;
525 for(i=0; i<=dx; i++) {
542 zslope = dy ? (dz << 8) / (verts[1].y - verts[0].y) : 0;
544 for(i=0; i<=dy; i++) {