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
54
#if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER )
55
#ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
79
class CTRTextureDetailMap2 : public IBurningShader
84
CTRTextureDetailMap2(CBurningVideoDriver* driver);
86
//! draws an indexed triangle list
87
virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c );
91
void scanline_bilinear ();
92
sScanConvertData scan;
98
CTRTextureDetailMap2::CTRTextureDetailMap2(CBurningVideoDriver* driver)
99
: IBurningShader(driver)
102
setDebugName("CTRTextureDetailMap2");
110
void CTRTextureDetailMap2::scanline_bilinear ()
137
sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES];
140
// apply top-left fill-convention, left
141
xStart = core::ceil32( line.x[0] );
142
xEnd = core::ceil32( line.x[1] ) - 1;
150
const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] );
153
slopeZ = (line.z[1] - line.z[0]) * invDeltaX;
156
slopeW = (line.w[1] - line.w[0]) * invDeltaX;
159
slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX;
162
slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX;
165
slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX;
169
subPixel = ( (f32) xStart ) - line.x[0];
171
line.z[0] += slopeZ * subPixel;
174
line.w[0] += slopeW * subPixel;
177
line.c[0][0] += slopeC * subPixel;
180
line.t[0][0] += slopeT[0] * subPixel;
183
line.t[1][0] += slopeT[1] * subPixel;
187
dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
190
z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
201
tFixPoint r0, g0, b0;
202
tFixPoint r1, g1, b1;
203
tFixPoint r2, g2, b2;
206
for ( s32 i = 0; i <= dx; ++i )
209
if ( line.z[0] < z[i] )
212
if ( line.w[0] >= z[i] )
217
inversew = fix_inverse32 ( line.w[0] );
219
tx0 = tofix ( line.t[0][0].x,inversew);
220
ty0 = tofix ( line.t[0][0].y,inversew);
221
tx1 = tofix ( line.t[1][0].x,inversew);
222
ty1 = tofix ( line.t[1][0].y,inversew);
225
tx0 = tofix ( line.t[0][0].x );
226
ty0 = tofix ( line.t[0][0].y );
227
tx1 = tofix ( line.t[1][0].x );
228
ty1 = tofix ( line.t[1][0].y );
230
getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 );
231
getSample_texture ( r1, g1, b1, &IT[1], tx1,ty1 );
234
r1 += -FIX_POINT_HALF_COLOR;
235
g1 += -FIX_POINT_HALF_COLOR;
236
b1 += -FIX_POINT_HALF_COLOR;
238
r2 = clampfix_mincolor ( clampfix_maxcolor ( r0 + r1 ) );
239
g2 = clampfix_mincolor ( clampfix_maxcolor ( g0 + g1 ) );
240
b2 = clampfix_mincolor ( clampfix_maxcolor ( b0 + b1 ) );
242
dst[i] = fix_to_color ( r2, g2, b2 );
260
line.c[0][0] += slopeC;
263
line.t[0][0] += slopeT[0];
266
line.t[1][0] += slopeT[1];
272
void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c )
275
if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
276
if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c);
277
if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
279
const f32 ca = c->Pos.y - a->Pos.y;
280
const f32 ba = b->Pos.y - a->Pos.y;
281
const f32 cb = c->Pos.y - b->Pos.y;
282
// calculate delta y of the edges
283
scan.invDeltaY[0] = core::reciprocal( ca );
284
scan.invDeltaY[1] = core::reciprocal( ba );
285
scan.invDeltaY[2] = core::reciprocal( cb );
287
if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) )
290
// find if the major edge is left or right aligned
293
temp[0] = a->Pos.x - c->Pos.x;
295
temp[2] = b->Pos.x - a->Pos.x;
298
scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1;
299
scan.right = 1 - scan.left;
301
// calculate slopes for the major edge
302
scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0];
303
scan.x[0] = a->Pos.x;
306
scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0];
307
scan.z[0] = a->Pos.z;
311
scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0];
312
scan.w[0] = a->Pos.w;
316
scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0];
317
scan.c[0][0] = a->Color[0];
321
scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0];
322
scan.t[0][0] = a->Tex[0];
326
scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0];
327
scan.t[1][0] = a->Tex[1];
330
// top left fill convention y run
338
// rasterize upper sub-triangle
339
if ( (f32) 0.0 != scan.invDeltaY[1] )
341
// calculate slopes for top edge
342
scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1];
343
scan.x[1] = a->Pos.x;
346
scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1];
347
scan.z[1] = a->Pos.z;
351
scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1];
352
scan.w[1] = a->Pos.w;
356
scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1];
357
scan.c[0][1] = a->Color[0];
361
scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1];
362
scan.t[0][1] = a->Tex[0];
366
scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1];
367
scan.t[1][1] = a->Tex[1];
370
// apply top-left fill convention, top part
371
yStart = core::ceil32( a->Pos.y );
372
yEnd = core::ceil32( b->Pos.y ) - 1;
375
subPixel = ( (f32) yStart ) - a->Pos.y;
377
// correct to pixel center
378
scan.x[0] += scan.slopeX[0] * subPixel;
379
scan.x[1] += scan.slopeX[1] * subPixel;
382
scan.z[0] += scan.slopeZ[0] * subPixel;
383
scan.z[1] += scan.slopeZ[1] * subPixel;
387
scan.w[0] += scan.slopeW[0] * subPixel;
388
scan.w[1] += scan.slopeW[1] * subPixel;
392
scan.c[0][0] += scan.slopeC[0][0] * subPixel;
393
scan.c[0][1] += scan.slopeC[0][1] * subPixel;
397
scan.t[0][0] += scan.slopeT[0][0] * subPixel;
398
scan.t[0][1] += scan.slopeT[0][1] * subPixel;
402
scan.t[1][0] += scan.slopeT[1][0] * subPixel;
403
scan.t[1][1] += scan.slopeT[1][1] * subPixel;
408
// rasterize the edge scanlines
409
for( line.y = yStart; line.y <= yEnd; ++line.y)
411
line.x[scan.left] = scan.x[0];
412
line.x[scan.right] = scan.x[1];
415
line.z[scan.left] = scan.z[0];
416
line.z[scan.right] = scan.z[1];
420
line.w[scan.left] = scan.w[0];
421
line.w[scan.right] = scan.w[1];
425
line.c[0][scan.left] = scan.c[0][0];
426
line.c[0][scan.right] = scan.c[0][1];
430
line.t[0][scan.left] = scan.t[0][0];
431
line.t[0][scan.right] = scan.t[0][1];
435
line.t[1][scan.left] = scan.t[1][0];
436
line.t[1][scan.right] = scan.t[1][1];
440
scanline_bilinear ();
442
scan.x[0] += scan.slopeX[0];
443
scan.x[1] += scan.slopeX[1];
446
scan.z[0] += scan.slopeZ[0];
447
scan.z[1] += scan.slopeZ[1];
451
scan.w[0] += scan.slopeW[0];
452
scan.w[1] += scan.slopeW[1];
456
scan.c[0][0] += scan.slopeC[0][0];
457
scan.c[0][1] += scan.slopeC[0][1];
461
scan.t[0][0] += scan.slopeT[0][0];
462
scan.t[0][1] += scan.slopeT[0][1];
466
scan.t[1][0] += scan.slopeT[1][0];
467
scan.t[1][1] += scan.slopeT[1][1];
473
// rasterize lower sub-triangle
474
if ( (f32) 0.0 != scan.invDeltaY[2] )
476
// advance to middle point
477
if( (f32) 0.0 != scan.invDeltaY[1] )
479
temp[0] = b->Pos.y - a->Pos.y; // dy
481
scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0];
483
scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0];
486
scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0];
489
scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0];
492
scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0];
495
scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0];
500
// calculate slopes for bottom edge
501
scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2];
502
scan.x[1] = b->Pos.x;
505
scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2];
506
scan.z[1] = b->Pos.z;
510
scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2];
511
scan.w[1] = b->Pos.w;
515
scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2];
516
scan.c[0][1] = b->Color[0];
520
scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2];
521
scan.t[0][1] = b->Tex[0];
525
scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2];
526
scan.t[1][1] = b->Tex[1];
529
// apply top-left fill convention, top part
530
yStart = core::ceil32( b->Pos.y );
531
yEnd = core::ceil32( c->Pos.y ) - 1;
535
subPixel = ( (f32) yStart ) - b->Pos.y;
537
// correct to pixel center
538
scan.x[0] += scan.slopeX[0] * subPixel;
539
scan.x[1] += scan.slopeX[1] * subPixel;
542
scan.z[0] += scan.slopeZ[0] * subPixel;
543
scan.z[1] += scan.slopeZ[1] * subPixel;
547
scan.w[0] += scan.slopeW[0] * subPixel;
548
scan.w[1] += scan.slopeW[1] * subPixel;
552
scan.c[0][0] += scan.slopeC[0][0] * subPixel;
553
scan.c[0][1] += scan.slopeC[0][1] * subPixel;
557
scan.t[0][0] += scan.slopeT[0][0] * subPixel;
558
scan.t[0][1] += scan.slopeT[0][1] * subPixel;
562
scan.t[1][0] += scan.slopeT[1][0] * subPixel;
563
scan.t[1][1] += scan.slopeT[1][1] * subPixel;
568
// rasterize the edge scanlines
569
for( line.y = yStart; line.y <= yEnd; ++line.y)
571
line.x[scan.left] = scan.x[0];
572
line.x[scan.right] = scan.x[1];
575
line.z[scan.left] = scan.z[0];
576
line.z[scan.right] = scan.z[1];
580
line.w[scan.left] = scan.w[0];
581
line.w[scan.right] = scan.w[1];
585
line.c[0][scan.left] = scan.c[0][0];
586
line.c[0][scan.right] = scan.c[0][1];
590
line.t[0][scan.left] = scan.t[0][0];
591
line.t[0][scan.right] = scan.t[0][1];
595
line.t[1][scan.left] = scan.t[1][0];
596
line.t[1][scan.right] = scan.t[1][1];
600
scanline_bilinear ();
602
scan.x[0] += scan.slopeX[0];
603
scan.x[1] += scan.slopeX[1];
606
scan.z[0] += scan.slopeZ[0];
607
scan.z[1] += scan.slopeZ[1];
611
scan.w[0] += scan.slopeW[0];
612
scan.w[1] += scan.slopeW[1];
616
scan.c[0][0] += scan.slopeC[0][0];
617
scan.c[0][1] += scan.slopeC[0][1];
621
scan.t[0][0] += scan.slopeT[0][0];
622
scan.t[0][1] += scan.slopeT[0][1];
626
scan.t[1][0] += scan.slopeT[1][0];
627
scan.t[1][1] += scan.slopeT[1][1];
635
} // end namespace video
636
} // end namespace irr
638
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
645
//! creates a flat triangle renderer
646
IBurningShader* createTriangleRendererTextureDetailMap2(CBurningVideoDriver* driver)
648
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
649
return new CTRTextureDetailMap2(driver);
652
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
656
} // end namespace video
657
} // end namespace irr