1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the AUTHORS
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 /*
24 * This file is based on, or a modified version of code from TinyGL (C) 1997-1998 Fabrice Bellard,
25 * which is licensed under the zlib-license (see LICENSE).
26 * It also has modifications by the ResidualVM-team, which are covered under the GPLv2 (or later).
27 */
28
29 #include "common/endian.h"
30 #include "graphics/tinygl/zbuffer.h"
31 #include "graphics/tinygl/zgl.h"
32
33 namespace TinyGL {
34
35 static const int NB_INTERP = 8;
36
37 template <bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending>
putPixelFlat(FrameBuffer * buffer,int buf,unsigned int * pz,int _a,int x,int y,unsigned int & z,unsigned int & r,unsigned int & g,unsigned int & b,unsigned int & a,int & dzdx)38 FORCEINLINE static void putPixelFlat(FrameBuffer *buffer, int buf, unsigned int *pz, int _a,
39 int x, int y, unsigned int &z, unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a, int &dzdx) {
40 if ((!kEnableScissor || !buffer->scissorPixel(x + _a, y)) && buffer->compareDepth(z, pz[_a])) {
41 buffer->writePixel<kEnableAlphaTest, kEnableBlending, kDepthWrite>(buf + _a, a >> (ZB_POINT_ALPHA_BITS - 8), r >> (ZB_POINT_RED_BITS - 8), g >> (ZB_POINT_GREEN_BITS - 8), b >> (ZB_POINT_BLUE_BITS - 8), z);
42 }
43 z += dzdx;
44 }
45
46 template <bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending>
putPixelSmooth(FrameBuffer * buffer,int buf,unsigned int * pz,int _a,int x,int y,unsigned int & z,unsigned int & r,unsigned int & g,unsigned int & b,unsigned int & a,int & dzdx,int & drdx,int & dgdx,int & dbdx,unsigned int dadx)47 FORCEINLINE static void putPixelSmooth(FrameBuffer *buffer, int buf, unsigned int *pz, int _a,
48 int x, int y, unsigned int &z, unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a,
49 int &dzdx, int &drdx, int &dgdx, int &dbdx, unsigned int dadx) {
50 if ((!kEnableScissor || !buffer->scissorPixel(x + _a, y)) && buffer->compareDepth(z, pz[_a])) {
51 buffer->writePixel<kEnableAlphaTest, kEnableBlending, kDepthWrite>(buf + _a, a >> (ZB_POINT_ALPHA_BITS - 8), r >> (ZB_POINT_RED_BITS - 8), g >> (ZB_POINT_GREEN_BITS - 8), b >> (ZB_POINT_BLUE_BITS - 8), z);
52 }
53 z += dzdx;
54 a += dadx;
55 r += drdx;
56 g += dgdx;
57 b += dbdx;
58 }
59
60 template <bool kDepthWrite, bool kEnableScissor>
putPixelDepth(FrameBuffer * buffer,int buf,unsigned int * pz,int _a,int x,int y,unsigned int & z,int & dzdx)61 FORCEINLINE static void putPixelDepth(FrameBuffer *buffer, int buf, unsigned int *pz, int _a, int x, int y, unsigned int &z, int &dzdx) {
62 if ((!kEnableScissor || !buffer->scissorPixel(x + _a, y)) && buffer->compareDepth(z, pz[_a])) {
63 if (kDepthWrite) {
64 pz[_a] = z;
65 }
66 }
67 z += dzdx;
68 }
69
70 template <bool kDepthWrite, bool kAlphaTestEnabled, bool kEnableScissor, bool kBlendingEnabled>
putPixelShadow(FrameBuffer * buffer,int buf,unsigned int * pz,int _a,int x,int y,unsigned int & z,unsigned int & r,unsigned int & g,unsigned int & b,int & dzdx,unsigned char * pm)71 FORCEINLINE static void putPixelShadow(FrameBuffer *buffer, int buf, unsigned int *pz, int _a, int x, int y, unsigned int &z, unsigned int &r, unsigned int &g, unsigned int &b, int &dzdx, unsigned char *pm) {
72 if ((!kEnableScissor || !buffer->scissorPixel(x + _a, y)) && buffer->compareDepth(z, pz[_a]) && pm[_a]) {
73 buffer->writePixel<kAlphaTestEnabled, kBlendingEnabled, kDepthWrite>(buf + _a, 255, r >> (ZB_POINT_RED_BITS - 8), g >> (ZB_POINT_GREEN_BITS - 8), b >> (ZB_POINT_BLUE_BITS - 8), z);
74 }
75 z += dzdx;
76 }
77
78 template <bool kDepthWrite, bool kLightsMode, bool kSmoothMode, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending>
putPixelTextureMappingPerspective(FrameBuffer * buffer,int buf,Graphics::PixelFormat & textureFormat,Graphics::PixelBuffer & texture,unsigned int * pz,int _a,int x,int y,unsigned int & z,unsigned int & t,unsigned int & s,unsigned int & r,unsigned int & g,unsigned int & b,unsigned int & a,int & dzdx,int & dsdx,int & dtdx,int & drdx,int & dgdx,int & dbdx,unsigned int dadx)79 FORCEINLINE static void putPixelTextureMappingPerspective(FrameBuffer *buffer, int buf,
80 Graphics::PixelFormat &textureFormat, Graphics::PixelBuffer &texture, unsigned int *pz, int _a,
81 int x, int y, unsigned int &z, unsigned int &t, unsigned int &s, unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a,
82 int &dzdx, int &dsdx, int &dtdx, int &drdx, int &dgdx, int &dbdx, unsigned int dadx) {
83 if ((!kEnableScissor || !buffer->scissorPixel(x + _a, y)) && buffer->compareDepth(z, pz[_a])) {
84 unsigned sss = (s & buffer->_textureSizeMask) >> ZB_POINT_ST_FRAC_BITS;
85 unsigned ttt = (t & buffer->_textureSizeMask) >> ZB_POINT_ST_FRAC_BITS;
86 int pixel = ttt * buffer->_textureSize + sss;
87 uint8 c_a, c_r, c_g, c_b;
88 uint32 *textureBuffer = (uint32 *)texture.getRawBuffer(pixel);
89 uint32 col = *textureBuffer;
90 c_a = (col >> textureFormat.aShift) & 0xFF;
91 c_r = (col >> textureFormat.rShift) & 0xFF;
92 c_g = (col >> textureFormat.gShift) & 0xFF;
93 c_b = (col >> textureFormat.bShift) & 0xFF;
94 if (kLightsMode) {
95 unsigned int l_a = (a >> (ZB_POINT_ALPHA_BITS - 8));
96 unsigned int l_r = (r >> (ZB_POINT_RED_BITS - 8));
97 unsigned int l_g = (g >> (ZB_POINT_GREEN_BITS - 8));
98 unsigned int l_b = (b >> (ZB_POINT_BLUE_BITS - 8));
99 c_a = (c_a * l_a) >> (ZB_POINT_ALPHA_BITS - 8);
100 c_r = (c_r * l_r) >> (ZB_POINT_RED_BITS - 8);
101 c_g = (c_g * l_g) >> (ZB_POINT_GREEN_BITS - 8);
102 c_b = (c_b * l_b) >> (ZB_POINT_BLUE_BITS - 8);
103 }
104 buffer->writePixel<kEnableAlphaTest, kEnableBlending, kDepthWrite>(buf + _a, c_a, c_r, c_g, c_b, z);
105 }
106 z += dzdx;
107 s += dsdx;
108 t += dtdx;
109 if (kSmoothMode) {
110 a += dadx;
111 r += drdx;
112 g += dgdx;
113 b += dbdx;
114 }
115 }
116
117 template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawLogic, bool kDepthWrite, bool kAlphaTestEnabled, bool kEnableScissor, bool kBlendingEnabled>
fillTriangle(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)118 void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
119 Graphics::PixelBuffer texture;
120 Graphics::PixelFormat textureFormat;
121 float fdzdx = 0, fndzdx = 0, ndszdx = 0, ndtzdx = 0;
122
123 ZBufferPoint *tp, *pr1 = 0, *pr2 = 0, *l1 = 0, *l2 = 0;
124 float fdx1, fdx2, fdy1, fdy2, fz0, d1, d2;
125 unsigned int *pz1 = NULL;
126 unsigned char *pm1 = NULL;
127 int part, update_left = 1, update_right = 1;
128
129 int nb_lines, dx1, dy1, tmp, dx2, dy2, y;
130
131 int error = 0, derror = 0;
132 int x1 = 0, dxdy_min = 0, dxdy_max = 0;
133 // warning: x2 is multiplied by 2^16
134 int x2 = 0, dx2dy2 = 0;
135
136 int z1 = 0, dzdx = 0, dzdy = 0, dzdl_min = 0, dzdl_max = 0;
137
138 int r1 = 0, drdx = 0, drdy = 0, drdl_min = 0, drdl_max = 0;
139 int g1 = 0, dgdx = 0, dgdy = 0, dgdl_min = 0, dgdl_max = 0;
140 int b1 = 0, dbdx = 0, dbdy = 0, dbdl_min = 0, dbdl_max = 0;
141 int a1 = 0, dadx = 0, dady = 0, dadl_min = 0, dadl_max = 0;
142
143 float sz1 = 0.0, dszdx = 0, dszdy = 0, dszdl_min = 0.0, dszdl_max = 0.0;
144 float tz1 = 0.0, dtzdx = 0, dtzdy = 0, dtzdl_min = 0.0, dtzdl_max = 0.0;
145
146 // we sort the vertex with increasing y
147 if (p1->y < p0->y) {
148 tp = p0;
149 p0 = p1;
150 p1 = tp;
151 }
152 if (p2->y < p0->y) {
153 tp = p2;
154 p2 = p1;
155 p1 = p0;
156 p0 = tp;
157 } else if (p2->y < p1->y) {
158 tp = p1;
159 p1 = p2;
160 p2 = tp;
161 }
162
163 // we compute dXdx and dXdy for all interpolated values
164
165 fdx1 = (float)(p1->x - p0->x);
166 fdy1 = (float)(p1->y - p0->y);
167
168 fdx2 = (float)(p2->x - p0->x);
169 fdy2 = (float)(p2->y - p0->y);
170
171 fz0 = fdx1 * fdy2 - fdx2 * fdy1;
172 if (fz0 == 0)
173 return;
174 fz0 = (float)(1.0 / fz0);
175
176 fdx1 *= fz0;
177 fdy1 *= fz0;
178 fdx2 *= fz0;
179 fdy2 *= fz0;
180
181 if (kInterpZ) {
182 d1 = (float)(p1->z - p0->z);
183 d2 = (float)(p2->z - p0->z);
184 dzdx = (int)(fdy2 * d1 - fdy1 * d2);
185 dzdy = (int)(fdx1 * d2 - fdx2 * d1);
186 }
187
188 if (kInterpRGB) {
189 d1 = (float)(p1->r - p0->r);
190 d2 = (float)(p2->r - p0->r);
191 drdx = (int)(fdy2 * d1 - fdy1 * d2);
192 drdy = (int)(fdx1 * d2 - fdx2 * d1);
193
194 d1 = (float)(p1->g - p0->g);
195 d2 = (float)(p2->g - p0->g);
196 dgdx = (int)(fdy2 * d1 - fdy1 * d2);
197 dgdy = (int)(fdx1 * d2 - fdx2 * d1);
198
199 d1 = (float)(p1->b - p0->b);
200 d2 = (float)(p2->b - p0->b);
201 dbdx = (int)(fdy2 * d1 - fdy1 * d2);
202 dbdy = (int)(fdx1 * d2 - fdx2 * d1);
203
204 d1 = (float)(p1->a - p0->a);
205 d2 = (float)(p2->a - p0->a);
206 dadx = (int)(fdy2 * d1 - fdy1 * d2);
207 dady = (int)(fdx1 * d2 - fdx2 * d1);
208 }
209
210 if (kInterpST || kInterpSTZ) {
211 if (kInterpSTZ) {
212 float zz;
213 zz = (float)p0->z;
214 p0->sz = (float)p0->s * zz;
215 p0->tz = (float)p0->t * zz;
216 zz = (float)p1->z;
217 p1->sz = (float)p1->s * zz;
218 p1->tz = (float)p1->t * zz;
219 zz = (float)p2->z;
220 p2->sz = (float)p2->s * zz;
221 p2->tz = (float)p2->t * zz;
222 } else {
223 p0->sz = (float)p0->s;
224 p0->tz = (float)p0->t;
225 p1->sz = (float)p1->s;
226 p1->tz = (float)p1->t;
227 p2->sz = (float)p2->s;
228 p2->tz = (float)p2->t;
229 }
230
231 d1 = p1->sz - p0->sz;
232 d2 = p2->sz - p0->sz;
233 dszdx = (fdy2 * d1 - fdy1 * d2);
234 dszdy = (fdx1 * d2 - fdx2 * d1);
235
236 d1 = p1->tz - p0->tz;
237 d2 = p2->tz - p0->tz;
238 dtzdx = (fdy2 * d1 - fdy1 * d2);
239 dtzdy = (fdx1 * d2 - fdx2 * d1);
240 }
241
242 // screen coordinates
243
244 int pp1 = xsize * p0->y;
245 pz1 = _zbuf + p0->y * xsize;
246
247 switch (kDrawLogic) {
248 case DRAW_SHADOW_MASK:
249 pm1 = shadow_mask_buf + p0->y * xsize;
250 break;
251 case DRAW_SHADOW:
252 pm1 = shadow_mask_buf + p0->y * xsize;
253 r1 = shadow_color_r;
254 g1 = shadow_color_g;
255 b1 = shadow_color_b;
256 break;
257 case DRAW_DEPTH_ONLY:
258 break;
259 case DRAW_FLAT:
260 r1 = p2->r;
261 g1 = p2->g;
262 b1 = p2->b;
263 a1 = p2->a;
264 break;
265 case DRAW_SMOOTH:
266 break;
267 default:
268 break;
269 }
270
271 if ((kInterpST || kInterpSTZ) && (kDrawLogic == DRAW_FLAT || kDrawLogic == DRAW_SMOOTH)) {
272 texture = current_texture;
273 textureFormat = texture.getFormat();
274 assert(textureFormat.bytesPerPixel == 4);
275 fdzdx = (float)dzdx;
276 fndzdx = NB_INTERP * fdzdx;
277 ndszdx = NB_INTERP * dszdx;
278 ndtzdx = NB_INTERP * dtzdx;
279 }
280
281 if (fz0 > 0) {
282 l1 = p0;
283 l2 = p2;
284 pr1 = p0;
285 pr2 = p1;
286 } else {
287 l1 = p0;
288 l2 = p1;
289 pr1 = p0;
290 pr2 = p2;
291 }
292 nb_lines = p1->y - p0->y;
293 y = p0->y;
294 for (part = 0; part < 2; part++) {
295 if (part == 1) {
296 // second part
297 if (fz0 > 0) {
298 update_left = 0;
299 pr1 = p1;
300 pr2 = p2;
301 } else {
302 update_right = 0;
303 l1 = p1;
304 l2 = p2;
305 }
306 nb_lines = p2->y - p1->y + 1;
307 }
308
309 // compute the values for the left edge
310
311 if (update_left) {
312 dy1 = l2->y - l1->y;
313 dx1 = l2->x - l1->x;
314 if (dy1 > 0)
315 tmp = (dx1 << 16) / dy1;
316 else
317 tmp = 0;
318 x1 = l1->x;
319 error = 0;
320 derror = tmp & 0x0000ffff;
321 dxdy_min = tmp >> 16;
322 dxdy_max = dxdy_min + 1;
323
324 if (kInterpZ) {
325 z1 = l1->z;
326 dzdl_min = (dzdy + dzdx * dxdy_min);
327 dzdl_max = dzdl_min + dzdx;
328 }
329
330 if (kInterpRGB) {
331 r1 = l1->r;
332 drdl_min = (drdy + drdx * dxdy_min);
333 drdl_max = drdl_min + drdx;
334
335 g1 = l1->g;
336 dgdl_min = (dgdy + dgdx * dxdy_min);
337 dgdl_max = dgdl_min + dgdx;
338
339 b1 = l1->b;
340 dbdl_min = (dbdy + dbdx * dxdy_min);
341 dbdl_max = dbdl_min + dbdx;
342
343 a1 = l1->a;
344 dadl_min = (dady + dadx * dxdy_min);
345 dadl_max = dadl_min + dadx;
346 }
347
348 if (kInterpST || kInterpSTZ) {
349 sz1 = l1->sz;
350 dszdl_min = (dszdy + dszdx * dxdy_min);
351 dszdl_max = dszdl_min + dszdx;
352
353 tz1 = l1->tz;
354 dtzdl_min = (dtzdy + dtzdx * dxdy_min);
355 dtzdl_max = dtzdl_min + dtzdx;
356 }
357 }
358
359 // compute values for the right edge
360
361 if (update_right) {
362 dx2 = (pr2->x - pr1->x);
363 dy2 = (pr2->y - pr1->y);
364 if (dy2 > 0)
365 dx2dy2 = (dx2 << 16) / dy2;
366 else
367 dx2dy2 = 0;
368 x2 = pr1->x << 16;
369 }
370
371 // we draw all the scan line of the part
372 while (nb_lines > 0) {
373 int x = x1;
374 {
375 if (kDrawLogic == DRAW_DEPTH_ONLY ||
376 (kDrawLogic == DRAW_FLAT && !(kInterpST || kInterpSTZ))) {
377 int pp;
378 int n;
379 unsigned int *pz;
380 unsigned int z, a;
381 int buf = pp1 + x1;
382 unsigned int r = r1;
383 unsigned int g = g1;
384 unsigned int b = b1;
385 n = (x2 >> 16) - x1;
386 pp = pp1 + x1;
387 if (kInterpZ) {
388 pz = pz1 + x1;
389 z = z1;
390 }
391 if (kDrawLogic == DRAW_FLAT) {
392 a = a1;
393 }
394 while (n >= 3) {
395 if (kDrawLogic == DRAW_DEPTH_ONLY) {
396 putPixelDepth<kDepthWrite, kEnableScissor>(this, buf, pz, 0, x, y, z, dzdx);
397 putPixelDepth<kDepthWrite, kEnableScissor>(this, buf, pz, 1, x, y, z, dzdx);
398 putPixelDepth<kDepthWrite, kEnableScissor>(this, buf, pz, 2, x, y, z, dzdx);
399 putPixelDepth<kDepthWrite, kEnableScissor>(this, buf, pz, 3, x, y, z, dzdx);
400 buf += 4;
401 }
402 if (kDrawLogic == DRAW_FLAT) {
403 putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, pp, pz, 0, x, y, z, r, g, b, a, dzdx);
404 putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, pp, pz, 1, x, y, z, r, g, b, a, dzdx);
405 putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, pp, pz, 2, x, y, z, r, g, g, a, dzdx);
406 putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, pp, pz, 3, x, y, z, r, g, b, a, dzdx);
407 }
408 if (kInterpZ) {
409 pz += 4;
410 }
411 pp += 4;
412 n -= 4;
413 x += 4;
414 }
415 while (n >= 0) {
416 if (kDrawLogic == DRAW_DEPTH_ONLY) {
417 putPixelDepth<kDepthWrite, kEnableScissor>(this, buf, pz, 0, x, y, z, dzdx);
418 buf ++;
419 }
420 if (kDrawLogic == DRAW_FLAT) {
421 putPixelFlat<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, pp, pz, 0, x, y, z, r, g, b, a, dzdx);
422 }
423 if (kInterpZ) {
424 pz += 1;
425 }
426 pp += 1;
427 n -= 1;
428 x += 1;
429 }
430 } else if (kDrawLogic == DRAW_SHADOW_MASK) {
431 unsigned char *pm;
432 int n;
433
434 n = (x2 >> 16) - x1;
435 pm = pm1 + x1;
436 while (n >= 3) {
437 pm[0] = 0xff;
438 pm[1] = 0xff;
439 pm[2] = 0xff;
440 pm[3] = 0xff;
441 pm += 4;
442 n -= 4;
443 x += 4;
444 }
445 while (n >= 0) {
446 pm[0] = 0xff;
447 pm += 1;
448 n -= 1;
449 x += 1;
450 }
451 } else if (kDrawLogic == DRAW_SHADOW) {
452 unsigned char *pm;
453 int n;
454 unsigned int *pz;
455 unsigned int z;
456 unsigned int r = r1;
457 unsigned int g = g1;
458 unsigned int b = b1;
459
460 n = (x2 >> 16) - x1;
461
462 int buf = pp1 + x1;
463
464 pm = pm1 + x1;
465 pz = pz1 + x1;
466 z = z1;
467 while (n >= 3) {
468 putPixelShadow<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 0, x, y, z, r, g, b, dzdx, pm);
469 putPixelShadow<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 1, x, y, z, r, g, b, dzdx, pm);
470 putPixelShadow<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 2, x, y, z, r, g, b, dzdx, pm);
471 putPixelShadow<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 3, x, y, z, r, g, b, dzdx, pm);
472 pz += 4;
473 pm += 4;
474 buf += 4;
475 n -= 4;
476 x += 4;
477 }
478 while (n >= 0) {
479 putPixelShadow<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 0, x, y, z, r, g, b, dzdx, pm);
480 pz += 1;
481 pm += 1;
482 buf += 1;
483 n -= 1;
484 x += 1;
485 }
486 } else if (kDrawLogic == DRAW_SMOOTH && !(kInterpST || kInterpSTZ)) {
487 unsigned int *pz;
488 int buf = pp1 + x1;
489 unsigned int z, r, g, b, a;
490 int n;
491 n = (x2 >> 16) - x1;
492 pz = pz1 + x1;
493 z = z1;
494 r = r1;
495 g = g1;
496 b = b1;
497 a = a1;
498 while (n >= 3) {
499 putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 0, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
500 putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 1, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
501 putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 2, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
502 putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 3, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
503 pz += 4;
504 buf += 4;
505 n -= 4;
506 x += 4;
507 }
508 while (n >= 0) {
509 putPixelSmooth<kDepthWrite, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, pz, 0, x, y, z, r, g, b, a, dzdx, drdx, dgdx, dbdx, dadx);
510 buf += 1;
511 pz += 1;
512 n -= 1;
513 x += 1;
514 }
515 } else if (kInterpST || kInterpSTZ) {
516 unsigned int *pz;
517 unsigned int s, t, z, r, g, b, a;
518 int n;
519 float sz, tz, fz, zinv;
520 int dsdx, dtdx;
521
522 n = (x2 >> 16) - x1;
523 fz = (float)z1;
524 zinv = (float)(1.0 / fz);
525
526 int buf = pp1 + x1;
527
528 pz = pz1 + x1;
529 z = z1;
530 sz = sz1;
531 tz = tz1;
532 r = r1;
533 g = g1;
534 b = b1;
535 a = a1;
536 while (n >= (NB_INTERP - 1)) {
537 {
538 float ss, tt;
539 ss = sz * zinv;
540 tt = tz * zinv;
541 s = (int)ss;
542 t = (int)tt;
543 dsdx = (int)((dszdx - ss * fdzdx) * zinv);
544 dtdx = (int)((dtzdx - tt * fdzdx) * zinv);
545 fz += fndzdx;
546 zinv = (float)(1.0 / fz);
547 }
548 for (int _a = 0; _a < NB_INTERP; _a++) {
549 putPixelTextureMappingPerspective<kDepthWrite, kInterpRGB, kDrawLogic == DRAW_SMOOTH, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, textureFormat, texture,
550 pz, _a, x, y, z, t, s, r, g, b, a, dzdx, dsdx, dtdx, drdx, dgdx, dbdx, dadx);
551 }
552 pz += NB_INTERP;
553 buf += NB_INTERP;
554 n -= NB_INTERP;
555 x += NB_INTERP;
556 sz += ndszdx;
557 tz += ndtzdx;
558 }
559
560 {
561 float ss, tt;
562 ss = sz * zinv;
563 tt = tz * zinv;
564 s = (int)ss;
565 t = (int)tt;
566 dsdx = (int)((dszdx - ss * fdzdx) * zinv);
567 dtdx = (int)((dtzdx - tt * fdzdx) * zinv);
568 }
569
570 while (n >= 0) {
571 putPixelTextureMappingPerspective<kDepthWrite, kInterpRGB, kDrawLogic == DRAW_SMOOTH, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, textureFormat, texture,
572 pz, 0, x, y, z, t, s, r, g, b, a, dzdx, dsdx, dtdx, drdx, dgdx, dbdx, dadx);
573 pz += 1;
574 buf += 1;
575 n -= 1;
576 x += 1;
577 }
578 }
579 }
580
581 // left edge
582 error += derror;
583 if (error > 0) {
584 error -= 0x10000;
585 x1 += dxdy_max;
586 if (kInterpZ) {
587 z1 += dzdl_max;
588 }
589
590 if (kInterpRGB) {
591 r1 += drdl_max;
592 g1 += dgdl_max;
593 b1 += dbdl_max;
594 a1 += dadl_max;
595 }
596
597 if (kInterpST || kInterpSTZ) {
598 sz1 += dszdl_max;
599 tz1 += dtzdl_max;
600 }
601 } else {
602 x1 += dxdy_min;
603 if (kInterpZ) {
604 z1 += dzdl_min;
605 }
606 if (kInterpRGB) {
607 r1 += drdl_min;
608 g1 += dgdl_min;
609 b1 += dbdl_min;
610 a1 += dadl_min;
611 }
612 if (kInterpST || kInterpSTZ) {
613 sz1 += dszdl_min;
614 tz1 += dtzdl_min;
615 }
616 }
617
618 // right edge
619 x2 += dx2dy2;
620
621 // screen coordinates
622 pp1 += xsize;
623 pz1 += xsize;
624
625 if (kDrawLogic == DRAW_SHADOW || kDrawLogic == DRAW_SHADOW_MASK)
626 pm1 = pm1 + xsize;
627 nb_lines--;
628 y++;
629 }
630 }
631 }
632
633 template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawMode, bool kDepthWrite, bool kEnableAlphaTest, bool kEnableScissor>
fillTriangle(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)634 void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
635 if (_blendingEnabled) {
636 fillTriangle<kInterpRGB, kInterpZ, kInterpST, kInterpSTZ, kDrawMode, kDepthWrite, kEnableAlphaTest, kEnableScissor, true>(p0, p1, p2);
637 } else {
638 fillTriangle<kInterpRGB, kInterpZ, kInterpST, kInterpSTZ, kDrawMode, kDepthWrite, kEnableAlphaTest, kEnableScissor, false>(p0, p1, p2);
639 }
640 }
641
642 template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawMode, bool kDepthWrite, bool kEnableAlphaTest>
fillTriangle(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)643 void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
644 if (_enableScissor) {
645 fillTriangle<kInterpRGB, kInterpZ, kInterpST, kInterpSTZ, kDrawMode, kDepthWrite, kEnableAlphaTest, true>(p0, p1, p2);
646 } else {
647 fillTriangle<kInterpRGB, kInterpZ, kInterpST, kInterpSTZ, kDrawMode, kDepthWrite, kEnableAlphaTest, false>(p0, p1, p2);
648 }
649 }
650
651 template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawMode, bool kDepthWrite>
fillTriangle(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)652 void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
653 if (_alphaTestEnabled) {
654 fillTriangle<kInterpRGB, kInterpZ, kInterpST, kInterpSTZ, kDrawMode, kDepthWrite, true>(p0, p1, p2);
655 } else {
656 fillTriangle<kInterpRGB, kInterpZ, kInterpST, kInterpSTZ, kDrawMode, kDepthWrite, false>(p0, p1, p2);
657 }
658 }
659
660 template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawMode>
fillTriangle(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)661 void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
662 if (_depthWrite) {
663 fillTriangle<kInterpRGB, kInterpZ, kInterpST, kInterpSTZ, kDrawMode, true>(p0, p1, p2);
664 } else {
665 fillTriangle<kInterpRGB, kInterpZ, kInterpST, kInterpSTZ, kDrawMode, false>(p0, p1, p2);
666 }
667 }
668
fillTriangleDepthOnly(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)669 void FrameBuffer::fillTriangleDepthOnly(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
670 const bool interpZ = true;
671 const bool interpRGB = false;
672 const bool interpST = false;
673 const bool interpSTZ = false;
674 if (_depthWrite && _depthTestEnabled)
675 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_DEPTH_ONLY, true>(p0, p1, p2);
676 else
677 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_DEPTH_ONLY, false>(p0, p1, p2);
678 }
679
fillTriangleFlat(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)680 void FrameBuffer::fillTriangleFlat(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
681 const bool interpZ = true;
682 const bool interpRGB = false;
683 const bool interpST = false;
684 const bool interpSTZ = false;
685 if (_depthWrite && _depthTestEnabled)
686 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_FLAT, true>(p0, p1, p2);
687 else
688 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_FLAT, false>(p0, p1, p2);
689 }
690
691 // Smooth filled triangle.
fillTriangleSmooth(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)692 void FrameBuffer::fillTriangleSmooth(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
693 const bool interpZ = true;
694 const bool interpRGB = true;
695 const bool interpST = false;
696 const bool interpSTZ = false;
697 if (_depthWrite && _depthTestEnabled)
698 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_SMOOTH, true>(p0, p1, p2);
699 else
700 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_SMOOTH, false>(p0, p1, p2);
701 }
702
fillTriangleTextureMappingPerspectiveSmooth(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)703 void FrameBuffer::fillTriangleTextureMappingPerspectiveSmooth(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
704 const bool interpZ = true;
705 const bool interpRGB = true;
706 const bool interpST = false;
707 const bool interpSTZ = true;
708 if (_depthWrite && _depthTestEnabled)
709 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_SMOOTH, true>(p0, p1, p2);
710 else
711 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_SMOOTH, false>(p0, p1, p2);
712 }
713
fillTriangleTextureMappingPerspectiveFlat(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)714 void FrameBuffer::fillTriangleTextureMappingPerspectiveFlat(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
715 const bool interpZ = true;
716 const bool interpRGB = true;
717 const bool interpST = false;
718 const bool interpSTZ = true;
719 if (_depthWrite && _depthTestEnabled)
720 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_FLAT, true>(p0, p1, p2);
721 else
722 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_FLAT, false>(p0, p1, p2);
723 }
724
fillTriangleFlatShadowMask(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)725 void FrameBuffer::fillTriangleFlatShadowMask(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
726 const bool interpZ = true;
727 const bool interpRGB = false;
728 const bool interpST = false;
729 const bool interpSTZ = false;
730 if (_depthWrite && _depthTestEnabled)
731 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_SHADOW_MASK, true>(p0, p1, p2);
732 else
733 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_SHADOW_MASK, false>(p0, p1, p2);
734 }
735
fillTriangleFlatShadow(ZBufferPoint * p0,ZBufferPoint * p1,ZBufferPoint * p2)736 void FrameBuffer::fillTriangleFlatShadow(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
737 const bool interpZ = true;
738 const bool interpRGB = false;
739 const bool interpST = false;
740 const bool interpSTZ = false;
741 if (_depthWrite && _depthTestEnabled)
742 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_SHADOW, true>(p0, p1, p2);
743 else
744 fillTriangle<interpRGB, interpZ, interpST, interpSTZ, DRAW_SHADOW, false>(p0, p1, p2);
745 }
746
747 } // end of namespace TinyGL
748