TGX 1.0.3
A tiny 2D/3D graphics library optimized for 32 bits microcontrollers.
Loading...
Searching...
No Matches
Shaders.h
Go to the documentation of this file.
1
5//
6// Copyright 2020 Arvind Singh
7//
8// This library is free software; you can redistribute it and/or
9// modify it under the terms of the GNU Lesser General Public
10// License as published by the Free Software Foundation; either
11// version 2.1 of the License, or (at your option) any later version.
12//
13// This library is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
16// Lesser General Public License for more details.
17//
18// You should have received a copy of the GNU Lesser General Public
19// License along with this library; If not, see <http://www.gnu.org/licenses/>.
20#ifndef _TGX_SHADERS_H_
21#define _TGX_SHADERS_H_
22
23
24// only C++, no plain C
25#ifdef __cplusplus
26
27
28#include "ShaderParams.h"
29
30namespace tgx
31{
32
34 inline TGX_INLINE int shaderclip(int v, int maxv)
35 {
36 return ((v < 0) ? 0 : ((v > maxv) ? maxv : v));
37 }
38
39
40
44 template<typename color_t, typename ZBUFFER_t>
45 void shader_test(const int32_t& offset, const int32_t& lx, const int32_t& ly,
46 const int32_t& dx1, const int32_t& dy1, int32_t O1, const tgx::RasterizerVec4& fP1,
47 const int32_t& dx2, const int32_t& dy2, int32_t O2, const tgx::RasterizerVec4& fP2,
48 const int32_t& dx3, const int32_t& dy3, int32_t O3, const tgx::RasterizerVec4& fP3,
49 const tgx::RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
50 {
51 color_t col = (color_t)tgx::RGB32_Red; //data.facecolor;
52 color_t* buf = data.im->data() + offset;
53 const int32_t stride = data.im->stride();
54 for (int y = 0; y < ly; y++)
55 {
56 for (int x = 0; x < lx; x++)
57 {
58 const int32_t o1 = O1 + dx1 * x + dy1 * y;
59 const int32_t o2 = O2 + dx2 * x + dy2 * y;
60 const int32_t o3 = O3 + dx3 * x + dy3 * y;
61 if ((o1 >= 0) && (o2 >= 0) && (o3 >= 0))
62 {
63 buf[x + stride * y].blend256(col, 128);
64 }
65 }
66 }
67 }
68
69
73 template<typename color_t, typename ZBUFFER_t>
74 void shader_Flat(const int32_t& offset, const int32_t& lx, const int32_t& ly,
75 const int32_t& dx1, const int32_t& dy1, int32_t O1, const RasterizerVec4& fP1,
76 const int32_t& dx2, const int32_t& dy2, int32_t O2, const RasterizerVec4& fP2,
77 const int32_t& dx3, const int32_t& dy3, int32_t O3, const RasterizerVec4& fP3,
78 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
79 {
80 color_t col = (color_t)data.facecolor;
81 color_t* buf = data.im->data() + offset;
82 const int32_t stride = data.im->stride();
83
84 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
85
86 while ((uintptr_t)(buf) < end)
87 { // iterate over scanlines
88 int32_t bx = 0; // start offset
89 if (O1 < 0)
90 {
91 // we know that dx1 > 0
92 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
93 }
94 if (O2 < 0)
95 {
96 if (dx2 <= 0)
97 {
98 if (dy2 <= 0) return;
99 const int32_t by = (-O2 + dy2 - 1) / dy2;
100 O1 += (by * dy1);
101 O2 += (by * dy2);
102 O3 += (by * dy3);
103 const int32_t offs = by * stride;
104 buf += offs;
105 continue;
106 }
107 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
108 }
109 if (O3 < 0)
110 {
111 if (dx3 <= 0)
112 {
113 if (dy3 <= 0) return;
114 const int32_t by = (-O3 + dy3 - 1) / dy3;
115 O1 += (by * dy1);
116 O2 += (by * dy2);
117 O3 += (by * dy3);
118 const int32_t offs = by * stride;
119 buf += offs;
120 continue;
121 }
122 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
123 }
124
125 int32_t C2 = O2 + (dx2 * bx);
126 int32_t C3 = O3 + (dx3 * bx);
127 while ((bx < lx) && ((C2 | C3) >= 0))
128 {
129 buf[bx] = col;
130 //buf[bx].blend256(col, 128) // for testing.
131 C2 += dx2;
132 C3 += dx3;
133 bx++;
134 }
135
136 O1 += dy1;
137 O2 += dy2;
138 O3 += dy3;
139 buf += stride;
140 }
141 }
142
143
144
148 template<typename color_t, typename ZBUFFER_t>
149 void shader_Gouraud(const int32_t& offset, const int32_t& lx, const int32_t& ly,
150 const int32_t& dx1, const int32_t& dy1, int32_t O1, const RasterizerVec4& fP1,
151 const int32_t& dx2, const int32_t& dy2, int32_t O2, const RasterizerVec4& fP2,
152 const int32_t& dx3, const int32_t& dy3, int32_t O3, const RasterizerVec4& fP3,
153 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
154 {
155 color_t* buf = data.im->data() + offset;
156 const int32_t stride = data.im->stride();
157
158 const color_t col1 = (color_t)fP1.color;
159 const color_t col2 = (color_t)fP2.color;
160 const color_t col3 = (color_t)fP3.color;
161
162 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
163 const int32_t pa = O1 + O2 + O3;
164 const int32_t E = ((pa == 0) ? 1 : 0);
165 const int32_t aera = pa + E;
166 const int shiftC = (aera > (1 << 22)) ? 10 : 0; // prevent overflow during color interpolation
167
168 while ((uintptr_t)(buf) < end)
169 { // iterate over scanlines
170 int32_t bx = 0; // start offset
171 if (O1 < 0)
172 {
173 // we know that dx1 > 0
174 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
175 }
176 if (O2 < 0)
177 {
178 if (dx2 <= 0)
179 {
180 if (dy2 <= 0) return;
181 const int32_t by = (-O2 + dy2 - 1) / dy2;
182 O1 += (by * dy1);
183 O2 += (by * dy2);
184 O3 += (by * dy3);
185 const int32_t offs = by * stride;
186 buf += offs;
187 continue;
188 }
189 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
190 }
191 if (O3 < 0)
192 {
193 if (dx3 <= 0)
194 {
195 if (dy3 <= 0) return;
196 const int32_t by = (-O3 + dy3 - 1) / dy3;
197 O1 += (by * dy1);
198 O2 += (by * dy2);
199 O3 += (by * dy3);
200 const int32_t offs = by * stride;
201 buf += offs;
202 continue;
203 }
204 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
205 }
206
207 int32_t C2 = O2 + (dx2 * bx);
208 int32_t C3 = O3 + (dx3 * bx);
209 while ((bx < lx) && ((C2 | C3) >= 0))
210 {
211 buf[bx] = interpolateColorsTriangle(col2, C2 >> shiftC, col3, C3 >> shiftC, col1, aera >> shiftC);
212 C2 += dx2;
213 C3 += dx3;
214 bx++;
215 }
216
217 O1 += dy1;
218 O2 += dy2;
219 O3 += dy3;
220 buf += stride;
221 }
222 }
223
224
225
229 template<typename color_t, typename ZBUFFER_t, bool TEXTURE_BILINEAR, bool TEXTURE_WRAP>
230 void shader_Flat_Texture(const int32_t& offset, const int32_t& lx, const int32_t& ly,
231 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
232 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
233 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
234 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
235 {
236 color_t* buf = data.im->data() + offset;
237 const int32_t stride = data.im->stride();
238
239 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
240 const int32_t pa = O1 + O2 + O3;
241 const int32_t E = ((pa == 0) ? 1 : 0);
242 const int32_t aera = pa + E;
243
244
245 const float invaera = fast_inv((float)aera);
246 const float fP1a = fP1.w * invaera;
247 const float fP2a = fP2.w * invaera;
248 const float fP3a = fP3.w * invaera;
249
250 const float dw = (dx1 * fP1a) + (dx2 * fP2a) + (dx3 * fP3a);
251
252 const RGBf& cf = (RGBf)data.facecolor;
253 const int fPR = (int)(256 * cf.R);
254 const int fPG = (int)(256 * cf.G);
255 const int fPB = (int)(256 * cf.B);
256
257 // the texture coord
258 fVec2 T1 = fP1.T;
259 fVec2 T2 = fP2.T;
260 fVec2 T3 = fP3.T;
261
262 const color_t* tex = data.tex->data();
263 const int32_t texsize_x = data.tex->width();
264 const int32_t texsize_y = data.tex->height();
265 const int32_t texsize_x_mm = texsize_x - 1;
266 const int32_t texsize_y_mm = texsize_y - 1;
267 const int32_t texstride = data.tex->stride();
268
269 // divide the texture coord by z * aera
270 T1 *= fP1a;
271 T2 *= fP2a;
272 T3 *= fP3a;
273 T1.x *= texsize_x;
274 T2.x *= texsize_x;
275 T3.x *= texsize_x;
276 T1.y *= texsize_y;
277 T2.y *= texsize_y;
278 T3.y *= texsize_y;
279
280 const float dtx = ((T1.x * dx1) + (T2.x * dx2) + (T3.x * dx3));
281 const float dty = ((T1.y * dx1) + (T2.y * dx2) + (T3.y * dx3));
282
283 while ((uintptr_t)(buf) < end)
284 { // iterate over scanlines
285 int32_t bx = 0; // start offset
286 if (O1 < 0)
287 {
288 // we know that dx1 > 0
289 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
290 }
291 if (O2 < 0)
292 {
293 if (dx2 <= 0)
294 {
295 if (dy2 <= 0) return;
296 const int32_t by = (-O2 + dy2 - 1) / dy2;
297 O1 += (by * dy1);
298 O2 += (by * dy2);
299 O3 += (by * dy3);
300 const int32_t offs = by * stride;
301 buf += offs;
302 continue;
303 }
304 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
305 }
306 if (O3 < 0)
307 {
308 if (dx3 <= 0)
309 {
310 if (dy3 <= 0) return;
311 const int32_t by = (-O3 + dy3 - 1) / dy3;
312 O1 += (by * dy1);
313 O2 += (by * dy2);
314 O3 += (by * dy3);
315 const int32_t offs = by * stride;
316 buf += offs;
317 continue;
318 }
319 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
320 }
321
322 int32_t C1 = O1 + (dx1 * bx) + E;
323 int32_t C2 = O2 + (dx2 * bx);
324 int32_t C3 = O3 + (dx3 * bx);
325 float cw = ((C1 * fP1a) + (C2 * fP2a) + (C3 * fP3a));
326
327 float tx = ((T1.x * C1) + (T2.x * C2) + (T3.x * C3));
328 float ty = ((T1.y * C1) + (T2.y * C2) + (T3.y * C3));
329
330 while ((bx < lx) && ((C2 | C3) >= 0))
331 {
332 const float icw = fast_inv(cw);
333
334 color_t col;
335 if (TEXTURE_BILINEAR)
336 {
337 const float xx = tx * icw;
338 const float yy = ty * icw;
339 const int ttx = (int)floorf(xx);
340 const int tty = (int)floorf(yy);
341 const float ax = xx - ttx;
342 const float ay = yy - tty;
343 const int minx = (TEXTURE_WRAP ? (ttx & (texsize_x_mm)) : shaderclip(ttx, texsize_x_mm));
344 const int maxx = (TEXTURE_WRAP ? ((ttx + 1) & (texsize_x_mm)) : shaderclip(ttx + 1, texsize_x_mm));
345 const int miny = (TEXTURE_WRAP ? ((tty & (texsize_y_mm))*texstride) : shaderclip(tty, texsize_y_mm) * texstride);
346 const int maxy = (TEXTURE_WRAP ? (((tty + 1) & (texsize_y_mm))*texstride) : shaderclip(tty + 1, texsize_y_mm) * texstride);
347 col = interpolateColorsBilinear(tex[minx + miny], tex[maxx + miny], tex[minx + maxy], tex[maxx + maxy], ax, ay);
348 }
349 else
350 {
351 const int ttx = (TEXTURE_WRAP ? ((int)((tx * icw))) & (texsize_x_mm) : shaderclip((int)(tx * icw), texsize_x_mm));
352 const int tty = (TEXTURE_WRAP ? ((int)((ty * icw))) & (texsize_y_mm) : shaderclip((int)(ty * icw), texsize_y_mm));
353 col = tex[ttx + (tty)*texstride];
354 }
355
356 col.mult256(fPR, fPG, fPB);
357 buf[bx] = col;
358
359 C2 += dx2;
360 C3 += dx3;
361 cw += dw;
362
363 tx += dtx;
364 ty += dty;
365
366 bx++;
367 }
368
369 O1 += dy1;
370 O2 += dy2;
371 O3 += dy3;
372 buf += stride;
373 }
374 }
375
376
377
381 template<typename color_t, typename ZBUFFER_t, bool TEXTURE_BILINEAR, bool TEXTURE_WRAP>
382 void shader_Gouraud_Texture(const int32_t& offset, const int32_t& lx, const int32_t& ly,
383 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
384 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
385 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
386 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
387 {
388
389 color_t* buf = data.im->data() + offset;
390 const int32_t stride = data.im->stride();
391
392 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
393 const int32_t pa = O1 + O2 + O3;
394 const int32_t E = ((pa == 0) ? 1 : 0);
395 const int32_t aera = pa + E;
396
397 const float invaera = fast_inv((float)aera);
398 const float fP1a = fP1.w * invaera;
399 const float fP2a = fP2.w * invaera;
400 const float fP3a = fP3.w * invaera;
401
402 const float dw = (dx1 * fP1a) + (dx2 * fP2a) + (dx3 * fP3a);
403
404 const RGBf& cf1 = (RGBf)fP1.color;
405 const RGBf& cf2 = (RGBf)fP2.color;
406 const RGBf& cf3 = (RGBf)fP3.color;
407 const int fP1R = (int)(256 * cf1.R);
408 const int fP1G = (int)(256 * cf1.G);
409 const int fP1B = (int)(256 * cf1.B);
410 const int fP21R = (int)(256 * (cf2.R - cf1.R));
411 const int fP21G = (int)(256 * (cf2.G - cf1.G));
412 const int fP21B = (int)(256 * (cf2.B - cf1.B));
413 const int fP31R = (int)(256 * (cf3.R - cf1.R));
414 const int fP31G = (int)(256 * (cf3.G - cf1.G));
415 const int fP31B = (int)(256 * (cf3.B - cf1.B));
416
417 // the texture coord
418 fVec2 T1 = fP1.T;
419 fVec2 T2 = fP2.T;
420 fVec2 T3 = fP3.T;
421
422 const color_t* tex = data.tex->data();
423 const int32_t texsize_x = data.tex->width();
424 const int32_t texsize_y = data.tex->height();
425 const int32_t texsize_x_mm = texsize_x - 1;
426 const int32_t texsize_y_mm = texsize_y - 1;
427 const int32_t texstride = data.tex->stride();
428
429 // divide the texture coord by z * aera
430 T1 *= fP1a;
431 T2 *= fP2a;
432 T3 *= fP3a;
433 T1.x *= texsize_x;
434 T2.x *= texsize_x;
435 T3.x *= texsize_x;
436 T1.y *= texsize_y;
437 T2.y *= texsize_y;
438 T3.y *= texsize_y;
439
440
441 const float dtx = ((T1.x * dx1) + (T2.x * dx2) + (T3.x * dx3));
442 const float dty = ((T1.y * dx1) + (T2.y * dx2) + (T3.y * dx3));
443
444 while ((uintptr_t)(buf) < end)
445 { // iterate over scanlines
446 int32_t bx = 0; // start offset
447 if (O1 < 0)
448 {
449 // we know that dx1 > 0
450 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
451 }
452 if (O2 < 0)
453 {
454 if (dx2 <= 0)
455 {
456 if (dy2 <= 0) return;
457 const int32_t by = (-O2 + dy2 - 1) / dy2;
458 O1 += (by * dy1);
459 O2 += (by * dy2);
460 O3 += (by * dy3);
461 const int32_t offs = by * stride;
462 buf += offs;
463 continue;
464 }
465 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
466 }
467 if (O3 < 0)
468 {
469 if (dx3 <= 0)
470 {
471 if (dy3 <= 0) return;
472 const int32_t by = (-O3 + dy3 - 1) / dy3;
473 O1 += (by * dy1);
474 O2 += (by * dy2);
475 O3 += (by * dy3);
476 const int32_t offs = by * stride;
477 buf += offs;
478 continue;
479 }
480 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
481 }
482
483 int32_t C1 = O1 + (dx1 * bx) + E;
484 int32_t C2 = O2 + (dx2 * bx);
485 int32_t C3 = O3 + (dx3 * bx);
486 float cw = ((C1 * fP1a) + (C2 * fP2a) + (C3 * fP3a));
487
488 float tx = ((T1.x * C1) + (T2.x * C2) + (T3.x * C3));
489 float ty = ((T1.y * C1) + (T2.y * C2) + (T3.y * C3));
490
491 while ((bx < lx) && ((C2 | C3) >= 0))
492 {
493 const float icw = fast_inv(cw);
494
495 color_t col;
496 if (TEXTURE_BILINEAR)
497 {
498 const float xx = tx * icw;
499 const float yy = ty * icw;
500 const int ttx = (int)floorf(xx);
501 const int tty = (int)floorf(yy);
502 const float ax = xx - ttx;
503 const float ay = yy - tty;
504 const int minx = (TEXTURE_WRAP ? (ttx & (texsize_x_mm)) : shaderclip(ttx, texsize_x_mm));
505 const int maxx = (TEXTURE_WRAP ? ((ttx + 1) & (texsize_x_mm)) : shaderclip(ttx + 1, texsize_x_mm));
506 const int miny = (TEXTURE_WRAP ? ((tty & (texsize_y_mm)) * texstride) : shaderclip(tty, texsize_y_mm) * texstride);
507 const int maxy = (TEXTURE_WRAP ? (((tty + 1) & (texsize_y_mm)) * texstride) : shaderclip(tty + 1, texsize_y_mm) * texstride);
508 col = interpolateColorsBilinear(tex[minx + miny], tex[maxx + miny], tex[minx + maxy], tex[maxx + maxy], ax, ay);
509 }
510 else
511 {
512 const int ttx = (TEXTURE_WRAP ? ((int)((tx * icw))) & (texsize_x_mm) : shaderclip((int)(tx * icw), texsize_x_mm));
513 const int tty = (TEXTURE_WRAP ? ((int)((ty * icw))) & (texsize_y_mm) : shaderclip((int)(ty * icw), texsize_y_mm));
514 col = tex[ttx + (tty)*texstride];
515 }
516
517 const int r = fP1R + ((C2 * fP21R + C3 * fP31R) / aera);
518 const int g = fP1G + ((C2 * fP21G + C3 * fP31G) / aera);
519 const int b = fP1B + ((C2 * fP21B + C3 * fP31B) / aera);
520
521 col.mult256(r, g, b);
522 buf[bx] = col;
523
524 C2 += dx2;
525 C3 += dx3;
526 cw += dw;
527
528 tx += dtx;
529 ty += dty;
530
531 bx++;
532 }
533
534 O1 += dy1;
535 O2 += dy2;
536 O3 += dy3;
537 buf += stride;
538 }
539 }
540
541
542
546 template<typename color_t, typename ZBUFFER_t>
547 void shader_Flat_Zbuffer(const int32_t offset, const int32_t& lx, const int32_t& ly,
548 const int32_t& dx1, const int32_t& dy1, int32_t O1, const RasterizerVec4& fP1,
549 const int32_t& dx2, const int32_t& dy2, int32_t O2, const RasterizerVec4& fP2,
550 const int32_t& dx3, const int32_t& dy3, int32_t O3, const RasterizerVec4& fP3,
551 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
552 {
553 const color_t col = (color_t)data.facecolor;
554 color_t* buf = data.im->data() + offset;
555 ZBUFFER_t * zbuf = data.zbuf + offset;
556
557 const int32_t stride = data.im->stride();
558 const int32_t zstride = data.im->lx();
559
560 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
561 const int32_t pa = O1 + O2 + O3;
562 const int32_t E = ((pa == 0) ? 1 : 0);
563 const int32_t aera = pa + E;
564
565 const float wa = data.wa;
566 const float wb = data.wb;
567 const float invaera = fast_inv((float)aera);
568 const float invaera_wa = invaera * wa;
569 const float fP1a = fP1.w * invaera_wa;
570 const float fP2a = fP2.w * invaera_wa;
571 const float fP3a = fP3.w * invaera_wa;
572 const float dw = (dx1 * fP1a) + (dx2 * fP2a) + (dx3 * fP3a);
573
574 while ((uintptr_t)(buf) < end)
575 { // iterate over scanlines
576 int32_t bx = 0; // start offset
577 if (O1 < 0)
578 {
579 // we know that dx1 > 0
580 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
581 }
582 if (O2 < 0)
583 {
584 if (dx2 <= 0)
585 {
586 if (dy2 <= 0) return;
587 const int32_t by = (-O2 + dy2 - 1) / dy2;
588 O1 += (by * dy1);
589 O2 += (by * dy2);
590 O3 += (by * dy3);
591 const int32_t offs = by * stride;
592 buf += offs;
593 zbuf += offs;
594 continue;
595 }
596 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
597 }
598 if (O3 < 0)
599 {
600 if (dx3 <= 0)
601 {
602 if (dy3 <= 0) return;
603 const int32_t by = (-O3 + dy3 - 1) / dy3;
604 O1 += (by * dy1);
605 O2 += (by * dy2);
606 O3 += (by * dy3);
607 const int32_t offs = by * stride;
608 buf += offs;
609 zbuf += offs;
610 continue;
611 }
612 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
613 }
614
615 const int32_t C1 = O1 + (dx1 * bx) + E;
616 int32_t C2 = O2 + (dx2 * bx);
617 int32_t C3 = O3 + (dx3 * bx);
618 float cw = ((C1 * fP1a) + (C2 * fP2a) + (C3 * fP3a)) + wb;
619
620 while ((bx < lx) && ((C2 | C3) >= 0))
621 {
622 ZBUFFER_t& W = zbuf[bx];
623 const ZBUFFER_t aa = (ZBUFFER_t)(cw);
624 if (W < aa)
625 {
626 W = aa;
627 buf[bx] = col;
628 }
629 C2 += dx2;
630 C3 += dx3;
631 cw += dw;
632 bx++;
633 }
634
635 O1 += dy1;
636 O2 += dy2;
637 O3 += dy3;
638 buf += stride;
639 zbuf += zstride;
640 }
641 }
642
643
644
648 template<typename color_t, typename ZBUFFER_t, int shiftC>
649 void shader_Gouraud_Zbuffer_sub(const int32_t& offset, const int32_t& lx, const int32_t& ly,
650 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
651 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
652 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
653 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
654 {
655 color_t* buf = data.im->data() + offset;
656 ZBUFFER_t* zbuf = data.zbuf + offset;
657
658
659 const int32_t stride = data.im->stride();
660 const int32_t zstride = data.im->lx();
661
662 const color_t col1 = (color_t)fP1.color;
663 const color_t col2 = (color_t)fP2.color;
664 const color_t col3 = (color_t)fP3.color;
665
666 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
667 const int32_t pa = O1 + O2 + O3;
668 const int32_t E = ((pa == 0) ? 1 : 0);
669 const int32_t aera = pa + E;
670 const int32_t aeraShifted = aera >> shiftC;
671
672 const float wa = data.wa;
673 const float wb = data.wb;
674 const float invaera = fast_inv((float)aera);
675 const float invaera_wa = invaera * wa;
676 const float fP1a = fP1.w * invaera_wa;
677 const float fP2a = fP2.w * invaera_wa;
678 const float fP3a = fP3.w * invaera_wa;
679 const float dw = (dx1 * fP1a) + (dx2 * fP2a) + (dx3 * fP3a);
680
681 while ((uintptr_t)(buf) < end)
682 { // iterate over scanlines
683 int32_t bx = 0; // start offset
684 if (O1 < 0)
685 {
686 // we know that dx1 > 0
687 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
688 }
689 if (O2 < 0)
690 {
691 if (dx2 <= 0)
692 {
693 if (dy2 <= 0) return;
694 const int32_t by = (-O2 + dy2 - 1) / dy2;
695 O1 += (by * dy1);
696 O2 += (by * dy2);
697 O3 += (by * dy3);
698 const int32_t offs = by * stride;
699 buf += offs;
700 zbuf += offs;
701 continue;
702 }
703 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
704 }
705 if (O3 < 0)
706 {
707 if (dx3 <= 0)
708 {
709 if (dy3 <= 0) return;
710 const int32_t by = (-O3 + dy3 - 1) / dy3;
711 O1 += (by * dy1);
712 O2 += (by * dy2);
713 O3 += (by * dy3);
714 const int32_t offs = by * stride;
715 buf += offs;
716 zbuf += offs;
717 continue;
718 }
719 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
720 }
721
722 const int32_t C1 = O1 + (dx1 * bx) + E;
723 int32_t C2 = O2 + (dx2 * bx);
724 int32_t C3 = O3 + (dx3 * bx);
725 float cw = ((C1 * fP1a) + (C2 * fP2a) + (C3 * fP3a)) + wb;
726
727 while ((bx < lx) && ((C2 | C3) >= 0))
728 {
729 ZBUFFER_t& W = zbuf[bx];
730 const ZBUFFER_t aa = (ZBUFFER_t)(cw);
731 if (W < aa)
732 {
733 W = aa;
734 buf[bx] = interpolateColorsTriangle(col2, C2 >> shiftC, col3, C3 >> shiftC , col1, aeraShifted);
735 }
736 C2 += dx2;
737 C3 += dx3;
738 cw += dw;
739 bx++;
740 }
741
742 O1 += dy1;
743 O2 += dy2;
744 O3 += dy3;
745 buf += stride;
746 zbuf += zstride;
747 }
748 }
749
753 template<typename color_t, typename ZBUFFER_t>
754 void shader_Gouraud_Zbuffer(const int32_t& offset, const int32_t& lx, const int32_t& ly,
755 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
756 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
757 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
758 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
759
760 {
761 if (O1 + O2 + O3 > (1 << 24))
762 { // large aera, use interpolateColorsTriangle<true>
763 shader_Gouraud_Zbuffer_sub<color_t, ZBUFFER_t, 10>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
764 }
765 else
766 { // small aera, use interpolateColorsTriangle<false>
767 shader_Gouraud_Zbuffer_sub<color_t, ZBUFFER_t, 0>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
768 }
769 }
770
771
772
776 template<typename color_t, typename ZBUFFER_t, bool TEXTURE_BILINEAR, bool TEXTURE_WRAP>
777 void shader_Flat_Texture_Zbuffer(const int32_t& offset, const int32_t& lx, const int32_t& ly,
778 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
779 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
780 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
781 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
782 {
783 color_t* buf = data.im->data() + offset;
784 ZBUFFER_t* zbuf = data.zbuf + offset;
785
786 const float wa = data.wa;
787 const float wb = data.wb;
788 (void)wa; // silence possible unused warnings
789 (void)wb; //
790
791
792 const int32_t stride = data.im->stride();
793 const int32_t zstride = data.im->lx();
794
795 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
796 const int32_t pa = O1 + O2 + O3;
797 const int32_t E = ((pa == 0) ? 1 : 0);
798 const int32_t aera = pa + E;
799
800 const float invaera = fast_inv((float)aera);
801 const float fP1a = fP1.w * invaera;
802 const float fP2a = fP2.w * invaera;
803 const float fP3a = fP3.w * invaera;
804
805 const float dw = (dx1 * fP1a) + (dx2 * fP2a) + (dx3 * fP3a);
806
807 const RGBf& cf = (RGBf)data.facecolor;
808 const int fPR = (int)(256 * cf.R);
809 const int fPG = (int)(256 * cf.G);
810 const int fPB = (int)(256 * cf.B);
811
812 // the texture coord
813 fVec2 T1 = fP1.T;
814 fVec2 T2 = fP2.T;
815 fVec2 T3 = fP3.T;
816
817 const color_t* tex = data.tex->data();
818 const int32_t texsize_x = data.tex->width();
819 const int32_t texsize_y = data.tex->height();
820 const int32_t texsize_x_mm = texsize_x - 1;
821 const int32_t texsize_y_mm = texsize_y - 1;
822 const int32_t texstride = data.tex->stride();
823
824 // divide the texture coord by z * aera
825 T1 *= fP1a;
826 T2 *= fP2a;
827 T3 *= fP3a;
828 T1.x *= texsize_x;
829 T2.x *= texsize_x;
830 T3.x *= texsize_x;
831 T1.y *= texsize_y;
832 T2.y *= texsize_y;
833 T3.y *= texsize_y;
834
835 const float dtx = ((T1.x * dx1) + (T2.x * dx2) + (T3.x * dx3));
836 const float dty = ((T1.y * dx1) + (T2.y * dx2) + (T3.y * dx3));
837
838 while ((uintptr_t)(buf) < end)
839 { // iterate over scanlines
840 int32_t bx = 0; // start offset
841 if (O1 < 0)
842 {
843 // we know that dx1 > 0
844 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
845 }
846 if (O2 < 0)
847 {
848 if (dx2 <= 0)
849 {
850 if (dy2 <= 0) return;
851 const int32_t by = (-O2 + dy2 - 1) / dy2;
852 O1 += (by * dy1);
853 O2 += (by * dy2);
854 O3 += (by * dy3);
855 const int32_t offs = by * stride;
856 buf += offs;
857 zbuf += offs;
858 continue;
859 }
860 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
861 }
862 if (O3 < 0)
863 {
864 if (dx3 <= 0)
865 {
866 if (dy3 <= 0) return;
867 const int32_t by = (-O3 + dy3 - 1) / dy3;
868 O1 += (by * dy1);
869 O2 += (by * dy2);
870 O3 += (by * dy3);
871 const int32_t offs = by * stride;
872 buf += offs;
873 zbuf += offs;
874 continue;
875 }
876 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
877 }
878
879 int32_t C1 = O1 + (dx1 * bx) + E;
880 int32_t C2 = O2 + (dx2 * bx);
881 int32_t C3 = O3 + (dx3 * bx);
882 float cw = ((C1 * fP1a) + (C2 * fP2a) + (C3 * fP3a));
883
884 float tx = ((T1.x * C1) + (T2.x * C2) + (T3.x * C3));
885 float ty = ((T1.y * C1) + (T2.y * C2) + (T3.y * C3));
886
887 while ((bx < lx) && ((C2 | C3) >= 0))
888 {
889 ZBUFFER_t& W = zbuf[bx];
890 const ZBUFFER_t aa = (std::is_same<ZBUFFER_t, uint16_t>::value) ? ((ZBUFFER_t)(cw * wa + wb)) : ((ZBUFFER_t)cw);
891 if (W < aa)
892 {
893 W = aa;
894 const float icw = fast_inv(cw);
895 color_t col;
896 if (TEXTURE_BILINEAR)
897 {
898 const float xx = tx * icw;
899 const float yy = ty * icw;
900 const int ttx = (int)floorf(xx);
901 const int tty = (int)floorf(yy);
902 const float ax = xx - ttx;
903 const float ay = yy - tty;
904 const int minx = (TEXTURE_WRAP ? (ttx & (texsize_x_mm)) : shaderclip(ttx, texsize_x_mm));
905 const int maxx = (TEXTURE_WRAP ? ((ttx + 1) & (texsize_x_mm)) : shaderclip(ttx + 1, texsize_x_mm));
906 const int miny = (TEXTURE_WRAP ? ((tty & (texsize_y_mm)) * texstride) : shaderclip(tty, texsize_y_mm) * texstride);
907 const int maxy = (TEXTURE_WRAP ? (((tty + 1) & (texsize_y_mm)) * texstride) : shaderclip(tty + 1, texsize_y_mm) * texstride);
908 col = interpolateColorsBilinear(tex[minx + miny], tex[maxx + miny], tex[minx + maxy], tex[maxx + maxy], ax, ay);
909 }
910 else
911 {
912 const int ttx = (TEXTURE_WRAP ? ((int)((tx * icw))) & (texsize_x_mm) : shaderclip((int)(tx * icw), texsize_x_mm));
913 const int tty = (TEXTURE_WRAP ? ((int)((ty * icw))) & (texsize_y_mm) : shaderclip((int)(ty * icw), texsize_y_mm));
914 col = tex[ttx + (tty)*texstride];
915 }
916
917 col.mult256(fPR, fPG, fPB);
918 buf[bx] = col;
919 }
920
921 C2 += dx2;
922 C3 += dx3;
923 cw += dw;
924
925 tx += dtx;
926 ty += dty;
927
928 bx++;
929 }
930
931 O1 += dy1;
932 O2 += dy2;
933 O3 += dy3;
934 buf += stride;
935 zbuf += zstride;
936 }
937 }
938
939
940
944 template<typename color_t, typename ZBUFFER_t, bool TEXTURE_BILINEAR, bool TEXTURE_WRAP>
945 void shader_Gouraud_Texture_Zbuffer(const int32_t& offset, const int32_t& lx, const int32_t& ly,
946 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
947 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
948 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
949 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
950 {
951 color_t* buf = data.im->data() + offset;
952 ZBUFFER_t* zbuf = data.zbuf + offset;
953
954 const float wa = data.wa;
955 const float wb = data.wb;
956 (void)wa; // silence possible unused warnings
957 (void)wb; //
958
959 const int32_t stride = data.im->stride();
960 const int32_t zstride = data.im->lx();
961
962 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
963 const int32_t pa = O1 + O2 + O3;
964 const int32_t E = ((pa == 0) ? 1 : 0);
965 const int32_t aera = pa + E;
966
967 const float invaera = fast_inv((float)aera);
968 const float fP1a = fP1.w * invaera;
969 const float fP2a = fP2.w * invaera;
970 const float fP3a = fP3.w * invaera;
971
972 const float dw = (dx1 * fP1a) + (dx2 * fP2a) + (dx3 * fP3a);
973
974 const RGBf& cf1 = (RGBf)fP1.color;
975 const RGBf& cf2 = (RGBf)fP2.color;
976 const RGBf& cf3 = (RGBf)fP3.color;
977 const int fP1R = (int)(256 * cf1.R);
978 const int fP1G = (int)(256 * cf1.G);
979 const int fP1B = (int)(256 * cf1.B);
980 const int fP21R = (int)(256 * (cf2.R - cf1.R));
981 const int fP21G = (int)(256 * (cf2.G - cf1.G));
982 const int fP21B = (int)(256 * (cf2.B - cf1.B));
983 const int fP31R = (int)(256 * (cf3.R - cf1.R));
984 const int fP31G = (int)(256 * (cf3.G - cf1.G));
985 const int fP31B = (int)(256 * (cf3.B - cf1.B));
986
987 // the texture coord
988 fVec2 T1 = fP1.T;
989 fVec2 T2 = fP2.T;
990 fVec2 T3 = fP3.T;
991
992 const color_t* tex = data.tex->data();
993 const int32_t texsize_x = data.tex->width();
994 const int32_t texsize_y = data.tex->height();
995 const int32_t texsize_x_mm = texsize_x - 1;
996 const int32_t texsize_y_mm = texsize_y - 1;
997 const int32_t texstride = data.tex->stride();
998
999 // divide the texture coord by z * aera
1000 T1 *= fP1a;
1001 T2 *= fP2a;
1002 T3 *= fP3a;
1003 T1.x *= texsize_x;
1004 T2.x *= texsize_x;
1005 T3.x *= texsize_x;
1006 T1.y *= texsize_y;
1007 T2.y *= texsize_y;
1008 T3.y *= texsize_y;
1009
1010 const float dtx = ((T1.x * dx1) + (T2.x * dx2) + (T3.x * dx3));
1011 const float dty = ((T1.y * dx1) + (T2.y * dx2) + (T3.y * dx3));
1012
1013 while ((uintptr_t)(buf) < end)
1014 { // iterate over scanlines
1015 int32_t bx = 0; // start offset
1016 if (O1 < 0)
1017 {
1018 // we know that dx1 > 0
1019 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
1020 }
1021 if (O2 < 0)
1022 {
1023 if (dx2 <= 0)
1024 {
1025 if (dy2 <= 0) return;
1026 const int32_t by = (-O2 + dy2 - 1) / dy2;
1027 O1 += (by * dy1);
1028 O2 += (by * dy2);
1029 O3 += (by * dy3);
1030 const int32_t offs = by * stride;
1031 buf += offs;
1032 zbuf += offs;
1033 continue;
1034 }
1035 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
1036 }
1037 if (O3 < 0)
1038 {
1039 if (dx3 <= 0)
1040 {
1041 if (dy3 <= 0) return;
1042 const int32_t by = (-O3 + dy3 - 1) / dy3;
1043 O1 += (by * dy1);
1044 O2 += (by * dy2);
1045 O3 += (by * dy3);
1046 const int32_t offs = by * stride;
1047 buf += offs;
1048 zbuf += offs;
1049 continue;
1050 }
1051 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
1052 }
1053 int32_t C1 = O1 + (dx1 * bx) + E;
1054 int32_t C2 = O2 + (dx2 * bx);
1055 int32_t C3 = O3 + (dx3 * bx);
1056 float cw = ((C1 * fP1a) + (C2 * fP2a) + (C3 * fP3a));
1057
1058 float tx = ((T1.x * C1) + (T2.x * C2) + (T3.x * C3));
1059 float ty = ((T1.y * C1) + (T2.y * C2) + (T3.y * C3));
1060
1061 while ((bx < lx) && ((C2 | C3) >= 0))
1062 {
1063 ZBUFFER_t& W = zbuf[bx];
1064 const ZBUFFER_t aa = (std::is_same<ZBUFFER_t, uint16_t>::value) ? ((ZBUFFER_t)(cw * wa + wb)) : ((ZBUFFER_t)cw);
1065 if (W < aa)
1066 {
1067 W = aa;
1068 const float icw = fast_inv(cw);
1069
1070 color_t col;
1071 if (TEXTURE_BILINEAR)
1072 {
1073 const float xx = tx * icw;
1074 const float yy = ty * icw;
1075 const int ttx = (int)floorf(xx);
1076 const int tty = (int)floorf(yy);
1077 const float ax = xx - ttx;
1078 const float ay = yy - tty;
1079 const int minx = (TEXTURE_WRAP ? (ttx & (texsize_x_mm)) : shaderclip(ttx, texsize_x_mm));
1080 const int maxx = (TEXTURE_WRAP ? ((ttx + 1) & (texsize_x_mm)) : shaderclip(ttx + 1, texsize_x_mm));
1081 const int miny = (TEXTURE_WRAP ? ((tty & (texsize_y_mm)) * texstride) : shaderclip(tty, texsize_y_mm) * texstride);
1082 const int maxy = (TEXTURE_WRAP ? (((tty + 1) & (texsize_y_mm)) * texstride) : shaderclip(tty + 1, texsize_y_mm) * texstride);
1083 col = interpolateColorsBilinear(tex[minx + miny], tex[maxx + miny], tex[minx + maxy], tex[maxx + maxy], ax, ay);
1084 }
1085 else
1086 {
1087 const int ttx = (TEXTURE_WRAP ? ((int)((tx * icw))) & (texsize_x_mm) : shaderclip((int)(tx * icw), texsize_x_mm));
1088 const int tty = (TEXTURE_WRAP ? ((int)((ty * icw))) & (texsize_y_mm) : shaderclip((int)(ty * icw), texsize_y_mm));
1089 col = tex[ttx + (tty)*texstride];
1090 }
1091
1092 const int r = fP1R + ((C2 * fP21R + C3 * fP31R) / aera);
1093 const int g = fP1G + ((C2 * fP21G + C3 * fP31G) / aera);
1094 const int b = fP1B + ((C2 * fP21B + C3 * fP31B) / aera);
1095 col.mult256(r, g, b);
1096 buf[bx] = col;
1097 }
1098
1099 C2 += dx2;
1100 C3 += dx3;
1101 cw += dw;
1102
1103 tx += dtx;
1104 ty += dty;
1105
1106 bx++;
1107 }
1108
1109 O1 += dy1;
1110 O2 += dy2;
1111 O3 += dy3;
1112 buf += stride;
1113 zbuf += zstride;
1114 }
1115 }
1116
1117
1118
1122 template<typename color_t, typename ZBUFFER_t, bool TEXTURE_BILINEAR, bool TEXTURE_WRAP>
1123 void shader_Flat_Texture_Ortho(const int32_t& offset, const int32_t& lx, const int32_t& ly,
1124 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
1125 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
1126 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
1127 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
1128 {
1129 color_t* buf = data.im->data() + offset;
1130 const int32_t stride = data.im->stride();
1131
1132 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
1133 const int32_t pa = O1 + O2 + O3;
1134 const int32_t E = ((pa == 0) ? 1 : 0);
1135 const int32_t aera = pa + E;
1136
1137 const float invaera = fast_inv((float)aera);
1138
1139 const RGBf& cf = (RGBf)data.facecolor;
1140 const int fPR = (int)(256 * cf.R);
1141 const int fPG = (int)(256 * cf.G);
1142 const int fPB = (int)(256 * cf.B);
1143
1144 // the texture coord
1145 fVec2 T1 = fP1.T;
1146 fVec2 T2 = fP2.T;
1147 fVec2 T3 = fP3.T;
1148
1149 const color_t* tex = data.tex->data();
1150 const int32_t texsize_x = data.tex->width();
1151 const int32_t texsize_y = data.tex->height();
1152 const int32_t texsize_x_mm = texsize_x - 1;
1153 const int32_t texsize_y_mm = texsize_y - 1;
1154 const int32_t texstride = data.tex->stride();
1155
1156 // divide the texture coord by aera
1157 T1 *= invaera;
1158 T2 *= invaera;
1159 T3 *= invaera;
1160 T1.x *= texsize_x;
1161 T2.x *= texsize_x;
1162 T3.x *= texsize_x;
1163 T1.y *= texsize_y;
1164 T2.y *= texsize_y;
1165 T3.y *= texsize_y;
1166
1167 const float dtx = ((T1.x * dx1) + (T2.x * dx2) + (T3.x * dx3));
1168 const float dty = ((T1.y * dx1) + (T2.y * dx2) + (T3.y * dx3));
1169
1170 while ((uintptr_t)(buf) < end)
1171 { // iterate over scanlines
1172 int32_t bx = 0; // start offset
1173 if (O1 < 0)
1174 {
1175 // we know that dx1 > 0
1176 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
1177 }
1178 if (O2 < 0)
1179 {
1180 if (dx2 <= 0)
1181 {
1182 if (dy2 <= 0) return;
1183 const int32_t by = (-O2 + dy2 - 1) / dy2;
1184 O1 += (by * dy1);
1185 O2 += (by * dy2);
1186 O3 += (by * dy3);
1187 const int32_t offs = by * stride;
1188 buf += offs;
1189 continue;
1190 }
1191 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
1192 }
1193 if (O3 < 0)
1194 {
1195 if (dx3 <= 0)
1196 {
1197 if (dy3 <= 0) return;
1198 const int32_t by = (-O3 + dy3 - 1) / dy3;
1199 O1 += (by * dy1);
1200 O2 += (by * dy2);
1201 O3 += (by * dy3);
1202 const int32_t offs = by * stride;
1203 buf += offs;
1204 continue;
1205 }
1206 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
1207 }
1208 int32_t C1 = O1 + (dx1 * bx) + E;
1209 int32_t C2 = O2 + (dx2 * bx);
1210 int32_t C3 = O3 + (dx3 * bx);
1211
1212 float tx = ((T1.x * C1) + (T2.x * C2) + (T3.x * C3));
1213 float ty = ((T1.y * C1) + (T2.y * C2) + (T3.y * C3));
1214
1215 while ((bx < lx) && ((C2 | C3) >= 0))
1216 {
1217
1218 color_t col;
1219 if (TEXTURE_BILINEAR)
1220 {
1221 const float xx = tx;
1222 const float yy = ty;
1223 const int ttx = (int)floorf(xx);
1224 const int tty = (int)floorf(yy);
1225 const float ax = xx - ttx;
1226 const float ay = yy - tty;
1227 const int minx = (TEXTURE_WRAP ? (ttx & (texsize_x_mm)) : shaderclip(ttx, texsize_x_mm));
1228 const int maxx = (TEXTURE_WRAP ? ((ttx + 1) & (texsize_x_mm)) : shaderclip(ttx + 1, texsize_x_mm));
1229 const int miny = (TEXTURE_WRAP ? ((tty & (texsize_y_mm)) * texstride) : shaderclip(tty, texsize_y_mm) * texstride);
1230 const int maxy = (TEXTURE_WRAP ? (((tty + 1) & (texsize_y_mm)) * texstride) : shaderclip(tty + 1, texsize_y_mm) * texstride);
1231 col = interpolateColorsBilinear(tex[minx + miny], tex[maxx + miny], tex[minx + maxy], tex[maxx + maxy], ax, ay);
1232 }
1233 else
1234 {
1235 const int ttx = (TEXTURE_WRAP ? ((int)((tx))) & (texsize_x_mm) : shaderclip((int)(tx), texsize_x_mm));
1236 const int tty = (TEXTURE_WRAP ? ((int)((ty))) & (texsize_y_mm) : shaderclip((int)(ty), texsize_y_mm));
1237 col = tex[ttx + (tty)*texstride];
1238 }
1239
1240 col.mult256(fPR, fPG, fPB);
1241 buf[bx] = col;
1242
1243 C2 += dx2;
1244 C3 += dx3;
1245
1246 tx += dtx;
1247 ty += dty;
1248
1249 bx++;
1250 }
1251
1252 O1 += dy1;
1253 O2 += dy2;
1254 O3 += dy3;
1255 buf += stride;
1256 }
1257 }
1258
1259
1260
1264 template<typename color_t, typename ZBUFFER_t, bool TEXTURE_BILINEAR, bool TEXTURE_WRAP>
1265 void shader_Gouraud_Texture_Ortho(const int32_t& offset, const int32_t& lx, const int32_t& ly,
1266 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
1267 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
1268 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
1269 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
1270 {
1271 color_t* buf = data.im->data() + offset;
1272 const int32_t stride = data.im->stride();
1273
1274 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
1275 const int32_t pa = O1 + O2 + O3;
1276 const int32_t E = ((pa == 0) ? 1 : 0);
1277 const int32_t aera = pa + E;
1278
1279 const float invaera = fast_inv((float)aera);
1280
1281 const RGBf& cf1 = (RGBf)fP1.color;
1282 const RGBf& cf2 = (RGBf)fP2.color;
1283 const RGBf& cf3 = (RGBf)fP3.color;
1284 const int fP1R = (int)(256 * cf1.R);
1285 const int fP1G = (int)(256 * cf1.G);
1286 const int fP1B = (int)(256 * cf1.B);
1287 const int fP21R = (int)(256 * (cf2.R - cf1.R));
1288 const int fP21G = (int)(256 * (cf2.G - cf1.G));
1289 const int fP21B = (int)(256 * (cf2.B - cf1.B));
1290 const int fP31R = (int)(256 * (cf3.R - cf1.R));
1291 const int fP31G = (int)(256 * (cf3.G - cf1.G));
1292 const int fP31B = (int)(256 * (cf3.B - cf1.B));
1293
1294 // the texture coord
1295 fVec2 T1 = fP1.T;
1296 fVec2 T2 = fP2.T;
1297 fVec2 T3 = fP3.T;
1298
1299 const color_t* tex = data.tex->data();
1300 const int32_t texsize_x = data.tex->width();
1301 const int32_t texsize_y = data.tex->height();
1302 const int32_t texsize_x_mm = texsize_x - 1;
1303 const int32_t texsize_y_mm = texsize_y - 1;
1304 const int32_t texstride = data.tex->stride();
1305
1306 // divide the texture coord by aera
1307 T1 *= invaera;
1308 T2 *= invaera;
1309 T3 *= invaera;
1310 T1.x *= texsize_x;
1311 T2.x *= texsize_x;
1312 T3.x *= texsize_x;
1313 T1.y *= texsize_y;
1314 T2.y *= texsize_y;
1315 T3.y *= texsize_y;
1316
1317 const float dtx = ((T1.x * dx1) + (T2.x * dx2) + (T3.x * dx3));
1318 const float dty = ((T1.y * dx1) + (T2.y * dx2) + (T3.y * dx3));
1319
1320 while ((uintptr_t)(buf) < end)
1321 { // iterate over scanlines
1322 int32_t bx = 0; // start offset
1323 if (O1 < 0)
1324 {
1325 // we know that dx1 > 0
1326 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
1327 }
1328 if (O2 < 0)
1329 {
1330 if (dx2 <= 0)
1331 {
1332 if (dy2 <= 0) return;
1333 const int32_t by = (-O2 + dy2 - 1) / dy2;
1334 O1 += (by * dy1);
1335 O2 += (by * dy2);
1336 O3 += (by * dy3);
1337 const int32_t offs = by * stride;
1338 buf += offs;
1339 continue;
1340 }
1341 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
1342 }
1343 if (O3 < 0)
1344 {
1345 if (dx3 <= 0)
1346 {
1347 if (dy3 <= 0) return;
1348 const int32_t by = (-O3 + dy3 - 1) / dy3;
1349 O1 += (by * dy1);
1350 O2 += (by * dy2);
1351 O3 += (by * dy3);
1352 const int32_t offs = by * stride;
1353 buf += offs;
1354 continue;
1355 }
1356 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
1357 }
1358
1359 int32_t C1 = O1 + (dx1 * bx) + E;
1360 int32_t C2 = O2 + (dx2 * bx);
1361 int32_t C3 = O3 + (dx3 * bx);
1362
1363 float tx = ((T1.x * C1) + (T2.x * C2) + (T3.x * C3));
1364 float ty = ((T1.y * C1) + (T2.y * C2) + (T3.y * C3));
1365
1366 while ((bx < lx) && ((C2 | C3) >= 0))
1367 {
1368
1369 color_t col;
1370 if (TEXTURE_BILINEAR)
1371 {
1372 const float xx = tx;
1373 const float yy = ty;
1374 const int ttx = (int)floorf(xx);
1375 const int tty = (int)floorf(yy);
1376 const float ax = xx - ttx;
1377 const float ay = yy - tty;
1378 const int minx = (TEXTURE_WRAP ? (ttx & (texsize_x_mm)) : shaderclip(ttx, texsize_x_mm));
1379 const int maxx = (TEXTURE_WRAP ? ((ttx + 1) & (texsize_x_mm)) : shaderclip(ttx + 1, texsize_x_mm));
1380 const int miny = (TEXTURE_WRAP ? ((tty & (texsize_y_mm)) * texstride) : shaderclip(tty, texsize_y_mm) * texstride);
1381 const int maxy = (TEXTURE_WRAP ? (((tty + 1) & (texsize_y_mm)) * texstride) : shaderclip(tty + 1, texsize_y_mm) * texstride);
1382 col = interpolateColorsBilinear(tex[minx + miny], tex[maxx + miny], tex[minx + maxy], tex[maxx + maxy], ax, ay);
1383 }
1384 else
1385 {
1386 const int ttx = (TEXTURE_WRAP ? ((int)((tx))) & (texsize_x_mm) : shaderclip((int)(tx), texsize_x_mm));
1387 const int tty = (TEXTURE_WRAP ? ((int)((ty))) & (texsize_y_mm) : shaderclip((int)(ty), texsize_y_mm));
1388 col = tex[ttx + (tty)*texstride];
1389 }
1390
1391 const int r = fP1R + ((C2 * fP21R + C3 * fP31R) / aera);
1392 const int g = fP1G + ((C2 * fP21G + C3 * fP31G) / aera);
1393 const int b = fP1B + ((C2 * fP21B + C3 * fP31B) / aera);
1394 col.mult256(r, g, b);
1395 buf[bx] = col;
1396
1397 C2 += dx2;
1398 C3 += dx3;
1399
1400 tx += dtx;
1401 ty += dty;
1402
1403 bx++;
1404 }
1405
1406 O1 += dy1;
1407 O2 += dy2;
1408 O3 += dy3;
1409 buf += stride;
1410 }
1411 }
1412
1413
1414
1418 template<typename color_t, typename ZBUFFER_t, bool TEXTURE_BILINEAR, bool TEXTURE_WRAP>
1419 void shader_Flat_Texture_Zbuffer_Ortho(const int32_t& offset, const int32_t& lx, const int32_t& ly,
1420 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
1421 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
1422 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
1423 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
1424 {
1425 color_t* buf = data.im->data() + offset;
1426 ZBUFFER_t* zbuf = data.zbuf + offset;
1427
1428 const float wa = data.wa;
1429 const float wb = data.wb;
1430 (void)wa; // silence possible unused warnings
1431 (void)wb; //
1432
1433 const int32_t stride = data.im->stride();
1434 const int32_t zstride = data.im->lx();
1435
1436 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
1437 const int32_t pa = O1 + O2 + O3;
1438 const int32_t E = ((pa == 0) ? 1 : 0);
1439 const int32_t aera = pa + E;
1440
1441 const float invaera = fast_inv((float)aera);
1442 const float fP1a = fP1.w * invaera;
1443 const float fP2a = fP2.w * invaera;
1444 const float fP3a = fP3.w * invaera;
1445
1446 const float dw = (dx1 * fP1a) + (dx2 * fP2a) + (dx3 * fP3a);
1447
1448 const RGBf& cf = (RGBf)data.facecolor;
1449 const int fPR = (int)(256 * cf.R);
1450 const int fPG = (int)(256 * cf.G);
1451 const int fPB = (int)(256 * cf.B);
1452
1453 // the texture coord
1454 fVec2 T1 = fP1.T;
1455 fVec2 T2 = fP2.T;
1456 fVec2 T3 = fP3.T;
1457
1458 const color_t* tex = data.tex->data();
1459 const int32_t texsize_x = data.tex->width();
1460 const int32_t texsize_y = data.tex->height();
1461 const int32_t texsize_x_mm = texsize_x - 1;
1462 const int32_t texsize_y_mm = texsize_y - 1;
1463 const int32_t texstride = data.tex->stride();
1464
1465 // divide the texture coord by aera
1466 T1 *= invaera;
1467 T2 *= invaera;
1468 T3 *= invaera;
1469 T1.x *= texsize_x;
1470 T2.x *= texsize_x;
1471 T3.x *= texsize_x;
1472 T1.y *= texsize_y;
1473 T2.y *= texsize_y;
1474 T3.y *= texsize_y;
1475
1476 const float dtx = ((T1.x * dx1) + (T2.x * dx2) + (T3.x * dx3));
1477 const float dty = ((T1.y * dx1) + (T2.y * dx2) + (T3.y * dx3));
1478
1479 while ((uintptr_t)(buf) < end)
1480 { // iterate over scanlines
1481 int32_t bx = 0; // start offset
1482 if (O1 < 0)
1483 {
1484 // we know that dx1 > 0
1485 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
1486 }
1487 if (O2 < 0)
1488 {
1489 if (dx2 <= 0)
1490 {
1491 if (dy2 <= 0) return;
1492 const int32_t by = (-O2 + dy2 - 1) / dy2;
1493 O1 += (by * dy1);
1494 O2 += (by * dy2);
1495 O3 += (by * dy3);
1496 const int32_t offs = by * stride;
1497 buf += offs;
1498 zbuf += offs;
1499 continue;
1500 }
1501 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
1502 }
1503 if (O3 < 0)
1504 {
1505 if (dx3 <= 0)
1506 {
1507 if (dy3 <= 0) return;
1508 const int32_t by = (-O3 + dy3 - 1) / dy3;
1509 O1 += (by * dy1);
1510 O2 += (by * dy2);
1511 O3 += (by * dy3);
1512 const int32_t offs = by * stride;
1513 buf += offs;
1514 zbuf += offs;
1515 continue;
1516 }
1517 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
1518 }
1519
1520 int32_t C1 = O1 + (dx1 * bx) + E;
1521 int32_t C2 = O2 + (dx2 * bx);
1522 int32_t C3 = O3 + (dx3 * bx);
1523 float cw = ((C1 * fP1a) + (C2 * fP2a) + (C3 * fP3a));
1524
1525 float tx = ((T1.x * C1) + (T2.x * C2) + (T3.x * C3));
1526 float ty = ((T1.y * C1) + (T2.y * C2) + (T3.y * C3));
1527
1528 while ((bx < lx) && ((C2 | C3) >= 0))
1529 {
1530 ZBUFFER_t& W = zbuf[bx];
1531 const ZBUFFER_t aa = (std::is_same<ZBUFFER_t, uint16_t>::value) ? ((ZBUFFER_t)(cw * wa + wb)) : ((ZBUFFER_t)cw);
1532 if (W < aa)
1533 {
1534 W = aa;
1535
1536 color_t col;
1537 if (TEXTURE_BILINEAR)
1538 {
1539 const float xx = tx;
1540 const float yy = ty;
1541 const int ttx = (int)floorf(xx);
1542 const int tty = (int)floorf(yy);
1543 const float ax = xx - ttx;
1544 const float ay = yy - tty;
1545 const int minx = (TEXTURE_WRAP ? (ttx & (texsize_x_mm)) : shaderclip(ttx, texsize_x_mm));
1546 const int maxx = (TEXTURE_WRAP ? ((ttx + 1) & (texsize_x_mm)) : shaderclip(ttx + 1, texsize_x_mm));
1547 const int miny = (TEXTURE_WRAP ? ((tty & (texsize_y_mm)) * texstride) : shaderclip(tty, texsize_y_mm) * texstride);
1548 const int maxy = (TEXTURE_WRAP ? (((tty + 1) & (texsize_y_mm)) * texstride) : shaderclip(tty + 1, texsize_y_mm) * texstride);
1549 col = interpolateColorsBilinear(tex[minx + miny], tex[maxx + miny], tex[minx + maxy], tex[maxx + maxy], ax, ay);
1550 }
1551 else
1552 {
1553 const int ttx = (TEXTURE_WRAP ? ((int)((tx))) & (texsize_x_mm) : shaderclip((int)(tx), texsize_x_mm));
1554 const int tty = (TEXTURE_WRAP ? ((int)((ty))) & (texsize_y_mm) : shaderclip((int)(ty), texsize_y_mm));
1555 col = tex[ttx + (tty)*texstride];
1556 }
1557
1558 col.mult256(fPR, fPG, fPB);
1559 buf[bx] = col;
1560 }
1561
1562 C2 += dx2;
1563 C3 += dx3;
1564 cw += dw;
1565
1566 tx += dtx;
1567 ty += dty;
1568
1569 bx++;
1570 }
1571
1572 O1 += dy1;
1573 O2 += dy2;
1574 O3 += dy3;
1575 buf += stride;
1576 zbuf += zstride;
1577 }
1578 }
1579
1580
1581
1585 template<typename color_t, typename ZBUFFER_t, bool TEXTURE_BILINEAR, bool TEXTURE_WRAP>
1586 void shader_Gouraud_Texture_Zbuffer_Ortho(const int32_t& offset, const int32_t& lx, const int32_t& ly,
1587 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
1588 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
1589 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
1590 const RasterizerParams<color_t, color_t, ZBUFFER_t>& data)
1591 {
1592 color_t* buf = data.im->data() + offset;
1593 ZBUFFER_t* zbuf = data.zbuf + offset;
1594
1595 const float wa = data.wa;
1596 const float wb = data.wb;
1597 (void)wa; // silence possible unused warnings
1598 (void)wb; //
1599
1600 const int32_t stride = data.im->stride();
1601 const int32_t zstride = data.im->lx();
1602
1603 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
1604 const int32_t pa = O1 + O2 + O3;
1605 const int32_t E = ((pa == 0) ? 1 : 0);
1606 const int32_t aera = pa + E;
1607
1608 const float invaera = fast_inv((float)aera);
1609 const float fP1a = fP1.w * invaera;
1610 const float fP2a = fP2.w * invaera;
1611 const float fP3a = fP3.w * invaera;
1612
1613 const float dw = (dx1 * fP1a) + (dx2 * fP2a) + (dx3 * fP3a);
1614
1615 const RGBf& cf1 = (RGBf)fP1.color;
1616 const RGBf& cf2 = (RGBf)fP2.color;
1617 const RGBf& cf3 = (RGBf)fP3.color;
1618 const int fP1R = (int)(256 * cf1.R);
1619 const int fP1G = (int)(256 * cf1.G);
1620 const int fP1B = (int)(256 * cf1.B);
1621 const int fP21R = (int)(256 * (cf2.R - cf1.R));
1622 const int fP21G = (int)(256 * (cf2.G - cf1.G));
1623 const int fP21B = (int)(256 * (cf2.B - cf1.B));
1624 const int fP31R = (int)(256 * (cf3.R - cf1.R));
1625 const int fP31G = (int)(256 * (cf3.G - cf1.G));
1626 const int fP31B = (int)(256 * (cf3.B - cf1.B));
1627
1628 // the texture coord
1629 fVec2 T1 = fP1.T;
1630 fVec2 T2 = fP2.T;
1631 fVec2 T3 = fP3.T;
1632
1633 const color_t* tex = data.tex->data();
1634 const int32_t texsize_x = data.tex->width();
1635 const int32_t texsize_y = data.tex->height();
1636 const int32_t texsize_x_mm = texsize_x - 1;
1637 const int32_t texsize_y_mm = texsize_y - 1;
1638 const int32_t texstride = data.tex->stride();
1639
1640 // divide the texture coord by aera
1641 T1 *= invaera;
1642 T2 *= invaera;
1643 T3 *= invaera;
1644 T1.x *= texsize_x;
1645 T2.x *= texsize_x;
1646 T3.x *= texsize_x;
1647 T1.y *= texsize_y;
1648 T2.y *= texsize_y;
1649 T3.y *= texsize_y;
1650
1651 const float dtx = ((T1.x * dx1) + (T2.x * dx2) + (T3.x * dx3));
1652 const float dty = ((T1.y * dx1) + (T2.y * dx2) + (T3.y * dx3));
1653
1654 while ((uintptr_t)(buf) < end)
1655 { // iterate over scanlines
1656 int32_t bx = 0; // start offset
1657 if (O1 < 0)
1658 {
1659 // we know that dx1 > 0
1660 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
1661 }
1662 if (O2 < 0)
1663 {
1664 if (dx2 <= 0)
1665 {
1666 if (dy2 <= 0) return;
1667 const int32_t by = (-O2 + dy2 - 1) / dy2;
1668 O1 += (by * dy1);
1669 O2 += (by * dy2);
1670 O3 += (by * dy3);
1671 const int32_t offs = by * stride;
1672 buf += offs;
1673 zbuf += offs;
1674 continue;
1675 }
1676 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
1677 }
1678 if (O3 < 0)
1679 {
1680 if (dx3 <= 0)
1681 {
1682 if (dy3 <= 0) return;
1683 const int32_t by = (-O3 + dy3 - 1) / dy3;
1684 O1 += (by * dy1);
1685 O2 += (by * dy2);
1686 O3 += (by * dy3);
1687 const int32_t offs = by * stride;
1688 buf += offs;
1689 zbuf += offs;
1690 continue;
1691 }
1692 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
1693 }
1694
1695 int32_t C1 = O1 + (dx1 * bx) + E;
1696 int32_t C2 = O2 + (dx2 * bx);
1697 int32_t C3 = O3 + (dx3 * bx);
1698 float cw = ((C1 * fP1a) + (C2 * fP2a) + (C3 * fP3a));
1699
1700 float tx = ((T1.x * C1) + (T2.x * C2) + (T3.x * C3));
1701 float ty = ((T1.y * C1) + (T2.y * C2) + (T3.y * C3));
1702
1703 while ((bx < lx) && ((C2 | C3) >= 0))
1704 {
1705 ZBUFFER_t& W = zbuf[bx];
1706 const ZBUFFER_t aa = (std::is_same<ZBUFFER_t, uint16_t>::value) ? ((ZBUFFER_t)(cw * wa + wb)) : ((ZBUFFER_t)cw);
1707 if (W < aa)
1708 {
1709 W = aa;
1710
1711 color_t col;
1712 if (TEXTURE_BILINEAR)
1713 {
1714 const float xx = tx;
1715 const float yy = ty;
1716 const int ttx = (int)floorf(xx);
1717 const int tty = (int)floorf(yy);
1718 const float ax = xx - ttx;
1719 const float ay = yy - tty;
1720 const int minx = (TEXTURE_WRAP ? (ttx & (texsize_x_mm)) : shaderclip(ttx, texsize_x_mm));
1721 const int maxx = (TEXTURE_WRAP ? ((ttx + 1) & (texsize_x_mm)) : shaderclip(ttx + 1, texsize_x_mm));
1722 const int miny = (TEXTURE_WRAP ? ((tty & (texsize_y_mm)) * texstride) : shaderclip(tty, texsize_y_mm) * texstride);
1723 const int maxy = (TEXTURE_WRAP ? (((tty + 1) & (texsize_y_mm)) * texstride) : shaderclip(tty + 1, texsize_y_mm) * texstride);
1724 col = interpolateColorsBilinear(tex[minx + miny], tex[maxx + miny], tex[minx + maxy], tex[maxx + maxy], ax, ay);
1725 }
1726 else
1727 {
1728 const int ttx = (TEXTURE_WRAP ? ((int)((tx))) & (texsize_x_mm) : shaderclip((int)(tx), texsize_x_mm));
1729 const int tty = (TEXTURE_WRAP ? ((int)((ty))) & (texsize_y_mm) : shaderclip((int)(ty), texsize_y_mm));
1730 col = tex[ttx + (tty)*texstride];
1731 }
1732
1733 const int r = fP1R + ((C2 * fP21R + C3 * fP31R) / aera);
1734 const int g = fP1G + ((C2 * fP21G + C3 * fP31G) / aera);
1735 const int b = fP1B + ((C2 * fP21B + C3 * fP31B) / aera);
1736
1737 col.mult256(r, g, b);
1738 buf[bx] = col;
1739
1740 }
1741
1742 C2 += dx2;
1743 C3 += dx3;
1744 cw += dw;
1745
1746 tx += dtx;
1747 ty += dty;
1748
1749 bx++;
1750 }
1751
1752 O1 += dy1;
1753 O2 += dy2;
1754 O3 += dy3;
1755 buf += stride;
1756 zbuf += zstride;
1757 }
1758 }
1759
1760
1761
1762
1766 template<int SHADER_FLAGS_ENABLED, typename color_t, typename ZBUFFER_t> void shader_select(const int32_t& offset, const int32_t& lx, const int32_t& ly,
1767 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
1768 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
1769 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
1770 const RasterizerParams<color_t, color_t, ZBUFFER_t> & data)
1771 {
1772 int raster_type = data.shader_type;
1773 if (TGX_SHADER_HAS_ZBUFFER(SHADER_FLAGS_ENABLED) && (TGX_SHADER_HAS_ZBUFFER(raster_type)))
1774 { // USING ZBUFFER
1775 if (TGX_SHADER_HAS_ORTHO(SHADER_FLAGS_ENABLED) && (TGX_SHADER_HAS_ORTHO(raster_type)))
1776 { // USING ORTHOGRAPHIC PROJECTION
1777 if (TGX_SHADER_HAS_TEXTURE(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE(raster_type))
1778 {
1779 if (TGX_SHADER_HAS_GOURAUD(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_GOURAUD(raster_type))
1780 {
1781 if (TGX_SHADER_HAS_TEXTURE_BILINEAR(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_BILINEAR(raster_type))
1782 {
1783 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1784 shader_Gouraud_Texture_Zbuffer_Ortho<color_t,ZBUFFER_t, true,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1785 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1786 shader_Gouraud_Texture_Zbuffer_Ortho<color_t, ZBUFFER_t, true, true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1787 }
1788 else if (TGX_SHADER_HAS_TEXTURE_NEAREST(SHADER_FLAGS_ENABLED))
1789 {
1790 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1791 shader_Gouraud_Texture_Zbuffer_Ortho<color_t, ZBUFFER_t, false,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1792 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1793 shader_Gouraud_Texture_Zbuffer_Ortho<color_t, ZBUFFER_t, false,true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1794 }
1795 }
1796 else if (TGX_SHADER_HAS_FLAT(SHADER_FLAGS_ENABLED))
1797 {
1798 if (TGX_SHADER_HAS_TEXTURE_BILINEAR(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_BILINEAR(raster_type))
1799 {
1800 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1801 shader_Flat_Texture_Zbuffer_Ortho<color_t, ZBUFFER_t, true,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1802 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1803 shader_Flat_Texture_Zbuffer_Ortho<color_t, ZBUFFER_t, true,true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1804 }
1805 else if (TGX_SHADER_HAS_TEXTURE_NEAREST(SHADER_FLAGS_ENABLED))
1806 {
1807 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1808 shader_Flat_Texture_Zbuffer_Ortho<color_t, ZBUFFER_t, false,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1809 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1810 shader_Flat_Texture_Zbuffer_Ortho<color_t, ZBUFFER_t, false,true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1811 }
1812 }
1813 }
1814 else if (TGX_SHADER_HAS_NOTEXTURE(SHADER_FLAGS_ENABLED))
1815 {
1816 if (TGX_SHADER_HAS_GOURAUD(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_GOURAUD(raster_type))
1817 shader_Gouraud_Zbuffer<color_t, ZBUFFER_t>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data); // same as perspective projection
1818 else if (TGX_SHADER_HAS_FLAT(SHADER_FLAGS_ENABLED))
1819 shader_Flat_Zbuffer<color_t, ZBUFFER_t>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data); // same as perspective projection
1820 }
1821 }
1822 else if (TGX_SHADER_HAS_PERSPECTIVE(SHADER_FLAGS_ENABLED))
1823 { // USING PERSPECTIVE PROJECTION
1824 if (TGX_SHADER_HAS_TEXTURE(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE(raster_type))
1825 {
1826 if (TGX_SHADER_HAS_GOURAUD(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_GOURAUD(raster_type))
1827 {
1828 if (TGX_SHADER_HAS_TEXTURE_BILINEAR(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_BILINEAR(raster_type))
1829 {
1830 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1831 shader_Gouraud_Texture_Zbuffer<color_t, ZBUFFER_t, true,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1832 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1833 shader_Gouraud_Texture_Zbuffer<color_t, ZBUFFER_t, true, true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1834 }
1835 else if (TGX_SHADER_HAS_TEXTURE_NEAREST(SHADER_FLAGS_ENABLED))
1836 {
1837 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1838 shader_Gouraud_Texture_Zbuffer<color_t, ZBUFFER_t, false,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1839 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1840 shader_Gouraud_Texture_Zbuffer<color_t, ZBUFFER_t, false,true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1841 }
1842 }
1843 else if (TGX_SHADER_HAS_FLAT(SHADER_FLAGS_ENABLED))
1844 {
1845 if (TGX_SHADER_HAS_TEXTURE_BILINEAR(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_BILINEAR(raster_type))
1846 {
1847 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1848 shader_Flat_Texture_Zbuffer<color_t, ZBUFFER_t, true,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1849 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1850 shader_Flat_Texture_Zbuffer<color_t, ZBUFFER_t, true,true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1851 }
1852 else if (TGX_SHADER_HAS_TEXTURE_NEAREST(SHADER_FLAGS_ENABLED))
1853 {
1854 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1855 shader_Flat_Texture_Zbuffer<color_t, ZBUFFER_t, false,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1856 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1857 shader_Flat_Texture_Zbuffer<color_t, ZBUFFER_t, false,true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1858 }
1859 }
1860 }
1861 else if (TGX_SHADER_HAS_NOTEXTURE(SHADER_FLAGS_ENABLED))
1862 {
1863 if (TGX_SHADER_HAS_GOURAUD(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_GOURAUD(raster_type))
1864 shader_Gouraud_Zbuffer<color_t, ZBUFFER_t>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1865 else if (TGX_SHADER_HAS_FLAT(SHADER_FLAGS_ENABLED))
1866 shader_Flat_Zbuffer<color_t, ZBUFFER_t>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1867 }
1868 }
1869 }
1870 else if (TGX_SHADER_HAS_NOZBUFFER(SHADER_FLAGS_ENABLED))
1871 { // NOT USING Z-BUFFER
1872 if (TGX_SHADER_HAS_ORTHO(SHADER_FLAGS_ENABLED) && (TGX_SHADER_HAS_ORTHO(raster_type)))
1873 { // USING ORTHOGRAPHIC PROJECTION
1874 if (TGX_SHADER_HAS_TEXTURE(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE(raster_type))
1875 {
1876 if (TGX_SHADER_HAS_GOURAUD(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_GOURAUD(raster_type))
1877 {
1878 if (TGX_SHADER_HAS_TEXTURE_BILINEAR(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_BILINEAR(raster_type))
1879 {
1880 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1881 shader_Gouraud_Texture_Ortho<color_t, ZBUFFER_t, true,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1882 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1883 shader_Gouraud_Texture_Ortho<color_t, ZBUFFER_t, true,true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1884 }
1885 else if (TGX_SHADER_HAS_TEXTURE_NEAREST(SHADER_FLAGS_ENABLED))
1886 {
1887 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1888 shader_Gouraud_Texture_Ortho<color_t, ZBUFFER_t, false,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1889 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1890 shader_Gouraud_Texture_Ortho<color_t, ZBUFFER_t, false,true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1891 }
1892 }
1893 else if (TGX_SHADER_HAS_FLAT(SHADER_FLAGS_ENABLED))
1894 {
1895 if (TGX_SHADER_HAS_TEXTURE_BILINEAR(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_BILINEAR(raster_type))
1896 {
1897 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1898 shader_Flat_Texture_Ortho<color_t, ZBUFFER_t, true,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1899 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1900 shader_Flat_Texture_Ortho<color_t, ZBUFFER_t, true,true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1901 }
1902 else if (TGX_SHADER_HAS_TEXTURE_NEAREST(SHADER_FLAGS_ENABLED))
1903 {
1904 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1905 shader_Flat_Texture_Ortho<color_t, ZBUFFER_t, false,false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1906 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1907 shader_Flat_Texture_Ortho<color_t, ZBUFFER_t, false,true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1908 }
1909 }
1910 }
1911 else if (TGX_SHADER_HAS_NOTEXTURE(SHADER_FLAGS_ENABLED))
1912 {
1913 if (TGX_SHADER_HAS_GOURAUD(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_GOURAUD(raster_type))
1914 shader_Gouraud<color_t, ZBUFFER_t>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data); // same as perspective projection
1915 else if (TGX_SHADER_HAS_FLAT(SHADER_FLAGS_ENABLED))
1916 shader_Flat<color_t, ZBUFFER_t>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data); // same as perspective projection
1917 }
1918 }
1919 else if (TGX_SHADER_HAS_PERSPECTIVE(SHADER_FLAGS_ENABLED))
1920 { // USING PERSPECTIVE PROJECTION
1921 if (TGX_SHADER_HAS_TEXTURE(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE(raster_type))
1922 {
1923 if (TGX_SHADER_HAS_GOURAUD(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_GOURAUD(raster_type))
1924 {
1925 if (TGX_SHADER_HAS_TEXTURE_BILINEAR(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_BILINEAR(raster_type))
1926 {
1927 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1928 shader_Gouraud_Texture<color_t, ZBUFFER_t, true, false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1929 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1930 shader_Gouraud_Texture<color_t, ZBUFFER_t, true, true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1931 }
1932 else if (TGX_SHADER_HAS_TEXTURE_NEAREST(SHADER_FLAGS_ENABLED))
1933 {
1934 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1935 shader_Gouraud_Texture<color_t, ZBUFFER_t, false, false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1936 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1937 shader_Gouraud_Texture<color_t, ZBUFFER_t, false, true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1938 }
1939 }
1940 else if (TGX_SHADER_HAS_FLAT(SHADER_FLAGS_ENABLED))
1941 {
1942 if (TGX_SHADER_HAS_TEXTURE_BILINEAR(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_BILINEAR(raster_type))
1943 {
1944 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1945 shader_Flat_Texture<color_t, ZBUFFER_t, true, false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1946 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1947 shader_Flat_Texture<color_t, ZBUFFER_t, true, true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1948 }
1949 else if (TGX_SHADER_HAS_TEXTURE_NEAREST(SHADER_FLAGS_ENABLED))
1950 {
1951 if (TGX_SHADER_HAS_TEXTURE_CLAMP(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_TEXTURE_CLAMP(raster_type))
1952 shader_Flat_Texture<color_t, ZBUFFER_t, false, false>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1953 else if (TGX_SHADER_HAS_TEXTURE_WRAP_POW2(SHADER_FLAGS_ENABLED))
1954 shader_Flat_Texture<color_t, ZBUFFER_t, false, true>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1955 }
1956 }
1957 }
1958 else if (TGX_SHADER_HAS_NOTEXTURE(SHADER_FLAGS_ENABLED))
1959 {
1960 if (TGX_SHADER_HAS_GOURAUD(SHADER_FLAGS_ENABLED) && TGX_SHADER_HAS_GOURAUD(raster_type))
1961 shader_Gouraud<color_t, ZBUFFER_t>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1962 else if (TGX_SHADER_HAS_FLAT(SHADER_FLAGS_ENABLED))
1963 shader_Flat<color_t, ZBUFFER_t>(offset, lx, ly, dx1, dy1, O1, fP1, dx2, dy2, O2, fP2, dx3, dy3, O3, fP3, data);
1964 }
1965 }
1966 }
1967 }
1968
1969
1970
1971
1972
1976 template<bool USE_BLENDING, typename color_t_im>
1977 void shader_2D_gradient(const int32_t& offset, const int32_t& lx, const int32_t& ly,
1978 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
1979 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
1980 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
1981 const RasterizerParams<color_t_im, color_t_im, float> & data)
1982 {
1983 color_t_im * buf = data.im->data() + offset;
1984 const int32_t stride = data.im->stride();
1985
1986 // use RGB32 (could use RGB64 be it would be slower).
1987 const RGB32 col1 = RGB64(fP1.color.R, fP1.color.G, fP1.color.B, fP1.A);
1988 const RGB32 col2 = RGB64(fP2.color.R, fP2.color.G, fP2.color.B, fP2.A);
1989 const RGB32 col3 = RGB64(fP3.color.R, fP3.color.G, fP3.color.B, fP3.A);
1990
1991 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
1992 const int32_t pa = O1 + O2 + O3;
1993 const int32_t E = ((pa == 0) ? 1 : 0);
1994 const int32_t aera = pa + E;
1995 const int shiftC = (aera > (1 << 22)) ? 10 : 0; // prevent overflow during color interpolation
1996
1997 while ((uintptr_t)(buf) < end)
1998 { // iterate over scanlines
1999 int32_t bx = 0; // start offset
2000 if (O1 < 0)
2001 {
2002 // we know that dx1 > 0
2003 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
2004 }
2005 if (O2 < 0)
2006 {
2007 if (dx2 <= 0)
2008 {
2009 if (dy2 <= 0) return;
2010 const int32_t by = (-O2 + dy2 - 1) / dy2;
2011 O1 += (by * dy1);
2012 O2 += (by * dy2);
2013 O3 += (by * dy3);
2014 const int32_t offs = by * stride;
2015 buf += offs;
2016 continue;
2017 }
2018 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
2019 }
2020 if (O3 < 0)
2021 {
2022 if (dx3 <= 0)
2023 {
2024 if (dy3 <= 0) return;
2025 const int32_t by = (-O3 + dy3 - 1) / dy3;
2026 O1 += (by * dy1);
2027 O2 += (by * dy2);
2028 O3 += (by * dy3);
2029 const int32_t offs = by * stride;
2030 buf += offs;
2031 continue;
2032 }
2033 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
2034 }
2035
2036 int32_t C2 = O2 + (dx2 * bx);
2037 int32_t C3 = O3 + (dx3 * bx);
2038 while ((bx < lx) && ((C2 | C3) >= 0))
2039 {
2040 if (USE_BLENDING)
2041 {
2042 RGB32 c(buf[bx]); // could use RGB64 instead but would be slower
2043 c.blend(interpolateColorsTriangle(col2, C2 >> shiftC, col3, C3 >> shiftC, col1, aera >> shiftC), data.opacity);
2044 buf[bx] = color_t_im(c);
2045 }
2046 else
2047 {
2048 buf[bx] = color_t_im(interpolateColorsTriangle(col2, C2 >> shiftC, col3, C3 >> shiftC, col1, aera >> shiftC));
2049 }
2050 C2 += dx2;
2051 C3 += dx3;
2052 bx++;
2053 }
2054
2055 O1 += dy1;
2056 O2 += dy2;
2057 O3 += dy3;
2058 buf += stride;
2059 }
2060 }
2061
2062
2063
2067 template<bool USE_BLENDING, bool USE_MASKING, bool USE_GRADIENT, typename color_t_im, typename color_t_tex>
2068 void shader_2D_texture(const int32_t& offset, const int32_t& lx, const int32_t& ly,
2069 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
2070 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
2071 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
2072 const RasterizerParams<color_t_im, color_t_tex, float> & data)
2073 {
2074
2075 color_t_im * buf = data.im->data() + offset;
2076 const int32_t stride = data.im->stride();
2077
2078 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
2079 const int32_t pa = O1 + O2 + O3;
2080 const int32_t E = ((pa == 0) ? 1 : 0);
2081 const int32_t aera = pa + E;
2082
2083 const float invaera = fast_inv((float)aera);
2084
2085 const color_t_tex mask_color = data.mask_color;
2086
2087 const RGBf& cf1 = (RGBf)fP1.color;
2088 const RGBf& cf2 = (RGBf)fP2.color;
2089 const RGBf& cf3 = (RGBf)fP3.color;
2090
2091 // the texture coord
2092 fVec2 T1 = fP1.T;
2093 fVec2 T2 = fP2.T;
2094 fVec2 T3 = fP3.T;
2095
2096 const color_t_tex * tex = data.tex->data();
2097 const int32_t texsize_x = data.tex->width();
2098 const int32_t texsize_y = data.tex->height();
2099 const int32_t texsize_x_mm = data.tex->width() - 1;
2100 const int32_t texsize_y_mm = data.tex->height() - 1;
2101 const int32_t texstride = data.tex->stride();
2102
2103 // divide the texture coord by aera
2104 T1 *= invaera;
2105 T2 *= invaera;
2106 T3 *= invaera;
2107 T1.x *= texsize_x;
2108 T2.x *= texsize_x;
2109 T3.x *= texsize_x;
2110 T1.y *= texsize_y;
2111 T2.y *= texsize_y;
2112 T3.y *= texsize_y;
2113
2114 const float dtx = ((T1.x * dx1) + (T2.x * dx2) + (T3.x * dx3));
2115 const float dty = ((T1.y * dx1) + (T2.y * dx2) + (T3.y * dx3));
2116
2117 while ((uintptr_t)(buf) < end)
2118 { // iterate over scanlines
2119 int32_t bx = 0; // start offset
2120 if (O1 < 0)
2121 {
2122 // we know that dx1 > 0
2123 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
2124 }
2125 if (O2 < 0)
2126 {
2127 if (dx2 <= 0)
2128 {
2129 if (dy2 <= 0) return;
2130 const int32_t by = (-O2 + dy2 - 1) / dy2;
2131 O1 += (by * dy1);
2132 O2 += (by * dy2);
2133 O3 += (by * dy3);
2134 const int32_t offs = by * stride;
2135 buf += offs;
2136 continue;
2137 }
2138 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
2139 }
2140 if (O3 < 0)
2141 {
2142 if (dx3 <= 0)
2143 {
2144 if (dy3 <= 0) return;
2145 const int32_t by = (-O3 + dy3 - 1) / dy3;
2146 O1 += (by * dy1);
2147 O2 += (by * dy2);
2148 O3 += (by * dy3);
2149 const int32_t offs = by * stride;
2150 buf += offs;
2151 continue;
2152 }
2153 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
2154 }
2155
2156 int32_t C1 = O1 + (dx1 * bx) + E;
2157 int32_t C2 = O2 + (dx2 * bx);
2158 int32_t C3 = O3 + (dx3 * bx);
2159
2160 float tx = ((T1.x * C1) + (T2.x * C2) + (T3.x * C3)) - 0.5f;
2161 float ty = ((T1.y * C1) + (T2.y * C2) + (T3.y * C3)) - 0.5f;
2162
2163 while ((bx < lx) && ((C2 | C3) >= 0))
2164 {
2165 const float xx = tx;
2166 const float yy = ty;
2167 const int ttx = (int)floorf(xx);
2168 const int tty = (int)floorf(yy);
2169 const float ax = xx - ttx;
2170 const float ay = yy - tty;
2171
2172 const int minx = shaderclip(ttx, texsize_x_mm);
2173 const int maxx = shaderclip(ttx + 1, texsize_x_mm);
2174 const int miny = shaderclip(tty, texsize_y_mm) * texstride;
2175 const int maxy = shaderclip(tty + 1, texsize_y_mm) * texstride;
2176
2177 if (USE_MASKING)
2178 { //
2179 auto col00 = tex[minx + miny];
2180 tgx::RGB32 acol00 = (col00 == mask_color) ? tgx::RGB32((uint32_t)0) : tgx::RGB32(col00);
2181
2182 auto col10 = tex[maxx + miny];
2183 tgx::RGB32 acol10 = (col10 == mask_color) ? tgx::RGB32((uint32_t)0) : tgx::RGB32(col10);
2184
2185 auto col01 = tex[minx + maxy];
2186 tgx::RGB32 acol01 = (col01 == mask_color) ? tgx::RGB32((uint32_t)0) : tgx::RGB32(col01);
2187
2188 auto col11 = tex[maxx + maxy];
2189 tgx::RGB32 acol11 = (col11 == mask_color) ? tgx::RGB32((uint32_t)0) : tgx::RGB32(col11);
2190
2191 tgx::RGB32 col = interpolateColorsBilinear(acol00, acol10, acol01, acol11, ax, ay);
2192
2193 if (USE_GRADIENT)
2194 {
2195 const int sC2 = C2;
2196 const int sC3 = C3;
2197 const int sC1 = aera - C3 - C2;
2198 const float m = 256.0f / aera;
2199 const int r = (int)((sC1 * cf1.R + sC2 * cf2.R + sC3 * cf3.R) * m);
2200 const int g = (int)((sC1 * cf1.G + sC2 * cf2.G + sC3 * cf3.G) * m);
2201 const int b = (int)((sC1 * cf1.B + sC2 * cf2.B + sC3 * cf3.B) * m);
2202 const int a = (int)((sC1 * fP1.A + sC2 * fP2.A + sC3 * fP3.A) * m);
2203 col.mult256(r, g, b, a);
2204 }
2205 if (USE_BLENDING)
2206 {
2207 tgx::RGB32 c = tgx::RGB32(buf[bx]);
2208 c.blend(col, data.opacity);
2209 buf[bx] = color_t_im(c);
2210 }
2211 else
2212 {
2213 buf[bx] = color_t_im(col);
2214 }
2215 }
2216 else
2217 {
2218 color_t_tex col = interpolateColorsBilinear(tex[minx + miny], tex[maxx + miny], tex[minx + maxy], tex[maxx + maxy], ax, ay);
2219 if (USE_GRADIENT)
2220 {
2221 const int sC2 = C2;
2222 const int sC3 = C3;
2223 const int sC1 = aera - C3 - C2;
2224 const float m = 256.0f / aera;
2225 const int r = (int)((sC1 * cf1.R + sC2 * cf2.R + sC3 * cf3.R) * m);
2226 const int g = (int)((sC1 * cf1.G + sC2 * cf2.G + sC3 * cf3.G) * m);
2227 const int b = (int)((sC1 * cf1.B + sC2 * cf2.B + sC3 * cf3.B) * m);
2228 const int a = (int)((sC1 * fP1.A + sC2 * fP2.A + sC3 * fP3.A) * m);
2229 col.mult256(r, g, b, a);
2230 }
2231 if (USE_BLENDING)
2232 {
2233 color_t_tex c = color_t_tex(buf[bx]);
2234 c.blend(col, data.opacity);
2235 buf[bx] = color_t_im(c);
2236 }
2237 else
2238 {
2239 buf[bx] = color_t_im(col);
2240 }
2241 }
2242
2243 C2 += dx2;
2244 C3 += dx3;
2245
2246 tx += dtx;
2247 ty += dty;
2248
2249 bx++;
2250 }
2251
2252 O1 += dy1;
2253 O2 += dy2;
2254 O3 += dy3;
2255 buf += stride;
2256 }
2257 }
2258
2259
2260
2261
2265 template<typename BLEND_OP, typename color_t_im, typename color_t_tex>
2266 void shader_2D_texture_blend_op(const int32_t& offset, const int32_t& lx, const int32_t& ly,
2267 const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4& fP1,
2268 const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4& fP2,
2269 const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4& fP3,
2270 const RasterizerParams<color_t_im, color_t_tex, float, BLEND_OP> & data)
2271 {
2272
2273 color_t_im * buf = data.im->data() + offset;
2274 const int32_t stride = data.im->stride();
2275
2276 const uintptr_t end = (uintptr_t)(buf + (ly * stride));
2277 const int32_t pa = O1 + O2 + O3;
2278 const int32_t E = ((pa == 0) ? 1 : 0);
2279 const int32_t aera = pa + E;
2280
2281 const float invaera = fast_inv((float)aera);
2282
2283 // the texture coord
2284 fVec2 T1 = fP1.T;
2285 fVec2 T2 = fP2.T;
2286 fVec2 T3 = fP3.T;
2287
2288
2289 const color_t_tex * tex = data.tex->data();
2290 const int32_t texsize_x = data.tex->width();
2291 const int32_t texsize_y = data.tex->height();
2292 const int32_t texsize_x_mm = data.tex->width() - 1;
2293 const int32_t texsize_y_mm = data.tex->height() - 1;
2294 const int32_t texstride = data.tex->stride();
2295
2296 // divide the texture coord by aera
2297 T1 *= invaera;
2298 T2 *= invaera;
2299 T3 *= invaera;
2300 T1.x *= texsize_x;
2301 T2.x *= texsize_x;
2302 T3.x *= texsize_x;
2303 T1.y *= texsize_y;
2304 T2.y *= texsize_y;
2305 T3.y *= texsize_y;
2306
2307 const float dtx = ((T1.x * dx1) + (T2.x * dx2) + (T3.x * dx3));
2308 const float dty = ((T1.y * dx1) + (T2.y * dx2) + (T3.y * dx3));
2309
2310 while ((uintptr_t)(buf) < end)
2311 { // iterate over scanlines
2312 int32_t bx = 0; // start offset
2313 if (O1 < 0)
2314 {
2315 // we know that dx1 > 0
2316 bx = (-O1 + dx1 - 1) / dx1; // first index where it becomes positive
2317 }
2318 if (O2 < 0)
2319 {
2320 if (dx2 <= 0)
2321 {
2322 if (dy2 <= 0) return;
2323 const int32_t by = (-O2 + dy2 - 1) / dy2;
2324 O1 += (by * dy1);
2325 O2 += (by * dy2);
2326 O3 += (by * dy3);
2327 const int32_t offs = by * stride;
2328 buf += offs;
2329 continue;
2330 }
2331 bx = max(bx, ((-O2 + dx2 - 1) / dx2));
2332 }
2333 if (O3 < 0)
2334 {
2335 if (dx3 <= 0)
2336 {
2337 if (dy3 <= 0) return;
2338 const int32_t by = (-O3 + dy3 - 1) / dy3;
2339 O1 += (by * dy1);
2340 O2 += (by * dy2);
2341 O3 += (by * dy3);
2342 const int32_t offs = by * stride;
2343 buf += offs;
2344 continue;
2345 }
2346 bx = max(bx, ((-O3 + dx3 - 1) / dx3));
2347 }
2348
2349 int32_t C1 = O1 + (dx1 * bx) + E;
2350 int32_t C2 = O2 + (dx2 * bx);
2351 int32_t C3 = O3 + (dx3 * bx);
2352
2353 float tx = ((T1.x * C1) + (T2.x * C2) + (T3.x * C3)) - 0.5f;
2354 float ty = ((T1.y * C1) + (T2.y * C2) + (T3.y * C3)) - 0.5f;
2355
2356 while ((bx < lx) && ((C2 | C3) >= 0))
2357 {
2358 const float xx = tx;
2359 const float yy = ty;
2360 const int ttx = (int)floorf(xx);
2361 const int tty = (int)floorf(yy);
2362 const float ax = xx - ttx;
2363 const float ay = yy - tty;
2364
2365 const int minx = shaderclip(ttx, texsize_x_mm);
2366 const int maxx = shaderclip(ttx + 1, texsize_x_mm);
2367 const int miny = shaderclip(tty, texsize_y_mm) * texstride;
2368 const int maxy = shaderclip(tty + 1, texsize_y_mm) * texstride;
2369
2370 color_t_tex col = interpolateColorsBilinear(tex[minx + miny], tex[maxx + miny], tex[minx + maxy], tex[maxx + maxy], ax, ay);
2371
2372 buf[bx] = (color_t_im)((*data.p_blend_op)(col, buf[bx]));
2373
2374 C2 += dx2;
2375 C3 += dx3;
2376
2377 tx += dtx;
2378 ty += dty;
2379
2380 bx++;
2381 }
2382
2383 O1 += dy1;
2384 O2 += dy2;
2385 O3 += dy3;
2386 buf += stride;
2387 }
2388 }
2389
2390
2391}
2392
2393#endif
2394
2395#endif
2396
const RGB32 RGB32_Red
Color red in RGB32 format.
RGB565 interpolateColorsBilinear(const RGB565 &C00, const RGB565 &C10, const RGB565 &C01, const RGB565 &C11, const float ax, const float ay)
Bilinear interpolation between 4 colors.
Definition: Color.h:621
RGB565 interpolateColorsTriangle(const RGB565 &col1, int32_t C1, const RGB565 &col2, int32_t C2, const RGB565 &col3, const int32_t totC)
Interpolate between 3 colors.
Definition: Color.h:591
TGX_INLINE T max(const T &a, const T &b)
Don't know why but much faster than fmaxf() for floats.
Definition: Misc.h:184
TGX_INLINE float fast_inv(float x)
Fast (approximate) computation of 1/x.
Definition: Misc.h:219
Triangle shader parameters.
void shader_test(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t &dx1, const int32_t &dy1, int32_t O1, const tgx::RasterizerVec4 &fP1, const int32_t &dx2, const int32_t &dy2, int32_t O2, const tgx::RasterizerVec4 &fP2, const int32_t &dx3, const int32_t &dy3, int32_t O3, const tgx::RasterizerVec4 &fP3, const tgx::RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
For test purposes...
Definition: Shaders.h:45
void shader_select(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
META-Shader THAT DISPATCH TO THE CORRECT Shader ABOVE (IF ENABLED).
Definition: Shaders.h:1766
void shader_Gouraud_Texture(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
TEXTURE + GOURAUD SHADING (NO ZBUFFER)
Definition: Shaders.h:382
void shader_2D_texture(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t_im, color_t_tex, float > &data)
2D shader (texture)
Definition: Shaders.h:2068
void shader_Flat(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t &dx1, const int32_t &dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t &dx2, const int32_t &dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t &dx3, const int32_t &dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
FLAT SHADING (NO ZBUFFER)
Definition: Shaders.h:74
void shader_Flat_Texture(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
TEXTURE + FLAT SHADING (NO ZBUFFER)
Definition: Shaders.h:230
void shader_Gouraud(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t &dx1, const int32_t &dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t &dx2, const int32_t &dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t &dx3, const int32_t &dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
GOURAUD SHADING (NO Z BUFFER)
Definition: Shaders.h:149
void shader_Flat_Texture_Zbuffer_Ortho(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
ZBUFFER + TEXTURE + FLAT SHADING + ORTHOGRAPHIC.
Definition: Shaders.h:1419
void shader_Gouraud_Texture_Ortho(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
TEXTURE + GOURAUD SHADING (NO ZBUFFER) + ORTHOGRAPHIC.
Definition: Shaders.h:1265
void shader_Flat_Texture_Zbuffer(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
ZBUFFER + TEXTURE + FLAT SHADING.
Definition: Shaders.h:777
void shader_Flat_Texture_Ortho(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
TEXTURE + FLAT SHADING (NO ZBUFFER) + ORTHOGRAPHIC.
Definition: Shaders.h:1123
void shader_Gouraud_Texture_Zbuffer_Ortho(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
ZBUFFER + TEXTURE + GOURAUD SHADING + ORTHOGRAPHIC.
Definition: Shaders.h:1586
void shader_Gouraud_Zbuffer(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
ZBUFFER + GOURAUD SHADING.
Definition: Shaders.h:754
void shader_2D_gradient(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t_im, color_t_im, float > &data)
2D shader (gradient)
Definition: Shaders.h:1977
TGX_INLINE int shaderclip(int v, int maxv)
for texture clamping
Definition: Shaders.h:34
void shader_Flat_Zbuffer(const int32_t offset, const int32_t &lx, const int32_t &ly, const int32_t &dx1, const int32_t &dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t &dx2, const int32_t &dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t &dx3, const int32_t &dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
ZBUFFER + FLAT SHADING.
Definition: Shaders.h:547
void shader_Gouraud_Zbuffer_sub(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
ZBUFFER + GOURAUD SHADING (sub-procedure, templated on shiftC)
Definition: Shaders.h:649
void shader_Gouraud_Texture_Zbuffer(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t, color_t, ZBUFFER_t > &data)
ZBUFFER + TEXTURE + GOURAUD SHADING.
Definition: Shaders.h:945
void shader_2D_texture_blend_op(const int32_t &offset, const int32_t &lx, const int32_t &ly, const int32_t dx1, const int32_t dy1, int32_t O1, const RasterizerVec4 &fP1, const int32_t dx2, const int32_t dy2, int32_t O2, const RasterizerVec4 &fP2, const int32_t dx3, const int32_t dy3, int32_t O3, const RasterizerVec4 &fP3, const RasterizerParams< color_t_im, color_t_tex, float, BLEND_OP > &data)
2D shader (texture with custom blending operator)
Definition: Shaders.h:2266
Color in R8/G8/B8/A8 format.
Definition: Color.h:1176
void mult256(int mr, int mg, int mb)
Multiply each color component by a given factor m/256 with m in [0,256] except the A component.
Definition: Color.h:1590
void blend256(const RGB32 &fg_col, uint32_t alpha)
alpha-blend fg_col over this one with a given opacity in the range 0.0f (fully transparent) to 1....
Definition: Color.h:1561
void blend(const RGB32 &fg_col, float alpha)
alpha-blend fg_col over this one with a given opacity in the range 0.0f (fully transparent) to 1....
Definition: Color.h:1546
float opacity() const
Return the opacity (alpha channel value) of this color in the range [0,1] (0=fully transparent,...
Definition: Color.h:1629
float opacity() const
Dummy function for compatibility with color types having an alpha channel.
Definition: Color.h:565
Color in R16/G16/B16/A16 format.
Definition: Color.h:1791
Color in R,G,B float format.
Definition: Color.h:2407
float R
Red channel.
Definition: Color.h:2420
float B
Blue channel.
Definition: Color.h:2422
float G
Green channel.
Definition: Color.h:2421
T x
'x' coordinate (first dimension)
Definition: Vec2.h:72
T y
'y' coordinate (second dimension)
Definition: Vec2.h:73