zbuffer partial implementation
[dosdemo] / src / 3dgfx / polyfill.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
5 #if defined(__WATCOMC__) || defined(_WIN32) || defined(__DJGPP__)
6 #include <malloc.h>
7 #else
8 #include <alloca.h>
9 #endif
10 #include "polyfill.h"
11 #include "gfxutil.h"
12
13 #define FILL_POLY_BITS  0x03
14
15 /* mode bits: 00-wire 01-flat 10-gouraud 11-reserved
16  *     bit 2: texture
17  *     bit 3-4: blend mode: 00-none 01-alpha 10-additive 11-reserved
18  *     bit 5: zbuffering
19  */
20 void (*fillfunc[])(struct pvertex*, int) = {
21         polyfill_wire,
22         polyfill_flat,
23         polyfill_gouraud,
24         0,
25         polyfill_tex_wire,
26         polyfill_tex_flat,
27         polyfill_tex_gouraud,
28         0,
29         polyfill_alpha_wire,
30         polyfill_alpha_flat,
31         polyfill_alpha_gouraud,
32         0,
33         polyfill_alpha_tex_wire,
34         polyfill_alpha_tex_flat,
35         polyfill_alpha_tex_gouraud,
36         0,
37         polyfill_add_wire,
38         polyfill_add_flat,
39         polyfill_add_gouraud,
40         0,
41         polyfill_add_tex_wire,
42         polyfill_add_tex_flat,
43         polyfill_add_tex_gouraud,
44         0, 0, 0, 0, 0, 0, 0, 0, 0,
45         polyfill_wire,
46         polyfill_flat_zbuf,
47         polyfill_gouraud_zbuf,
48         0,
49         polyfill_tex_wire,
50         polyfill_tex_flat_zbuf,
51         polyfill_tex_gouraud_zbuf,
52         0,
53         polyfill_alpha_wire,
54         polyfill_alpha_flat_zbuf,
55         polyfill_alpha_gouraud_zbuf,
56         0,
57         polyfill_alpha_tex_wire,
58         polyfill_alpha_tex_flat_zbuf,
59         polyfill_alpha_tex_gouraud_zbuf,
60         0,
61         polyfill_add_wire,
62         polyfill_add_flat_zbuf,
63         polyfill_add_gouraud_zbuf,
64         0,
65         polyfill_add_tex_wire,
66         polyfill_add_tex_flat_zbuf,
67         polyfill_add_tex_gouraud_zbuf,
68         0, 0, 0, 0, 0, 0, 0, 0, 0
69 };
70
71 struct pimage pfill_fb, pfill_tex;
72 uint16_t *pfill_zbuf;
73
74 #define EDGEPAD 8
75 static struct pvertex *edgebuf, *left, *right;
76 static int edgebuf_size;
77 static int fbheight;
78
79 /*
80 #define CHECKEDGE(x) \
81         do { \
82                 assert(x >= 0); \
83                 assert(x < fbheight); \
84         } while(0)
85 */
86 #define CHECKEDGE(x)
87
88
89 void polyfill_fbheight(int height)
90 {
91         void *tmp;
92         int newsz = (height * 2 + EDGEPAD * 3) * sizeof *edgebuf;
93
94         if(newsz > edgebuf_size) {
95                 free(edgebuf);
96                 if(!(edgebuf = malloc(newsz))) {
97                         fprintf(stderr, "failed to allocate edge table buffer (%d bytes)\n", newsz);
98                         abort();
99                 }
100                 edgebuf_size = newsz;
101
102                 left = edgebuf + EDGEPAD;
103                 right = edgebuf + height + EDGEPAD * 2;
104
105 #ifndef NDEBUG
106                 memset(edgebuf, 0xaa, EDGEPAD * sizeof *edgebuf);
107                 memset(edgebuf + height + EDGEPAD, 0xaa, EDGEPAD * sizeof *edgebuf);
108                 memset(edgebuf + height * 2 + EDGEPAD * 2, 0xaa, EDGEPAD * sizeof *edgebuf);
109 #endif
110         }
111
112         fbheight = height;
113 }
114
115 void polyfill(int mode, struct pvertex *verts, int nverts)
116 {
117 #ifndef NDEBUG
118         if(!fillfunc[mode]) {
119                 fprintf(stderr, "polyfill mode %d not implemented\n", mode);
120                 abort();
121         }
122 #endif
123
124         fillfunc[mode](verts, nverts);
125 }
126
127 void polyfill_wire(struct pvertex *verts, int nverts)
128 {
129         int i, x0, y0, x1, y1;
130         struct pvertex *v = verts;
131         unsigned short color = ((v->r << 8) & 0xf800) |
132                 ((v->g << 3) & 0x7e0) | ((v->b >> 3) & 0x1f);
133
134         for(i=0; i<nverts - 1; i++) {
135                 x0 = v->x >> 8;
136                 y0 = v->y >> 8;
137                 ++v;
138                 x1 = v->x >> 8;
139                 y1 = v->y >> 8;
140                 if(clip_line(&x0, &y0, &x1, &y1, 0, 0, pfill_fb.width, pfill_fb.height)) {
141                         draw_line(x0, y0, x1, y1, color);
142                 }
143         }
144         x0 = verts[0].x >> 8;
145         y0 = verts[0].y >> 8;
146         if(clip_line(&x1, &y1, &x0, &y0, 0, 0, pfill_fb.width, pfill_fb.height)) {
147                 draw_line(x1, y1, x0, y0, color);
148         }
149 }
150
151 void polyfill_tex_wire(struct pvertex *verts, int nverts)
152 {
153         polyfill_wire(verts, nverts);   /* TODO */
154 }
155
156 void polyfill_alpha_wire(struct pvertex *verts, int nverts)
157 {
158         polyfill_wire(verts, nverts);   /* TODO */
159 }
160
161 void polyfill_alpha_tex_wire(struct pvertex *verts, int nverts)
162 {
163         polyfill_wire(verts, nverts);   /* TODO */
164 }
165
166 void polyfill_add_wire(struct pvertex *verts, int nverts)
167 {
168         polyfill_wire(verts, nverts);   /* TODO */
169 }
170
171 void polyfill_add_tex_wire(struct pvertex *verts, int nverts)
172 {
173         polyfill_wire(verts, nverts);   /* TODO */
174 }
175
176 #define NEXTIDX(x) (((x) - 1 + nverts) % nverts)
177 #define PREVIDX(x) (((x) + 1) % nverts)
178
179 /* XXX
180  * When HIGH_QUALITY is defined, the rasterizer calculates slopes for attribute
181  * interpolation on each scanline separately; otherwise the slope for each
182  * attribute would be calculated once for the whole polygon, which is faster,
183  * but produces some slight quantization artifacts, due to the limited precision
184  * of fixed-point calculations.
185  */
186 #define HIGH_QUALITY
187
188 /* extra bits of precision to use when interpolating colors.
189  * try tweaking this if you notice strange quantization artifacts.
190  */
191 #define COLOR_SHIFT     12
192
193
194 #define POLYFILL polyfill_flat
195 #define SCANEDGE scanedge_flat
196 #undef GOURAUD
197 #undef TEXMAP
198 #undef BLEND_ALPHA
199 #undef BLEND_ADD
200 #undef ZBUF
201 #include "polytmpl.h"
202 #undef POLYFILL
203 #undef SCANEDGE
204
205 #define POLYFILL polyfill_gouraud
206 #define SCANEDGE scanedge_gouraud
207 #define GOURAUD
208 #undef TEXMAP
209 #undef BLEND_ALPHA
210 #undef BLEND_ADD
211 #undef ZBUF
212 #include "polytmpl.h"
213 #undef POLYFILL
214 #undef SCANEDGE
215
216 #define POLYFILL polyfill_tex_flat
217 #define SCANEDGE scanedge_tex_flat
218 #undef GOURAUD
219 #define TEXMAP
220 #undef BLEND_ALPHA
221 #undef BLEND_ADD
222 #undef ZBUF
223 #include "polytmpl.h"
224 #undef POLYFILL
225 #undef SCANEDGE
226
227 #define POLYFILL polyfill_tex_gouraud
228 #define SCANEDGE scanedge_tex_gouraud
229 #define GOURAUD
230 #define TEXMAP
231 #undef BLEND_ALPHA
232 #undef BLEND_ADD
233 #undef ZBUF
234 #include "polytmpl.h"
235 #undef POLYFILL
236 #undef SCANEDGE
237
238 #define POLYFILL polyfill_alpha_flat
239 #define SCANEDGE scanedge_alpha_flat
240 #undef GOURAUD
241 #undef TEXMAP
242 #define BLEND_ALPHA
243 #undef BLEND_ADD
244 #undef ZBUF
245 #include "polytmpl.h"
246 #undef POLYFILL
247 #undef SCANEDGE
248
249 #define POLYFILL polyfill_alpha_gouraud
250 #define SCANEDGE scanedge_alpha_gouraud
251 #define GOURAUD
252 #undef TEXMAP
253 #define BLEND_ALPHA
254 #undef BLEND_ADD
255 #undef ZBUF
256 #include "polytmpl.h"
257 #undef POLYFILL
258 #undef SCANEDGE
259
260 #define POLYFILL polyfill_alpha_tex_flat
261 #define SCANEDGE scanedge_alpha_tex_flat
262 #undef GOURAUD
263 #define TEXMAP
264 #define BLEND_ALPHA
265 #undef BLEND_ADD
266 #undef ZBUF
267 #include "polytmpl.h"
268 #undef POLYFILL
269 #undef SCANEDGE
270
271 #define POLYFILL polyfill_alpha_tex_gouraud
272 #define SCANEDGE scanedge_alpha_tex_gouraud
273 #define GOURAUD
274 #define TEXMAP
275 #define BLEND_ALPHA
276 #undef BLEND_ADD
277 #undef ZBUF
278 #include "polytmpl.h"
279 #undef POLYFILL
280 #undef SCANEDGE
281
282 #define POLYFILL polyfill_add_flat
283 #define SCANEDGE scanedge_add_flat
284 #undef GOURAUD
285 #undef TEXMAP
286 #undef BLEND_ALPHA
287 #define BLEND_ADD
288 #undef ZBUF
289 #include "polytmpl.h"
290 #undef POLYFILL
291 #undef SCANEDGE
292
293 #define POLYFILL polyfill_add_gouraud
294 #define SCANEDGE scanedge_add_gouraud
295 #define GOURAUD
296 #undef TEXMAP
297 #undef BLEND_ALPHA
298 #define BLEND_ADD
299 #undef ZBUF
300 #include "polytmpl.h"
301 #undef POLYFILL
302 #undef SCANEDGE
303
304 #define POLYFILL polyfill_add_tex_flat
305 #define SCANEDGE scanedge_add_tex_flat
306 #undef GOURAUD
307 #define TEXMAP
308 #undef BLEND_ALPHA
309 #define BLEND_ADD
310 #undef ZBUF
311 #include "polytmpl.h"
312 #undef POLYFILL
313 #undef SCANEDGE
314
315 #define POLYFILL polyfill_add_tex_gouraud
316 #define SCANEDGE scanedge_add_tex_gouraud
317 #define GOURAUD
318 #define TEXMAP
319 #undef BLEND_ALPHA
320 #define BLEND_ADD
321 #undef ZBUF
322 #include "polytmpl.h"
323 #undef POLYFILL
324 #undef SCANEDGE
325
326 /* ---- zbuffer variants ----- */
327
328 #define POLYFILL polyfill_flat_zbuf
329 #define SCANEDGE scanedge_flat_zbuf
330 #undef GOURAUD
331 #undef TEXMAP
332 #undef BLEND_ALPHA
333 #undef BLEND_ADD
334 #define ZBUF
335 #include "polytmpl.h"
336 #undef POLYFILL
337 #undef SCANEDGE
338
339 #define POLYFILL polyfill_gouraud_zbuf
340 #define SCANEDGE scanedge_gouraud_zbuf
341 #define GOURAUD
342 #undef TEXMAP
343 #undef BLEND_ALPHA
344 #undef BLEND_ADD
345 #define ZBUF
346 #include "polytmpl.h"
347 #undef POLYFILL
348 #undef SCANEDGE
349
350 #define POLYFILL polyfill_tex_flat_zbuf
351 #define SCANEDGE scanedge_tex_flat_zbuf
352 #undef GOURAUD
353 #define TEXMAP
354 #undef BLEND_ALPHA
355 #undef BLEND_ADD
356 #define ZBUF
357 #include "polytmpl.h"
358 #undef POLYFILL
359 #undef SCANEDGE
360
361 #define POLYFILL polyfill_tex_gouraud_zbuf
362 #define SCANEDGE scanedge_tex_gouraud_zbuf
363 #define GOURAUD
364 #define TEXMAP
365 #undef BLEND_ALPHA
366 #undef BLEND_ADD
367 #define ZBUF
368 #include "polytmpl.h"
369 #undef POLYFILL
370 #undef SCANEDGE
371
372 #define POLYFILL polyfill_alpha_flat_zbuf
373 #define SCANEDGE scanedge_alpha_flat_zbuf
374 #undef GOURAUD
375 #undef TEXMAP
376 #define BLEND_ALPHA
377 #undef BLEND_ADD
378 #define ZBUF
379 #include "polytmpl.h"
380 #undef POLYFILL
381 #undef SCANEDGE
382
383 #define POLYFILL polyfill_alpha_gouraud_zbuf
384 #define SCANEDGE scanedge_alpha_gouraud_zbuf
385 #define GOURAUD
386 #undef TEXMAP
387 #define BLEND_ALPHA
388 #undef BLEND_ADD
389 #define ZBUF
390 #include "polytmpl.h"
391 #undef POLYFILL
392 #undef SCANEDGE
393
394 #define POLYFILL polyfill_alpha_tex_flat_zbuf
395 #define SCANEDGE scanedge_alpha_tex_flat_zbuf
396 #undef GOURAUD
397 #define TEXMAP
398 #define BLEND_ALPHA
399 #undef BLEND_ADD
400 #define ZBUF
401 #include "polytmpl.h"
402 #undef POLYFILL
403 #undef SCANEDGE
404
405 #define POLYFILL polyfill_alpha_tex_gouraud_zbuf
406 #define SCANEDGE scanedge_alpha_tex_gouraud_zbuf
407 #define GOURAUD
408 #define TEXMAP
409 #define BLEND_ALPHA
410 #undef BLEND_ADD
411 #define ZBUF
412 #include "polytmpl.h"
413 #undef POLYFILL
414 #undef SCANEDGE
415
416 #define POLYFILL polyfill_add_flat_zbuf
417 #define SCANEDGE scanedge_add_flat_zbuf
418 #undef GOURAUD
419 #undef TEXMAP
420 #undef BLEND_ALPHA
421 #define BLEND_ADD
422 #define ZBUF
423 #include "polytmpl.h"
424 #undef POLYFILL
425 #undef SCANEDGE
426
427 #define POLYFILL polyfill_add_gouraud_zbuf
428 #define SCANEDGE scanedge_add_gouraud_zbuf
429 #define GOURAUD
430 #undef TEXMAP
431 #undef BLEND_ALPHA
432 #define BLEND_ADD
433 #define ZBUF
434 #include "polytmpl.h"
435 #undef POLYFILL
436 #undef SCANEDGE
437
438 #define POLYFILL polyfill_add_tex_flat_zbuf
439 #define SCANEDGE scanedge_add_tex_flat_zbuf
440 #undef GOURAUD
441 #define TEXMAP
442 #undef BLEND_ALPHA
443 #define BLEND_ADD
444 #define ZBUF
445 #include "polytmpl.h"
446 #undef POLYFILL
447 #undef SCANEDGE
448
449 #define POLYFILL polyfill_add_tex_gouraud_zbuf
450 #define SCANEDGE scanedge_add_tex_gouraud_zbuf
451 #define GOURAUD
452 #define TEXMAP
453 #undef BLEND_ALPHA
454 #define BLEND_ADD
455 #define ZBUF
456 #include "polytmpl.h"
457 #undef POLYFILL
458 #undef SCANEDGE