10 /*#define DEBUG_OVERDRAW G3D_PACK_RGB(10, 10, 10)*/
12 #define FILL_POLY_BITS 0x03
14 /*void polyfill_tex_flat_new(struct pvertex *varr);*/
16 /* mode bits: 00-wire 01-flat 10-gouraud 11-reserved
20 void (*fillfunc[])(struct pvertex*) = {
29 0, 0, 0, 0, 0, 0, 0, 0,
32 polyfill_gouraud_zbuf,
35 polyfill_tex_flat_zbuf,
36 polyfill_tex_gouraud_zbuf,
38 0, 0, 0, 0, 0, 0, 0, 0
41 struct pimage pfill_fb, pfill_tex;
43 struct pgradient pgrad;
46 static struct pvertex *edgebuf, *left, *right;
47 static int edgebuf_size;
51 #define CHECKEDGE(x) \
54 assert(x < fbheight); \
60 void polyfill_fbheight(int height)
62 int newsz = (height * 2 + EDGEPAD * 3) * sizeof *edgebuf;
64 if(newsz > edgebuf_size) {
66 if(!(edgebuf = malloc(newsz))) {
67 fprintf(stderr, "failed to allocate edge table buffer (%d bytes)\n", newsz);
72 left = edgebuf + EDGEPAD;
73 right = edgebuf + height + EDGEPAD * 2;
76 memset(edgebuf, 0xaa, EDGEPAD * sizeof *edgebuf);
77 memset(edgebuf + height + EDGEPAD, 0xaa, EDGEPAD * sizeof *edgebuf);
78 memset(edgebuf + height * 2 + EDGEPAD * 2, 0xaa, EDGEPAD * sizeof *edgebuf);
85 void polyfill(int mode, struct pvertex *verts)
89 fprintf(stderr, "polyfill mode %d not implemented\n", mode);
94 fillfunc[mode](verts);
97 void polyfill_wire(struct pvertex *verts)
99 int i, x0, y0, x1, y1;
100 struct pvertex *v = verts;
101 int color = find_color(v->l, v->l, v->l);
109 if(clip_line(&x0, &y0, &x1, &y1, 0, 0, pfill_fb.width, pfill_fb.height)) {
110 draw_line(x0, y0, x1, y1, color);
113 x0 = verts[0].x >> 8;
114 y0 = verts[0].y >> 8;
115 if(clip_line(&x1, &y1, &x0, &y0, 0, 0, pfill_fb.width, pfill_fb.height)) {
116 draw_line(x1, y1, x0, y0, color);
120 void polyfill_tex_wire(struct pvertex *verts)
122 polyfill_wire(verts); /* TODO */
125 void polyfill_alpha_wire(struct pvertex *verts)
127 polyfill_wire(verts); /* TODO */
130 void polyfill_alpha_tex_wire(struct pvertex *verts)
132 polyfill_wire(verts); /* TODO */
135 void polyfill_add_wire(struct pvertex *verts)
137 polyfill_wire(verts); /* TODO */
140 void polyfill_add_tex_wire(struct pvertex *verts)
142 polyfill_wire(verts); /* TODO */
145 #define VNEXT(p) (((p) == varr + 2) ? varr : (p) + 1)
146 #define VPREV(p) ((p) == varr ? varr + 2 : (p) - 1)
147 #define VSUCC(p, side) ((side) == 0 ? VNEXT(p) : VPREV(p))
149 /* extra bits of precision to use when interpolating colors.
150 * try tweaking this if you notice strange quantization artifacts.
152 #define COLOR_SHIFT 12
155 #define POLYFILL polyfill_flat
159 #include "polytmpl.h"
162 #define POLYFILL polyfill_gouraud
166 #include "polytmpl.h"
169 #define POLYFILL polyfill_tex_flat
173 #include "polytmpl.h"
176 #define POLYFILL polyfill_tex_gouraud
180 #include "polytmpl.h"
183 /* ---- zbuffer variants ----- */
185 #define POLYFILL polyfill_flat_zbuf
189 #include "polytmpl.h"
192 #define POLYFILL polyfill_gouraud_zbuf
196 #include "polytmpl.h"
199 #define POLYFILL polyfill_tex_flat_zbuf
203 #include "polytmpl.h"
206 #define POLYFILL polyfill_tex_gouraud_zbuf
210 #include "polytmpl.h"
214 void polyfill_tex_flat_new(struct pvertex *varr)
216 int i, line, top, bot;
217 struct pvertex *v, *vn, *tab;
218 int32_t x, y0, y1, dx, dy, slope, fx, fy;
220 g3d_pixel *fbptr, *pptr, color;
221 int32_t tu, tv, du, dv, uslope, vslope;
225 top = pfill_fb.height;
229 /* scan the edge between the current and next vertex */
233 if(vn->y == v->y) continue; /* XXX ??? */
236 /* inrementing Y: left side */
239 /* decrementing Y: right side, flip vertices to trace bottom->up */
245 /* calculate edge slope */
248 slope = (dx << 8) / dy;
254 uslope = (du << 8) / dy;
255 vslope = (dv << 8) / dy;
257 y0 = (v->y + 0x100) & 0xffffff00; /* start from the next scanline */
258 fy = y0 - v->y; /* fractional part before the next scanline */
259 fx = (fy * slope) >> 8; /* X adjust for the step to the next scanline */
260 x = v->x + fx; /* adjust X */
261 y1 = vn->y & 0xffffff00; /* last scanline of the edge <= vn->y */
263 /* also adjust other interpolated attributes */
264 tu += (fy * uslope) >> 8;
265 tv += (fy * vslope) >> 8;
268 if(line < top) top = line;
269 if((y1 >> 8) > bot) bot = y1 >> 8;
271 if(line > 0) tab += line;
273 while(line <= (y1 >> 8) && line < pfill_fb.height) {
275 int val = x < 0 ? 0 : x >> 8;
276 tab->x = val < pfill_fb.width ? val : pfill_fb.width - 1;
289 if(bot >= pfill_fb.height) bot = pfill_fb.height - 1;
291 fbptr = pfill_fb.pixels + top * pfill_fb.width;
292 for(i=top; i<=bot; i++) {
294 len = right[i].x - start;
295 /* XXX we probably need more precision in left/right.x */
297 dx = len == 0 ? 256 : (len << 8);
302 pptr = fbptr + start;
306 tx = (tu >> (16 - pfill_tex.xshift)) & pfill_tex.xmask;
307 ty = (tv >> (16 - pfill_tex.yshift)) & pfill_tex.ymask;
308 texel = pfill_tex.pixels[(ty << pfill_tex.xshift) + tx];
317 /* This is not correct, should be /255, but it's much faster
318 * to shift by 8 (/256), and won't make a huge difference
320 cr = (cr * G3D_UNPACK_R(texel)) >> 8;
321 cg = (cg * G3D_UNPACK_G(texel)) >> 8;
322 cb = (cb * G3D_UNPACK_B(texel)) >> 8;
324 if(cr >= 255) cr = 255;
325 if(cg >= 255) cg = 255;
326 if(cb >= 255) cb = 255;
327 color = G3D_PACK_RGB(cr, cg, cb);
330 fbptr += pfill_fb.width;