integrating software renderer
[retroray] / src / gaw / polyfill.c
1 /*
2 RetroRay - integrated standalone vintage modeller/renderer
3 Copyright (C) 2023  John Tsiombikas <nuclear@mutantstargoat.com>
4
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.
9
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.
14
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/>.
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <assert.h>
22 #include "polyfill.h"
23
24 /*#define DEBUG_OVERDRAW        PACK_RGB(10, 10, 10)*/
25
26 #define FILL_POLY_BITS  0x03
27
28
29 /* mode bits: 00-wire 01-flat 10-gouraud 11-reserved
30  *     bit 2: texture
31  *     bit 3-4: blend mode: 00-none 01-alpha 10-additive 11-reserved
32  *     bit 5: zbuffering
33  */
34 void (*fillfunc[])(struct pvertex*, int) = {
35         polyfill_wire,
36         polyfill_flat,
37         polyfill_gouraud,
38         0,
39         polyfill_tex_wire,
40         polyfill_tex_flat,
41         polyfill_tex_gouraud,
42         0,
43         polyfill_alpha_wire,
44         polyfill_alpha_flat,
45         polyfill_alpha_gouraud,
46         0,
47         polyfill_alpha_tex_wire,
48         polyfill_alpha_tex_flat,
49         polyfill_alpha_tex_gouraud,
50         0,
51         polyfill_add_wire,
52         polyfill_add_flat,
53         polyfill_add_gouraud,
54         0,
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,
59         polyfill_wire,
60         polyfill_flat_zbuf,
61         polyfill_gouraud_zbuf,
62         0,
63         polyfill_tex_wire,
64         polyfill_tex_flat_zbuf,
65         polyfill_tex_gouraud_zbuf,
66         0,
67         polyfill_alpha_wire,
68         polyfill_alpha_flat_zbuf,
69         polyfill_alpha_gouraud_zbuf,
70         0,
71         polyfill_alpha_tex_wire,
72         polyfill_alpha_tex_flat_zbuf,
73         polyfill_alpha_tex_gouraud_zbuf,
74         0,
75         polyfill_add_wire,
76         polyfill_add_flat_zbuf,
77         polyfill_add_gouraud_zbuf,
78         0,
79         polyfill_add_tex_wire,
80         polyfill_add_tex_flat_zbuf,
81         polyfill_add_tex_gouraud_zbuf,
82         0, 0, 0, 0, 0, 0, 0, 0, 0
83 };
84
85 struct pimage pfill_fb, pfill_tex;
86 uint32_t *pfill_zbuf;
87
88 #define EDGEPAD 8
89 static struct pvertex *edgebuf, *left, *right;
90 static int edgebuf_size;
91 static int fbheight;
92
93 /*
94 #define CHECKEDGE(x) \
95         do { \
96                 assert(x >= 0); \
97                 assert(x < fbheight); \
98         } while(0)
99 */
100 #define CHECKEDGE(x)
101
102
103 void polyfill_fbheight(int height)
104 {
105         int newsz = (height * 2 + EDGEPAD * 3) * sizeof *edgebuf;
106
107         if(newsz > edgebuf_size) {
108                 free(edgebuf);
109                 if(!(edgebuf = malloc(newsz))) {
110                         fprintf(stderr, "failed to allocate edge table buffer (%d bytes)\n", newsz);
111                         abort();
112                 }
113                 edgebuf_size = newsz;
114
115                 left = edgebuf + EDGEPAD;
116                 right = edgebuf + height + EDGEPAD * 2;
117
118 #ifndef NDEBUG
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);
122 #endif
123         }
124
125         fbheight = height;
126 }
127
128 void polyfill(int mode, struct pvertex *verts, int nverts)
129 {
130 #ifndef NDEBUG
131         if(!fillfunc[mode]) {
132                 fprintf(stderr, "polyfill mode %d not implemented\n", mode);
133                 abort();
134         }
135 #endif
136
137         fillfunc[mode](verts, nverts);
138 }
139
140 void polyfill_wire(struct pvertex *verts, int nverts)
141 {
142         /*
143         int i, x0, y0, x1, y1;
144         struct pvertex *v = verts;
145         uint32_t color = PACK_RGB(v->r, v->g, v->b);
146
147         for(i=0; i<nverts - 1; i++) {
148                 x0 = v->x >> 8;
149                 y0 = v->y >> 8;
150                 ++v;
151                 x1 = v->x >> 8;
152                 y1 = v->y >> 8;
153                 if(clip_line(&x0, &y0, &x1, &y1, 0, 0, pfill_fb.width, pfill_fb.height)) {
154                         draw_line(x0, y0, x1, y1, color);
155                 }
156         }
157         x0 = verts[0].x >> 8;
158         y0 = verts[0].y >> 8;
159         if(clip_line(&x1, &y1, &x0, &y0, 0, 0, pfill_fb.width, pfill_fb.height)) {
160                 draw_line(x1, y1, x0, y0, color);
161         }
162         */
163 }
164
165 void polyfill_tex_wire(struct pvertex *verts, int nverts)
166 {
167         polyfill_wire(verts, nverts);   /* TODO */
168 }
169
170 void polyfill_alpha_wire(struct pvertex *verts, int nverts)
171 {
172         polyfill_wire(verts, nverts);   /* TODO */
173 }
174
175 void polyfill_alpha_tex_wire(struct pvertex *verts, int nverts)
176 {
177         polyfill_wire(verts, nverts);   /* TODO */
178 }
179
180 void polyfill_add_wire(struct pvertex *verts, int nverts)
181 {
182         polyfill_wire(verts, nverts);   /* TODO */
183 }
184
185 void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
186 {
187         polyfill_wire(verts, nverts);   /* TODO */
188 }
189
190 #define VNEXT(p)        (((p) == vlast) ? varr : (p) + 1)
191 #define VPREV(p)        ((p) == varr ? vlast : (p) - 1)
192 #define VSUCC(p, side)  ((side) == 0 ? VNEXT(p) : VPREV(p))
193
194 /* extra bits of precision to use when interpolating colors.
195  * try tweaking this if you notice strange quantization artifacts.
196  */
197 #define COLOR_SHIFT     12
198
199
200 #define POLYFILL polyfill_flat
201 #undef GOURAUD
202 #undef TEXMAP
203 #undef BLEND_ALPHA
204 #undef BLEND_ADD
205 #undef ZBUF
206 #include "polytmpl.h"
207 #undef POLYFILL
208
209 #define POLYFILL polyfill_gouraud
210 #define GOURAUD
211 #undef TEXMAP
212 #undef BLEND_ALPHA
213 #undef BLEND_ADD
214 #undef ZBUF
215 #include "polytmpl.h"
216 #undef POLYFILL
217
218 #define POLYFILL polyfill_tex_flat
219 #undef GOURAUD
220 #define TEXMAP
221 #undef BLEND_ALPHA
222 #undef BLEND_ADD
223 #undef ZBUF
224 #include "polytmpl.h"
225 #undef POLYFILL
226
227 #define POLYFILL polyfill_tex_gouraud
228 #define GOURAUD
229 #define TEXMAP
230 #undef BLEND_ALPHA
231 #undef BLEND_ADD
232 #undef ZBUF
233 #include "polytmpl.h"
234 #undef POLYFILL
235
236 #define POLYFILL polyfill_alpha_flat
237 #undef GOURAUD
238 #undef TEXMAP
239 #define BLEND_ALPHA
240 #undef BLEND_ADD
241 #undef ZBUF
242 #include "polytmpl.h"
243 #undef POLYFILL
244
245 #define POLYFILL polyfill_alpha_gouraud
246 #define GOURAUD
247 #undef TEXMAP
248 #define BLEND_ALPHA
249 #undef BLEND_ADD
250 #undef ZBUF
251 #include "polytmpl.h"
252 #undef POLYFILL
253
254 #define POLYFILL polyfill_alpha_tex_flat
255 #undef GOURAUD
256 #define TEXMAP
257 #define BLEND_ALPHA
258 #undef BLEND_ADD
259 #undef ZBUF
260 #include "polytmpl.h"
261 #undef POLYFILL
262
263 #define POLYFILL polyfill_alpha_tex_gouraud
264 #define GOURAUD
265 #define TEXMAP
266 #define BLEND_ALPHA
267 #undef BLEND_ADD
268 #undef ZBUF
269 #include "polytmpl.h"
270 #undef POLYFILL
271
272 #define POLYFILL polyfill_add_flat
273 #undef GOURAUD
274 #undef TEXMAP
275 #undef BLEND_ALPHA
276 #define BLEND_ADD
277 #undef ZBUF
278 #include "polytmpl.h"
279 #undef POLYFILL
280
281 #define POLYFILL polyfill_add_gouraud
282 #define GOURAUD
283 #undef TEXMAP
284 #undef BLEND_ALPHA
285 #define BLEND_ADD
286 #undef ZBUF
287 #include "polytmpl.h"
288 #undef POLYFILL
289
290 #define POLYFILL polyfill_add_tex_flat
291 #undef GOURAUD
292 #define TEXMAP
293 #undef BLEND_ALPHA
294 #define BLEND_ADD
295 #undef ZBUF
296 #include "polytmpl.h"
297 #undef POLYFILL
298
299 #define POLYFILL polyfill_add_tex_gouraud
300 #define GOURAUD
301 #define TEXMAP
302 #undef BLEND_ALPHA
303 #define BLEND_ADD
304 #undef ZBUF
305 #include "polytmpl.h"
306 #undef POLYFILL
307
308 /* ---- zbuffer variants ----- */
309
310 #define POLYFILL polyfill_flat_zbuf
311 #undef GOURAUD
312 #undef TEXMAP
313 #undef BLEND_ALPHA
314 #undef BLEND_ADD
315 #define ZBUF
316 #include "polytmpl.h"
317 #undef POLYFILL
318
319 #define POLYFILL polyfill_gouraud_zbuf
320 #define GOURAUD
321 #undef TEXMAP
322 #undef BLEND_ALPHA
323 #undef BLEND_ADD
324 #define ZBUF
325 #include "polytmpl.h"
326 #undef POLYFILL
327
328 #define POLYFILL polyfill_tex_flat_zbuf
329 #undef GOURAUD
330 #define TEXMAP
331 #undef BLEND_ALPHA
332 #undef BLEND_ADD
333 #define ZBUF
334 #include "polytmpl.h"
335 #undef POLYFILL
336
337 #define POLYFILL polyfill_tex_gouraud_zbuf
338 #define GOURAUD
339 #define TEXMAP
340 #undef BLEND_ALPHA
341 #undef BLEND_ADD
342 #define ZBUF
343 #include "polytmpl.h"
344 #undef POLYFILL
345
346 #define POLYFILL polyfill_alpha_flat_zbuf
347 #undef GOURAUD
348 #undef TEXMAP
349 #define BLEND_ALPHA
350 #undef BLEND_ADD
351 #define ZBUF
352 #include "polytmpl.h"
353 #undef POLYFILL
354
355 #define POLYFILL polyfill_alpha_gouraud_zbuf
356 #define GOURAUD
357 #undef TEXMAP
358 #define BLEND_ALPHA
359 #undef BLEND_ADD
360 #define ZBUF
361 #include "polytmpl.h"
362 #undef POLYFILL
363
364 #define POLYFILL polyfill_alpha_tex_flat_zbuf
365 #undef GOURAUD
366 #define TEXMAP
367 #define BLEND_ALPHA
368 #undef BLEND_ADD
369 #define ZBUF
370 #include "polytmpl.h"
371 #undef POLYFILL
372
373 #define POLYFILL polyfill_alpha_tex_gouraud_zbuf
374 #define GOURAUD
375 #define TEXMAP
376 #define BLEND_ALPHA
377 #undef BLEND_ADD
378 #define ZBUF
379 #include "polytmpl.h"
380 #undef POLYFILL
381
382 #define POLYFILL polyfill_add_flat_zbuf
383 #undef GOURAUD
384 #undef TEXMAP
385 #undef BLEND_ALPHA
386 #define BLEND_ADD
387 #define ZBUF
388 #include "polytmpl.h"
389 #undef POLYFILL
390
391 #define POLYFILL polyfill_add_gouraud_zbuf
392 #define GOURAUD
393 #undef TEXMAP
394 #undef BLEND_ALPHA
395 #define BLEND_ADD
396 #define ZBUF
397 #include "polytmpl.h"
398 #undef POLYFILL
399
400 #define POLYFILL polyfill_add_tex_flat_zbuf
401 #undef GOURAUD
402 #define TEXMAP
403 #undef BLEND_ALPHA
404 #define BLEND_ADD
405 #define ZBUF
406 #include "polytmpl.h"
407 #undef POLYFILL
408
409 #define POLYFILL polyfill_add_tex_gouraud_zbuf
410 #define GOURAUD
411 #define TEXMAP
412 #undef BLEND_ALPHA
413 #define BLEND_ADD
414 #define ZBUF
415 #include "polytmpl.h"
416 #undef POLYFILL
417