1 // Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #include "IrrCompileConfig.h"
6 #include "IBurningShader.h"
7 
8 #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
9 
10 // compile flag for this file
11 #undef USE_ZBUFFER
12 #undef IPOL_Z
13 #undef CMP_Z
14 #undef WRITE_Z
15 
16 #undef IPOL_W
17 #undef CMP_W
18 #undef WRITE_W
19 
20 #undef SUBTEXEL
21 #undef INVERSE_W
22 
23 #undef IPOL_C0
24 #undef IPOL_T0
25 #undef IPOL_T1
26 
27 // define render case
28 #define SUBTEXEL
29 #define INVERSE_W
30 
31 #define USE_ZBUFFER
32 #define IPOL_W
33 #define CMP_W
34 #define WRITE_W
35 
36 #define IPOL_C0
37 #define IPOL_T0
38 //#define IPOL_T1
39 
40 // apply global override
41 #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
42 	#undef INVERSE_W
43 #endif
44 
45 #ifndef SOFTWARE_DRIVER_2_SUBTEXEL
46 	#undef SUBTEXEL
47 #endif
48 
49 #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR
50 	#undef IPOL_C0
51 #endif
52 
53 #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER )
54 	#ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
55 		#undef IPOL_W
56 	#endif
57 	#define IPOL_Z
58 
59 	#ifdef CMP_W
60 		#undef CMP_W
61 		#define CMP_Z
62 	#endif
63 
64 	#ifdef WRITE_W
65 		#undef WRITE_W
66 		#define WRITE_Z
67 	#endif
68 
69 #endif
70 
71 
72 
73 namespace irr
74 {
75 
76 namespace video
77 {
78 
79 class CTRTextureGouraudAlpha2 : public IBurningShader
80 {
81 public:
82 
83 	//! constructor
84 	CTRTextureGouraudAlpha2(CBurningVideoDriver* driver);
85 
86 	//! draws an indexed triangle list
87 	virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c );
88 
89 	virtual void setParam ( u32 index, f32 value);
90 
91 
92 private:
93 	void scanline_bilinear ();
94 
95 	sScanConvertData scan;
96 	sScanLineData line;
97 
98 	u32 AlphaRef;
99 };
100 
101 //! constructor
CTRTextureGouraudAlpha2(CBurningVideoDriver * driver)102 CTRTextureGouraudAlpha2::CTRTextureGouraudAlpha2(CBurningVideoDriver* driver)
103 : IBurningShader(driver)
104 {
105 	#ifdef _DEBUG
106 	setDebugName("CTRTextureGouraudAlpha2");
107 	#endif
108 
109 	AlphaRef = 0;
110 }
111 
112 
113 /*!
114 */
setParam(u32 index,f32 value)115 void CTRTextureGouraudAlpha2::setParam ( u32 index, f32 value)
116 {
117 #ifdef BURNINGVIDEO_RENDERER_FAST
118 	AlphaRef = core::floor32 ( value * 256.f );
119 #else
120 	AlphaRef = u32_to_fixPoint ( core::floor32 ( value * 256.f ) );
121 #endif
122 }
123 
124 /*!
125 */
scanline_bilinear()126 void CTRTextureGouraudAlpha2::scanline_bilinear ()
127 {
128 	tVideoSample *dst;
129 
130 #ifdef USE_ZBUFFER
131 	fp24 *z;
132 #endif
133 
134 	s32 xStart;
135 	s32 xEnd;
136 	s32 dx;
137 
138 
139 #ifdef SUBTEXEL
140 	f32 subPixel;
141 #endif
142 
143 #ifdef IPOL_Z
144 	f32 slopeZ;
145 #endif
146 #ifdef IPOL_W
147 	fp24 slopeW;
148 #endif
149 #ifdef IPOL_C0
150 	sVec4 slopeC[MATERIAL_MAX_COLORS];
151 #endif
152 #ifdef IPOL_T0
153 	sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES];
154 #endif
155 
156 	// apply top-left fill-convention, left
157 	xStart = core::ceil32( line.x[0] );
158 	xEnd = core::ceil32( line.x[1] ) - 1;
159 
160 	dx = xEnd - xStart;
161 
162 	if ( dx < 0 )
163 		return;
164 
165 	// slopes
166 	const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] );
167 
168 #ifdef IPOL_Z
169 	slopeZ = (line.z[1] - line.z[0]) * invDeltaX;
170 #endif
171 #ifdef IPOL_W
172 	slopeW = (line.w[1] - line.w[0]) * invDeltaX;
173 #endif
174 #ifdef IPOL_C0
175 	slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX;
176 #endif
177 #ifdef IPOL_T0
178 	slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX;
179 #endif
180 #ifdef IPOL_T1
181 	slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX;
182 #endif
183 
184 #ifdef SUBTEXEL
185 	subPixel = ( (f32) xStart ) - line.x[0];
186 #ifdef IPOL_Z
187 	line.z[0] += slopeZ * subPixel;
188 #endif
189 #ifdef IPOL_W
190 	line.w[0] += slopeW * subPixel;
191 #endif
192 #ifdef IPOL_C0
193 	line.c[0][0] += slopeC[0] * subPixel;
194 #endif
195 #ifdef IPOL_T0
196 	line.t[0][0] += slopeT[0] * subPixel;
197 #endif
198 #ifdef IPOL_T1
199 	line.t[1][0] += slopeT[1] * subPixel;
200 #endif
201 #endif
202 
203 	dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
204 
205 #ifdef USE_ZBUFFER
206 	z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
207 #endif
208 
209 
210 #ifdef INVERSE_W
211 	f32 inversew;
212 #endif
213 
214 #ifdef BURNINGVIDEO_RENDERER_FAST
215 	u32 dIndex = ( line.y & 3 ) << 2;
216 
217 #else
218 	tFixPoint a0;
219 	tFixPoint r0, g0, b0;
220 #endif
221 
222 #ifdef IPOL_C0
223 	tFixPoint r1, g1, b1;
224 	tFixPoint r2, g2, b2;
225 #endif
226 
227 	for ( s32 i = 0; i <= dx; ++i )
228 	{
229 #ifdef CMP_Z
230 		if ( line.z[0] < z[i] )
231 #endif
232 #ifdef CMP_W
233 		if ( line.w[0] >= z[i] )
234 #endif
235 
236 		{
237 
238 #ifdef BURNINGVIDEO_RENDERER_FAST
239 
240 		const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ];
241 
242 #ifdef INVERSE_W
243 
244 		inversew = fix_inverse32 ( line.w[0] );
245 
246 		u32 argb = getTexel_plain ( &IT[0],	d + tofix ( line.t[0][0].x,inversew),
247 											d + tofix ( line.t[0][0].y,inversew)
248 											);
249 
250 #else
251 
252 		u32 argb = getTexel_plain ( &IT[0],	d + tofix ( line.t[0][0].x),
253 											d + tofix ( line.t[0][0].y)
254 											);
255 
256 #endif
257 
258 		const u32 alpha = ( argb >> 24 );
259 		if ( alpha > AlphaRef )
260 		{
261 #ifdef WRITE_Z
262 			z[i] = line.z[0];
263 #endif
264 #ifdef WRITE_W
265 			z[i] = line.w[0];
266 #endif
267 
268 			dst[i] = PixelBlend32 ( dst[i], argb, alpha );
269 		}
270 
271 
272 #else
273 
274 #ifdef INVERSE_W
275 		inversew = fix_inverse32 ( line.w[0] );
276 		getSample_texture ( a0,r0,g0,b0,
277 							&IT[0],
278 							tofix ( line.t[0][0].x,inversew),
279 							tofix ( line.t[0][0].y,inversew)
280 						);
281 #else
282 		getSample_texture ( a0,r0,g0,b0,
283 							&IT[0],
284 							tofix ( line.t[0][0].x),
285 							tofix ( line.t[0][0].y)
286 						);
287 #endif
288 		if ( (tFixPointu) a0 > AlphaRef )
289 		{
290 #ifdef WRITE_Z
291 			z[i] = line.z[0];
292 #endif
293 #ifdef WRITE_W
294 			z[i] = line.w[0];
295 #endif
296 
297 #ifdef INVERSE_W
298 			getSample_color ( r2, g2, b2, line.c[0][0], inversew );
299 #else
300 			getSample_color ( r2, g2, b2, line.c[0][0] );
301 #endif
302 			r0 = imulFix ( r0, r2 );
303 			g0 = imulFix ( g0, g2 );
304 			b0 = imulFix ( b0, b2 );
305 
306 			color_to_fix ( r1, g1, b1, dst[i] );
307 
308 			a0 >>= 8;
309 
310 			r2 = r1 + imulFix ( a0, r0 - r1 );
311 			g2 = g1 + imulFix ( a0, g0 - g1 );
312 			b2 = b1 + imulFix ( a0, b0 - b1 );
313 			dst[i] = fix4_to_color ( a0, r2, g2, b2 );
314 
315 /*
316 			dst[i] = PixelBlend32 ( dst[i],
317 									fix_to_color ( r0,g0, b0 ),
318 									fixPointu_to_u32 ( a0 )
319 								);
320 */
321 /*
322 			getSample_color ( r2, g2, b2, line.c[0][0], inversew * COLOR_MAX );
323 			color_to_fix ( r1, g1, b1, dst[i] );
324 
325 			r2 = r0 + imulFix ( a0, r1 - r0 );
326 			g2 = g0 + imulFix ( a0, g1 - g0 );
327 			b2 = b0 + imulFix ( a0, b1 - b0 );
328 			dst[i] = fix_to_color ( r2, g2, b2 );
329 */
330 
331 		}
332 #endif
333 
334 		}
335 
336 #ifdef IPOL_Z
337 		line.z[0] += slopeZ;
338 #endif
339 #ifdef IPOL_W
340 		line.w[0] += slopeW;
341 #endif
342 #ifdef IPOL_C0
343 		line.c[0][0] += slopeC[0];
344 #endif
345 #ifdef IPOL_T0
346 		line.t[0][0] += slopeT[0];
347 #endif
348 #ifdef IPOL_T1
349 		line.t[1][0] += slopeT[1];
350 #endif
351 	}
352 
353 }
354 
drawTriangle(const s4DVertex * a,const s4DVertex * b,const s4DVertex * c)355 void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c )
356 {
357 	// sort on height, y
358 	if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
359 	if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c);
360 	if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
361 
362 	const f32 ca = c->Pos.y - a->Pos.y;
363 	const f32 ba = b->Pos.y - a->Pos.y;
364 	const f32 cb = c->Pos.y - b->Pos.y;
365 	// calculate delta y of the edges
366 	scan.invDeltaY[0] = core::reciprocal( ca );
367 	scan.invDeltaY[1] = core::reciprocal( ba );
368 	scan.invDeltaY[2] = core::reciprocal( cb );
369 
370 	if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) )
371 		return;
372 
373 	// find if the major edge is left or right aligned
374 	f32 temp[4];
375 
376 	temp[0] = a->Pos.x - c->Pos.x;
377 	temp[1] = -ca;
378 	temp[2] = b->Pos.x - a->Pos.x;
379 	temp[3] = ba;
380 
381 	scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1;
382 	scan.right = 1 - scan.left;
383 
384 	// calculate slopes for the major edge
385 	scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0];
386 	scan.x[0] = a->Pos.x;
387 
388 #ifdef IPOL_Z
389 	scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0];
390 	scan.z[0] = a->Pos.z;
391 #endif
392 
393 #ifdef IPOL_W
394 	scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0];
395 	scan.w[0] = a->Pos.w;
396 #endif
397 
398 #ifdef IPOL_C0
399 	scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0];
400 	scan.c[0][0] = a->Color[0];
401 #endif
402 
403 #ifdef IPOL_T0
404 	scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0];
405 	scan.t[0][0] = a->Tex[0];
406 #endif
407 
408 #ifdef IPOL_T1
409 	scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0];
410 	scan.t[1][0] = a->Tex[1];
411 #endif
412 
413 	// top left fill convention y run
414 	s32 yStart;
415 	s32 yEnd;
416 
417 #ifdef SUBTEXEL
418 	f32 subPixel;
419 #endif
420 
421 	// rasterize upper sub-triangle
422 	if ( (f32) 0.0 != scan.invDeltaY[1]  )
423 	{
424 		// calculate slopes for top edge
425 		scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1];
426 		scan.x[1] = a->Pos.x;
427 
428 #ifdef IPOL_Z
429 		scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1];
430 		scan.z[1] = a->Pos.z;
431 #endif
432 
433 #ifdef IPOL_W
434 		scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1];
435 		scan.w[1] = a->Pos.w;
436 #endif
437 
438 #ifdef IPOL_C0
439 		scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1];
440 		scan.c[0][1] = a->Color[0];
441 #endif
442 
443 #ifdef IPOL_T0
444 		scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1];
445 		scan.t[0][1] = a->Tex[0];
446 #endif
447 
448 #ifdef IPOL_T1
449 		scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1];
450 		scan.t[1][1] = a->Tex[1];
451 #endif
452 
453 		// apply top-left fill convention, top part
454 		yStart = core::ceil32( a->Pos.y );
455 		yEnd = core::ceil32( b->Pos.y ) - 1;
456 
457 #ifdef SUBTEXEL
458 		subPixel = ( (f32) yStart ) - a->Pos.y;
459 
460 		// correct to pixel center
461 		scan.x[0] += scan.slopeX[0] * subPixel;
462 		scan.x[1] += scan.slopeX[1] * subPixel;
463 
464 #ifdef IPOL_Z
465 		scan.z[0] += scan.slopeZ[0] * subPixel;
466 		scan.z[1] += scan.slopeZ[1] * subPixel;
467 #endif
468 
469 #ifdef IPOL_W
470 		scan.w[0] += scan.slopeW[0] * subPixel;
471 		scan.w[1] += scan.slopeW[1] * subPixel;
472 #endif
473 
474 #ifdef IPOL_C0
475 		scan.c[0][0] += scan.slopeC[0][0] * subPixel;
476 		scan.c[0][1] += scan.slopeC[0][1] * subPixel;
477 #endif
478 
479 #ifdef IPOL_T0
480 		scan.t[0][0] += scan.slopeT[0][0] * subPixel;
481 		scan.t[0][1] += scan.slopeT[0][1] * subPixel;
482 #endif
483 
484 #ifdef IPOL_T1
485 		scan.t[1][0] += scan.slopeT[1][0] * subPixel;
486 		scan.t[1][1] += scan.slopeT[1][1] * subPixel;
487 #endif
488 
489 #endif
490 
491 		// rasterize the edge scanlines
492 		for( line.y = yStart; line.y <= yEnd; ++line.y)
493 		{
494 			line.x[scan.left] = scan.x[0];
495 			line.x[scan.right] = scan.x[1];
496 
497 #ifdef IPOL_Z
498 			line.z[scan.left] = scan.z[0];
499 			line.z[scan.right] = scan.z[1];
500 #endif
501 
502 #ifdef IPOL_W
503 			line.w[scan.left] = scan.w[0];
504 			line.w[scan.right] = scan.w[1];
505 #endif
506 
507 #ifdef IPOL_C0
508 			line.c[0][scan.left] = scan.c[0][0];
509 			line.c[0][scan.right] = scan.c[0][1];
510 #endif
511 
512 #ifdef IPOL_T0
513 			line.t[0][scan.left] = scan.t[0][0];
514 			line.t[0][scan.right] = scan.t[0][1];
515 #endif
516 
517 #ifdef IPOL_T1
518 			line.t[1][scan.left] = scan.t[1][0];
519 			line.t[1][scan.right] = scan.t[1][1];
520 #endif
521 
522 			// render a scanline
523 			scanline_bilinear ( );
524 
525 			scan.x[0] += scan.slopeX[0];
526 			scan.x[1] += scan.slopeX[1];
527 
528 #ifdef IPOL_Z
529 			scan.z[0] += scan.slopeZ[0];
530 			scan.z[1] += scan.slopeZ[1];
531 #endif
532 
533 #ifdef IPOL_W
534 			scan.w[0] += scan.slopeW[0];
535 			scan.w[1] += scan.slopeW[1];
536 #endif
537 
538 #ifdef IPOL_C0
539 			scan.c[0][0] += scan.slopeC[0][0];
540 			scan.c[0][1] += scan.slopeC[0][1];
541 #endif
542 
543 #ifdef IPOL_T0
544 			scan.t[0][0] += scan.slopeT[0][0];
545 			scan.t[0][1] += scan.slopeT[0][1];
546 #endif
547 
548 #ifdef IPOL_T1
549 			scan.t[1][0] += scan.slopeT[1][0];
550 			scan.t[1][1] += scan.slopeT[1][1];
551 #endif
552 
553 		}
554 	}
555 
556 	// rasterize lower sub-triangle
557 	if ( (f32) 0.0 != scan.invDeltaY[2] )
558 	{
559 		// advance to middle point
560 		if( (f32) 0.0 != scan.invDeltaY[1] )
561 		{
562 			temp[0] = b->Pos.y - a->Pos.y;	// dy
563 
564 			scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0];
565 #ifdef IPOL_Z
566 			scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0];
567 #endif
568 #ifdef IPOL_W
569 			scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0];
570 #endif
571 #ifdef IPOL_C0
572 			scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0];
573 #endif
574 #ifdef IPOL_T0
575 			scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0];
576 #endif
577 #ifdef IPOL_T1
578 			scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0];
579 #endif
580 
581 		}
582 
583 		// calculate slopes for bottom edge
584 		scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2];
585 		scan.x[1] = b->Pos.x;
586 
587 #ifdef IPOL_Z
588 		scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2];
589 		scan.z[1] = b->Pos.z;
590 #endif
591 
592 #ifdef IPOL_W
593 		scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2];
594 		scan.w[1] = b->Pos.w;
595 #endif
596 
597 #ifdef IPOL_C0
598 		scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2];
599 		scan.c[0][1] = b->Color[0];
600 #endif
601 
602 #ifdef IPOL_T0
603 		scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2];
604 		scan.t[0][1] = b->Tex[0];
605 #endif
606 
607 #ifdef IPOL_T1
608 		scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2];
609 		scan.t[1][1] = b->Tex[1];
610 #endif
611 
612 		// apply top-left fill convention, top part
613 		yStart = core::ceil32( b->Pos.y );
614 		yEnd = core::ceil32( c->Pos.y ) - 1;
615 
616 #ifdef SUBTEXEL
617 
618 		subPixel = ( (f32) yStart ) - b->Pos.y;
619 
620 		// correct to pixel center
621 		scan.x[0] += scan.slopeX[0] * subPixel;
622 		scan.x[1] += scan.slopeX[1] * subPixel;
623 
624 #ifdef IPOL_Z
625 		scan.z[0] += scan.slopeZ[0] * subPixel;
626 		scan.z[1] += scan.slopeZ[1] * subPixel;
627 #endif
628 
629 #ifdef IPOL_W
630 		scan.w[0] += scan.slopeW[0] * subPixel;
631 		scan.w[1] += scan.slopeW[1] * subPixel;
632 #endif
633 
634 #ifdef IPOL_C0
635 		scan.c[0][0] += scan.slopeC[0][0] * subPixel;
636 		scan.c[0][1] += scan.slopeC[0][1] * subPixel;
637 #endif
638 
639 #ifdef IPOL_T0
640 		scan.t[0][0] += scan.slopeT[0][0] * subPixel;
641 		scan.t[0][1] += scan.slopeT[0][1] * subPixel;
642 #endif
643 
644 #ifdef IPOL_T1
645 		scan.t[1][0] += scan.slopeT[1][0] * subPixel;
646 		scan.t[1][1] += scan.slopeT[1][1] * subPixel;
647 #endif
648 
649 #endif
650 
651 		// rasterize the edge scanlines
652 		for( line.y = yStart; line.y <= yEnd; ++line.y)
653 		{
654 			line.x[scan.left] = scan.x[0];
655 			line.x[scan.right] = scan.x[1];
656 
657 #ifdef IPOL_Z
658 			line.z[scan.left] = scan.z[0];
659 			line.z[scan.right] = scan.z[1];
660 #endif
661 
662 #ifdef IPOL_W
663 			line.w[scan.left] = scan.w[0];
664 			line.w[scan.right] = scan.w[1];
665 #endif
666 
667 #ifdef IPOL_C0
668 			line.c[0][scan.left] = scan.c[0][0];
669 			line.c[0][scan.right] = scan.c[0][1];
670 #endif
671 
672 #ifdef IPOL_T0
673 			line.t[0][scan.left] = scan.t[0][0];
674 			line.t[0][scan.right] = scan.t[0][1];
675 #endif
676 
677 #ifdef IPOL_T1
678 			line.t[1][scan.left] = scan.t[1][0];
679 			line.t[1][scan.right] = scan.t[1][1];
680 #endif
681 
682 			// render a scanline
683 			scanline_bilinear ( );
684 
685 			scan.x[0] += scan.slopeX[0];
686 			scan.x[1] += scan.slopeX[1];
687 
688 #ifdef IPOL_Z
689 			scan.z[0] += scan.slopeZ[0];
690 			scan.z[1] += scan.slopeZ[1];
691 #endif
692 
693 #ifdef IPOL_W
694 			scan.w[0] += scan.slopeW[0];
695 			scan.w[1] += scan.slopeW[1];
696 #endif
697 
698 #ifdef IPOL_C0
699 			scan.c[0][0] += scan.slopeC[0][0];
700 			scan.c[0][1] += scan.slopeC[0][1];
701 #endif
702 
703 #ifdef IPOL_T0
704 			scan.t[0][0] += scan.slopeT[0][0];
705 			scan.t[0][1] += scan.slopeT[0][1];
706 #endif
707 
708 #ifdef IPOL_T1
709 			scan.t[1][0] += scan.slopeT[1][0];
710 			scan.t[1][1] += scan.slopeT[1][1];
711 #endif
712 
713 		}
714 	}
715 
716 }
717 
718 
719 } // end namespace video
720 } // end namespace irr
721 
722 #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
723 
724 namespace irr
725 {
726 namespace video
727 {
728 
729 
730 //! creates a flat triangle renderer
createTRTextureGouraudAlpha(CBurningVideoDriver * driver)731 IBurningShader* createTRTextureGouraudAlpha(CBurningVideoDriver* driver)
732 {
733 	#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
734 	return new CTRTextureGouraudAlpha2(driver);
735 	#else
736 	return 0;
737 	#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
738 }
739 
740 
741 } // end namespace video
742 } // end namespace irr
743 
744 
745