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
41
// apply global override
42
#ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
46
#ifndef SOFTWARE_DRIVER_2_SUBTEXEL
50
#ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR
54
#if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER )
55
#ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
79
class CTRStencilShadow : public IBurningShader
84
CTRStencilShadow(CBurningVideoDriver* driver);
86
//! draws an indexed triangle list
87
virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c );
88
virtual void setParam ( u32 index, f32 value);
92
typedef void (CTRStencilShadow::*tFragmentShader) ();
93
void fragment_zfail_decr ();
94
void fragment_zfail_incr ();
96
tFragmentShader fragmentShader;
98
sScanConvertData scan;
104
CTRStencilShadow::CTRStencilShadow(CBurningVideoDriver* driver)
105
: IBurningShader(driver)
108
setDebugName("CTRStencilShadow");
115
void CTRStencilShadow::setParam ( u32 index, f32 value)
117
u32 val = (u32) value;
119
// glStencilOp (fail,zfail,zpass
120
if ( index == 1 && val == 1 )
122
fragmentShader = &CTRStencilShadow::fragment_zfail_incr;
125
if ( index == 1 && val == 2 )
127
fragmentShader = &CTRStencilShadow::fragment_zfail_decr;
133
void CTRStencilShadow::fragment_zfail_decr ()
162
sVec4 slopeC[MATERIAL_MAX_COLORS];
165
sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES];
168
sVec3 slopeL[BURNING_MATERIAL_MAX_TANGENT];
171
// apply top-left fill-convention, left
172
xStart = core::ceil32( line.x[0] );
173
xEnd = core::ceil32( line.x[1] ) - 1;
181
const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] );
184
slopeZ = (line.z[1] - line.z[0]) * invDeltaX;
187
slopeW = (line.w[1] - line.w[0]) * invDeltaX;
190
slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX;
193
slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX;
196
slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX;
199
slopeT[2] = (line.t[2][1] - line.t[2][0]) * invDeltaX;
202
slopeL[0] = (line.l[0][1] - line.l[0][0]) * invDeltaX;
206
subPixel = ( (f32) xStart ) - line.x[0];
208
line.z[0] += slopeZ * subPixel;
211
line.w[0] += slopeW * subPixel;
214
line.c[0][0] += slopeC[0] * subPixel;
217
line.t[0][0] += slopeT[0] * subPixel;
220
line.t[1][0] += slopeT[1] * subPixel;
223
line.t[2][0] += slopeT[2] * subPixel;
226
line.l[0][0] += slopeL[0] * subPixel;
230
//dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
233
z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
237
stencil = (u32*) Stencil->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
247
tFixPoint r3, g3, b3;
250
for ( s32 i = 0; i <= dx; i++ )
253
if ( line.z[0] < z[i] )
256
if ( line.w[0] < z[i] )
270
line.c[0][0] += slopeC[0];
273
line.t[0][0] += slopeT[0];
276
line.t[1][0] += slopeT[1];
279
line.t[2][0] += slopeT[2];
282
line.l[0][0] += slopeL[0];
289
void CTRStencilShadow::fragment_zfail_incr()
319
sVec4 slopeC[MATERIAL_MAX_COLORS];
322
sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES];
325
sVec3 slopeL[BURNING_MATERIAL_MAX_TANGENT];
328
// apply top-left fill-convention, left
329
xStart = core::ceil32( line.x[0] );
330
xEnd = core::ceil32( line.x[1] ) - 1;
338
const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] );
341
slopeZ = (line.z[1] - line.z[0]) * invDeltaX;
344
slopeW = (line.w[1] - line.w[0]) * invDeltaX;
347
slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX;
350
slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX;
353
slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX;
356
slopeT[2] = (line.t[2][1] - line.t[2][0]) * invDeltaX;
359
slopeL[0] = (line.l[0][1] - line.l[0][0]) * invDeltaX;
363
subPixel = ( (f32) xStart ) - line.x[0];
365
line.z[0] += slopeZ * subPixel;
368
line.w[0] += slopeW * subPixel;
371
line.c[0][0] += slopeC[0] * subPixel;
374
line.t[0][0] += slopeT[0] * subPixel;
377
line.t[1][0] += slopeT[1] * subPixel;
380
line.t[2][0] += slopeT[2] * subPixel;
383
line.l[0][0] += slopeL[0] * subPixel;
387
//dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
390
z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
394
stencil = (u32*) Stencil->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
402
tFixPoint r3, g3, b3;
405
for ( s32 i = 0; i <= dx; i++ )
408
if ( line.z[0] < z[i] )
411
if ( line.w[0] < z[i] )
425
line.c[0][0] += slopeC[0];
428
line.t[0][0] += slopeT[0];
431
line.t[1][0] += slopeT[1];
434
line.t[2][0] += slopeT[2];
437
line.l[0][0] += slopeL[0];
442
void CTRStencilShadow::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c )
445
if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
446
if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c);
447
if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
449
const f32 ca = c->Pos.y - a->Pos.y;
450
const f32 ba = b->Pos.y - a->Pos.y;
451
const f32 cb = c->Pos.y - b->Pos.y;
452
// calculate delta y of the edges
453
scan.invDeltaY[0] = core::reciprocal( ca );
454
scan.invDeltaY[1] = core::reciprocal( ba );
455
scan.invDeltaY[2] = core::reciprocal( cb );
457
if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) )
460
// find if the major edge is left or right aligned
463
temp[0] = a->Pos.x - c->Pos.x;
465
temp[2] = b->Pos.x - a->Pos.x;
468
scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1;
469
scan.right = 1 - scan.left;
471
// calculate slopes for the major edge
472
scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0];
473
scan.x[0] = a->Pos.x;
476
scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0];
477
scan.z[0] = a->Pos.z;
481
scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0];
482
scan.w[0] = a->Pos.w;
486
scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0];
487
scan.c[0][0] = a->Color[0];
491
scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0];
492
scan.t[0][0] = a->Tex[0];
496
scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0];
497
scan.t[1][0] = a->Tex[1];
501
scan.slopeT[2][0] = (c->Tex[2] - a->Tex[2]) * scan.invDeltaY[0];
502
scan.t[2][0] = a->Tex[2];
506
scan.slopeL[0][0] = (c->LightTangent[0] - a->LightTangent[0]) * scan.invDeltaY[0];
507
scan.l[0][0] = a->LightTangent[0];
510
// top left fill convention y run
518
// rasterize upper sub-triangle
519
//if ( (f32) 0.0 != scan.invDeltaY[1] )
520
if ( F32_GREATER_0 ( scan.invDeltaY[1] ) )
522
// calculate slopes for top edge
523
scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1];
524
scan.x[1] = a->Pos.x;
527
scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1];
528
scan.z[1] = a->Pos.z;
532
scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1];
533
scan.w[1] = a->Pos.w;
537
scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1];
538
scan.c[0][1] = a->Color[0];
542
scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1];
543
scan.t[0][1] = a->Tex[0];
547
scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1];
548
scan.t[1][1] = a->Tex[1];
552
scan.slopeT[2][1] = (b->Tex[2] - a->Tex[2]) * scan.invDeltaY[1];
553
scan.t[2][1] = a->Tex[2];
557
scan.slopeL[0][1] = (b->LightTangent[0] - a->LightTangent[0]) * scan.invDeltaY[1];
558
scan.l[0][1] = a->LightTangent[0];
561
// apply top-left fill convention, top part
562
yStart = core::ceil32( a->Pos.y );
563
yEnd = core::ceil32( b->Pos.y ) - 1;
566
subPixel = ( (f32) yStart ) - a->Pos.y;
568
// correct to pixel center
569
scan.x[0] += scan.slopeX[0] * subPixel;
570
scan.x[1] += scan.slopeX[1] * subPixel;
573
scan.z[0] += scan.slopeZ[0] * subPixel;
574
scan.z[1] += scan.slopeZ[1] * subPixel;
578
scan.w[0] += scan.slopeW[0] * subPixel;
579
scan.w[1] += scan.slopeW[1] * subPixel;
583
scan.c[0][0] += scan.slopeC[0][0] * subPixel;
584
scan.c[0][1] += scan.slopeC[0][1] * subPixel;
588
scan.t[0][0] += scan.slopeT[0][0] * subPixel;
589
scan.t[0][1] += scan.slopeT[0][1] * subPixel;
593
scan.t[1][0] += scan.slopeT[1][0] * subPixel;
594
scan.t[1][1] += scan.slopeT[1][1] * subPixel;
598
scan.t[2][0] += scan.slopeT[2][0] * subPixel;
599
scan.t[2][1] += scan.slopeT[2][1] * subPixel;
603
scan.l[0][0] += scan.slopeL[0][0] * subPixel;
604
scan.l[0][1] += scan.slopeL[0][1] * subPixel;
609
// rasterize the edge scanlines
610
for( line.y = yStart; line.y <= yEnd; ++line.y)
612
line.x[scan.left] = scan.x[0];
613
line.x[scan.right] = scan.x[1];
616
line.z[scan.left] = scan.z[0];
617
line.z[scan.right] = scan.z[1];
621
line.w[scan.left] = scan.w[0];
622
line.w[scan.right] = scan.w[1];
626
line.c[0][scan.left] = scan.c[0][0];
627
line.c[0][scan.right] = scan.c[0][1];
631
line.t[0][scan.left] = scan.t[0][0];
632
line.t[0][scan.right] = scan.t[0][1];
636
line.t[1][scan.left] = scan.t[1][0];
637
line.t[1][scan.right] = scan.t[1][1];
641
line.t[2][scan.left] = scan.t[2][0];
642
line.t[2][scan.right] = scan.t[2][1];
646
line.l[0][scan.left] = scan.l[0][0];
647
line.l[0][scan.right] = scan.l[0][1];
651
(this->*fragmentShader) ();
653
scan.x[0] += scan.slopeX[0];
654
scan.x[1] += scan.slopeX[1];
657
scan.z[0] += scan.slopeZ[0];
658
scan.z[1] += scan.slopeZ[1];
662
scan.w[0] += scan.slopeW[0];
663
scan.w[1] += scan.slopeW[1];
667
scan.c[0][0] += scan.slopeC[0][0];
668
scan.c[0][1] += scan.slopeC[0][1];
672
scan.t[0][0] += scan.slopeT[0][0];
673
scan.t[0][1] += scan.slopeT[0][1];
677
scan.t[1][0] += scan.slopeT[1][0];
678
scan.t[1][1] += scan.slopeT[1][1];
682
scan.t[2][0] += scan.slopeT[2][0];
683
scan.t[2][1] += scan.slopeT[2][1];
687
scan.l[0][0] += scan.slopeL[0][0];
688
scan.l[0][1] += scan.slopeL[0][1];
694
// rasterize lower sub-triangle
695
//if ( (f32) 0.0 != scan.invDeltaY[2] )
696
if ( F32_GREATER_0 ( scan.invDeltaY[2] ) )
698
// advance to middle point
699
//if( (f32) 0.0 != scan.invDeltaY[1] )
700
if ( F32_GREATER_0 ( scan.invDeltaY[1] ) )
702
temp[0] = b->Pos.y - a->Pos.y; // dy
704
scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0];
706
scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0];
709
scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0];
712
scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0];
715
scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0];
718
scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0];
721
scan.t[2][0] = a->Tex[2] + scan.slopeT[2][0] * temp[0];
724
scan.l[0][0] = a->LightTangent[0] + scan.slopeL[0][0] * temp[0];
729
// calculate slopes for bottom edge
730
scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2];
731
scan.x[1] = b->Pos.x;
734
scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2];
735
scan.z[1] = b->Pos.z;
739
scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2];
740
scan.w[1] = b->Pos.w;
744
scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2];
745
scan.c[0][1] = b->Color[0];
749
scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2];
750
scan.t[0][1] = b->Tex[0];
754
scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2];
755
scan.t[1][1] = b->Tex[1];
759
scan.slopeT[2][1] = (c->Tex[2] - b->Tex[2]) * scan.invDeltaY[2];
760
scan.t[2][1] = b->Tex[2];
764
scan.slopeL[0][1] = (c->LightTangent[0] - b->LightTangent[0]) * scan.invDeltaY[2];
765
scan.l[0][1] = b->LightTangent[0];
768
// apply top-left fill convention, top part
769
yStart = core::ceil32( b->Pos.y );
770
yEnd = core::ceil32( c->Pos.y ) - 1;
774
subPixel = ( (f32) yStart ) - b->Pos.y;
776
// correct to pixel center
777
scan.x[0] += scan.slopeX[0] * subPixel;
778
scan.x[1] += scan.slopeX[1] * subPixel;
781
scan.z[0] += scan.slopeZ[0] * subPixel;
782
scan.z[1] += scan.slopeZ[1] * subPixel;
786
scan.w[0] += scan.slopeW[0] * subPixel;
787
scan.w[1] += scan.slopeW[1] * subPixel;
791
scan.c[0][0] += scan.slopeC[0][0] * subPixel;
792
scan.c[0][1] += scan.slopeC[0][1] * subPixel;
796
scan.t[0][0] += scan.slopeT[0][0] * subPixel;
797
scan.t[0][1] += scan.slopeT[0][1] * subPixel;
801
scan.t[1][0] += scan.slopeT[1][0] * subPixel;
802
scan.t[1][1] += scan.slopeT[1][1] * subPixel;
806
scan.t[2][0] += scan.slopeT[2][0] * subPixel;
807
scan.t[2][1] += scan.slopeT[2][1] * subPixel;
811
scan.l[0][0] += scan.slopeL[0][0] * subPixel;
812
scan.l[0][1] += scan.slopeL[0][1] * subPixel;
817
// rasterize the edge scanlines
818
for( line.y = yStart; line.y <= yEnd; ++line.y)
820
line.x[scan.left] = scan.x[0];
821
line.x[scan.right] = scan.x[1];
824
line.z[scan.left] = scan.z[0];
825
line.z[scan.right] = scan.z[1];
829
line.w[scan.left] = scan.w[0];
830
line.w[scan.right] = scan.w[1];
834
line.c[0][scan.left] = scan.c[0][0];
835
line.c[0][scan.right] = scan.c[0][1];
839
line.t[0][scan.left] = scan.t[0][0];
840
line.t[0][scan.right] = scan.t[0][1];
844
line.t[1][scan.left] = scan.t[1][0];
845
line.t[1][scan.right] = scan.t[1][1];
849
line.t[2][scan.left] = scan.t[2][0];
850
line.t[2][scan.right] = scan.t[2][1];
854
line.l[0][scan.left] = scan.l[0][0];
855
line.l[0][scan.right] = scan.l[0][1];
859
(this->*fragmentShader) ();
861
scan.x[0] += scan.slopeX[0];
862
scan.x[1] += scan.slopeX[1];
865
scan.z[0] += scan.slopeZ[0];
866
scan.z[1] += scan.slopeZ[1];
870
scan.w[0] += scan.slopeW[0];
871
scan.w[1] += scan.slopeW[1];
875
scan.c[0][0] += scan.slopeC[0][0];
876
scan.c[0][1] += scan.slopeC[0][1];
880
scan.t[0][0] += scan.slopeT[0][0];
881
scan.t[0][1] += scan.slopeT[0][1];
885
scan.t[1][0] += scan.slopeT[1][0];
886
scan.t[1][1] += scan.slopeT[1][1];
889
scan.t[2][0] += scan.slopeT[2][0];
890
scan.t[2][1] += scan.slopeT[2][1];
894
scan.l[0][0] += scan.slopeL[0][0];
895
scan.l[0][1] += scan.slopeL[0][1];
904
} // end namespace video
905
} // end namespace irr
907
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
915
//! creates a triangle renderer
916
IBurningShader* createTRStencilShadow(CBurningVideoDriver* driver)
918
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
919
return new CTRStencilShadow(driver);
922
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
926
} // end namespace video
927
} // end namespace irr