1
// Copyright (C) 2002-2011 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
5
#include "IrrCompileConfig.h"
6
#include "IBurningShader.h"
8
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
10
// compile flag for this file
40
// apply global override
41
#ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
45
#ifndef SOFTWARE_DRIVER_2_SUBTEXEL
49
#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR
53
#if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER )
54
#ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
77
class CTRTextureVertexAlpha2 : public IBurningShader
82
CTRTextureVertexAlpha2(CBurningVideoDriver* driver);
84
//! draws an indexed triangle list
85
virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c );
89
void scanline_bilinear ();
90
sScanConvertData scan;
96
CTRTextureVertexAlpha2::CTRTextureVertexAlpha2(CBurningVideoDriver* driver)
97
: IBurningShader(driver)
100
setDebugName("CTRTextureVertexAlpha2");
108
void CTRTextureVertexAlpha2::scanline_bilinear ( )
135
sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES];
138
// apply top-left fill-convention, left
139
xStart = core::ceil32( line.x[0] );
140
xEnd = core::ceil32( line.x[1] ) - 1;
148
const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] );
151
slopeZ = (line.z[1] - line.z[0]) * invDeltaX;
154
slopeW = (line.w[1] - line.w[0]) * invDeltaX;
157
slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX;
160
slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX;
163
slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX;
167
subPixel = ( (f32) xStart ) - line.x[0];
169
line.z[0] += slopeZ * subPixel;
172
line.w[0] += slopeW * subPixel;
175
line.c[0][0] += slopeC * subPixel;
178
line.t[0][0] += slopeT[0] * subPixel;
181
line.t[1][0] += slopeT[1] * subPixel;
185
dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
188
z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
196
//#define __TEST_THIS
204
tFixPoint r0, g0, b0;
205
tFixPoint r1, g1, b1;
206
tFixPoint r2, g2, b2;
215
for ( s32 i = 0; i <= dx; ++i )
218
if ( line.z[0] < z[i] )
221
if ( line.w[0] >= z[i] )
227
inversew = fix_inverse32 ( line.w[0] );
229
dst[i] = PixelAdd32 (
231
getTexel_plain ( &IT[0], tofix ( line.t[0][0].x,inversew),
232
tofix ( line.t[0][0].y,inversew) )
238
inversew = fix_inverse32 ( line.w[0] );
240
tx0 = tofix ( line.t[0][0].x,inversew);
241
ty0 = tofix ( line.t[0][0].y,inversew);
244
a3 = tofix ( line.c[0][0].y,inversew );
248
tx0 = tofix ( line.t[0][0].x );
249
ty0 = tofix ( line.t[0][0].y );
252
a3 = tofix ( line.c[0][0].y );
258
getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 );
259
color_to_fix ( r1, g1, b1, dst[i] );
262
r2 = clampfix_maxcolor ( r1 + imulFix ( r0, a3 ) );
263
g2 = clampfix_maxcolor ( g1 + imulFix ( g0, a3 ) );
264
b2 = clampfix_maxcolor ( b1 + imulFix ( b0, a3 ) );
266
r2 = clampfix_maxcolor ( r1 + r0 );
267
g2 = clampfix_maxcolor ( g1 + g0 );
268
b2 = clampfix_maxcolor ( b1 + b0 );
271
dst[i] = fix_to_color ( r2, g2, b2 );
289
line.c[0][0] += slopeC;
292
line.t[0][0] += slopeT[0];
295
line.t[1][0] += slopeT[1];
301
void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c )
304
if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
305
if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c);
306
if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
308
const f32 ca = c->Pos.y - a->Pos.y;
309
const f32 ba = b->Pos.y - a->Pos.y;
310
const f32 cb = c->Pos.y - b->Pos.y;
311
// calculate delta y of the edges
312
scan.invDeltaY[0] = core::reciprocal( ca );
313
scan.invDeltaY[1] = core::reciprocal( ba );
314
scan.invDeltaY[2] = core::reciprocal( cb );
316
if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) )
319
// find if the major edge is left or right aligned
322
temp[0] = a->Pos.x - c->Pos.x;
324
temp[2] = b->Pos.x - a->Pos.x;
327
scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1;
328
scan.right = 1 - scan.left;
330
// calculate slopes for the major edge
331
scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0];
332
scan.x[0] = a->Pos.x;
335
scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0];
336
scan.z[0] = a->Pos.z;
340
scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0];
341
scan.w[0] = a->Pos.w;
345
scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0];
346
scan.c[0][0] = a->Color[0];
350
scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0];
351
scan.t[0][0] = a->Tex[0];
355
scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0];
356
scan.t[1][0] = a->Tex[1];
359
// top left fill convention y run
367
// rasterize upper sub-triangle
368
if ( (f32) 0.0 != scan.invDeltaY[1] )
370
// calculate slopes for top edge
371
scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1];
372
scan.x[1] = a->Pos.x;
375
scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1];
376
scan.z[1] = a->Pos.z;
380
scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1];
381
scan.w[1] = a->Pos.w;
385
scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1];
386
scan.c[0][1] = a->Color[0];
390
scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1];
391
scan.t[0][1] = a->Tex[0];
395
scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1];
396
scan.t[1][1] = a->Tex[1];
399
// apply top-left fill convention, top part
400
yStart = core::ceil32( a->Pos.y );
401
yEnd = core::ceil32( b->Pos.y ) - 1;
404
subPixel = ( (f32) yStart ) - a->Pos.y;
406
// correct to pixel center
407
scan.x[0] += scan.slopeX[0] * subPixel;
408
scan.x[1] += scan.slopeX[1] * subPixel;
411
scan.z[0] += scan.slopeZ[0] * subPixel;
412
scan.z[1] += scan.slopeZ[1] * subPixel;
416
scan.w[0] += scan.slopeW[0] * subPixel;
417
scan.w[1] += scan.slopeW[1] * subPixel;
421
scan.c[0][0] += scan.slopeC[0][0] * subPixel;
422
scan.c[0][1] += scan.slopeC[0][1] * subPixel;
426
scan.t[0][0] += scan.slopeT[0][0] * subPixel;
427
scan.t[0][1] += scan.slopeT[0][1] * subPixel;
431
scan.t[1][0] += scan.slopeT[1][0] * subPixel;
432
scan.t[1][1] += scan.slopeT[1][1] * subPixel;
437
// rasterize the edge scanlines
438
for( line.y = yStart; line.y <= yEnd; ++line.y)
440
line.x[scan.left] = scan.x[0];
441
line.x[scan.right] = scan.x[1];
444
line.z[scan.left] = scan.z[0];
445
line.z[scan.right] = scan.z[1];
449
line.w[scan.left] = scan.w[0];
450
line.w[scan.right] = scan.w[1];
454
line.c[0][scan.left] = scan.c[0][0];
455
line.c[0][scan.right] = scan.c[0][1];
459
line.t[0][scan.left] = scan.t[0][0];
460
line.t[0][scan.right] = scan.t[0][1];
464
line.t[1][scan.left] = scan.t[1][0];
465
line.t[1][scan.right] = scan.t[1][1];
469
scanline_bilinear ();
471
scan.x[0] += scan.slopeX[0];
472
scan.x[1] += scan.slopeX[1];
475
scan.z[0] += scan.slopeZ[0];
476
scan.z[1] += scan.slopeZ[1];
480
scan.w[0] += scan.slopeW[0];
481
scan.w[1] += scan.slopeW[1];
485
scan.c[0][0] += scan.slopeC[0][0];
486
scan.c[0][1] += scan.slopeC[0][1];
490
scan.t[0][0] += scan.slopeT[0][0];
491
scan.t[0][1] += scan.slopeT[0][1];
495
scan.t[1][0] += scan.slopeT[1][0];
496
scan.t[1][1] += scan.slopeT[1][1];
502
// rasterize lower sub-triangle
503
if ( (f32) 0.0 != scan.invDeltaY[2] )
505
// advance to middle point
506
if( (f32) 0.0 != scan.invDeltaY[1] )
508
temp[0] = b->Pos.y - a->Pos.y; // dy
510
scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0];
512
scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0];
515
scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0];
518
scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0];
521
scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0];
524
scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0];
529
// calculate slopes for bottom edge
530
scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2];
531
scan.x[1] = b->Pos.x;
534
scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2];
535
scan.z[1] = b->Pos.z;
539
scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2];
540
scan.w[1] = b->Pos.w;
544
scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2];
545
scan.c[0][1] = b->Color[0];
549
scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2];
550
scan.t[0][1] = b->Tex[0];
554
scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2];
555
scan.t[1][1] = b->Tex[1];
558
// apply top-left fill convention, top part
559
yStart = core::ceil32( b->Pos.y );
560
yEnd = core::ceil32( c->Pos.y ) - 1;
564
subPixel = ( (f32) yStart ) - b->Pos.y;
566
// correct to pixel center
567
scan.x[0] += scan.slopeX[0] * subPixel;
568
scan.x[1] += scan.slopeX[1] * subPixel;
571
scan.z[0] += scan.slopeZ[0] * subPixel;
572
scan.z[1] += scan.slopeZ[1] * subPixel;
576
scan.w[0] += scan.slopeW[0] * subPixel;
577
scan.w[1] += scan.slopeW[1] * subPixel;
581
scan.c[0][0] += scan.slopeC[0][0] * subPixel;
582
scan.c[0][1] += scan.slopeC[0][1] * subPixel;
586
scan.t[0][0] += scan.slopeT[0][0] * subPixel;
587
scan.t[0][1] += scan.slopeT[0][1] * subPixel;
591
scan.t[1][0] += scan.slopeT[1][0] * subPixel;
592
scan.t[1][1] += scan.slopeT[1][1] * subPixel;
597
// rasterize the edge scanlines
598
for( line.y = yStart; line.y <= yEnd; ++line.y)
600
line.x[scan.left] = scan.x[0];
601
line.x[scan.right] = scan.x[1];
604
line.z[scan.left] = scan.z[0];
605
line.z[scan.right] = scan.z[1];
609
line.w[scan.left] = scan.w[0];
610
line.w[scan.right] = scan.w[1];
614
line.c[0][scan.left] = scan.c[0][0];
615
line.c[0][scan.right] = scan.c[0][1];
619
line.t[0][scan.left] = scan.t[0][0];
620
line.t[0][scan.right] = scan.t[0][1];
624
line.t[1][scan.left] = scan.t[1][0];
625
line.t[1][scan.right] = scan.t[1][1];
629
scanline_bilinear ();
631
scan.x[0] += scan.slopeX[0];
632
scan.x[1] += scan.slopeX[1];
635
scan.z[0] += scan.slopeZ[0];
636
scan.z[1] += scan.slopeZ[1];
640
scan.w[0] += scan.slopeW[0];
641
scan.w[1] += scan.slopeW[1];
645
scan.c[0][0] += scan.slopeC[0][0];
646
scan.c[0][1] += scan.slopeC[0][1];
650
scan.t[0][0] += scan.slopeT[0][0];
651
scan.t[0][1] += scan.slopeT[0][1];
655
scan.t[1][0] += scan.slopeT[1][0];
656
scan.t[1][1] += scan.slopeT[1][1];
665
} // end namespace video
666
} // end namespace irr
668
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
675
//! creates a flat triangle renderer
676
IBurningShader* createTriangleRendererTextureVertexAlpha2(CBurningVideoDriver* driver)
678
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
679
return new CTRTextureVertexAlpha2(driver);
682
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
686
} // end namespace video
687
} // end namespace irr