1 // Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "IrrCompileConfig.h"
\r
6 #include "IBurningShader.h"
\r
8 #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
10 // compile flag for this file
\r
27 // define render case
\r
40 // apply global override
\r
41 #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
\r
45 #ifndef SOFTWARE_DRIVER_2_SUBTEXEL
\r
49 #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR
\r
53 #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER )
\r
54 #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
\r
77 class CTRTextureLightMap2_M1 : public IBurningShader
\r
82 CTRTextureLightMap2_M1(CBurningVideoDriver* driver);
\r
84 //! draws an indexed triangle list
\r
85 virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) _IRR_OVERRIDE_;
\r
89 void scanline_bilinear2 ();
\r
96 CTRTextureLightMap2_M1::CTRTextureLightMap2_M1(CBurningVideoDriver* driver)
\r
97 : IBurningShader(driver)
\r
100 setDebugName("CTRTextureLightMap2_M1");
\r
106 REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 ()
\r
117 // apply top-left fill-convention, left
\r
118 xStart = core::ceil32_fast( line.x[0] );
\r
119 xEnd = core::ceil32_fast( line.x[1] ) - 1;
\r
121 dx = xEnd - xStart;
\r
126 const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] );
\r
128 // search z-buffer for first not occulled pixel
\r
129 z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
\r
132 const f32 subPixel = ( (f32) xStart ) - line.x[0];
\r
135 const f32 b = (line.w[1] - line.w[0]) * invDeltaX;
\r
136 f32 a = line.w[0] + ( b * subPixel );
\r
140 while ( a <= z[i] )
\r
149 // lazy setup rest of scanline
\r
154 const f32 b = (line.z[1] - line.z[0]) * invDeltaX;
\r
155 f32 a = line.z[0] + ( b * subPixel );
\r
168 // lazy setup rest of scanline
\r
173 dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
\r
175 a = (f32) i + subPixel;
\r
177 line.t[0][1] = (line.t[0][1] - line.t[0][0]) * invDeltaX;
\r
178 line.t[1][1] = (line.t[1][1] - line.t[1][0]) * invDeltaX;
\r
180 line.t[0][0] += line.t[0][1] * a;
\r
181 line.t[1][0] += line.t[1][1] * a;
\r
184 #ifdef BURNINGVIDEO_RENDERER_FAST
\r
185 u32 dIndex = ( line.y & 3 ) << 2;
\r
187 tFixPoint r0, g0, b0;
\r
188 tFixPoint r1, g1, b1;
\r
192 tFixPoint r0, g0, b0;
\r
193 tFixPoint r1, g1, b1;
\r
197 for ( ;i <= dx; i++ )
\r
200 if ( line.w[0] >= z[i] )
\r
204 if ( line.z[0] < z[i] )
\r
209 #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
\r
210 f32 inversew = fix_inverse32 ( line.w[0] );
\r
212 f32 inversew = FIX_POINT_F32_MUL;
\r
217 #ifdef BURNINGVIDEO_RENDERER_FAST
\r
219 const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ];
\r
221 getSample_texture ( r0, g0, b0, &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) );
\r
222 getSample_texture ( r1, g1, b1, &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) );
\r
224 getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) );
\r
225 getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) );
\r
229 dst[i] = fix_to_color ( imulFix_tex1 ( r0, r1 ),
\r
230 imulFix_tex1 ( g0, g1 ),
\r
231 imulFix_tex1 ( b0, b1 )
\r
236 line.w[0] += line.w[1];
\r
238 line.z[0] += line.z[1];
\r
240 line.t[0][0] += line.t[0][1];
\r
241 line.t[1][0] += line.t[1][1];
\r
247 void CTRTextureLightMap2_M1::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c )
\r
249 sScanConvertData scan;
\r
251 // sort on height, y
\r
252 if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
\r
253 if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c);
\r
254 if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
\r
256 const f32 ca = c->Pos.y - a->Pos.y;
\r
257 const f32 ba = b->Pos.y - a->Pos.y;
\r
258 const f32 cb = c->Pos.y - b->Pos.y;
\r
259 // calculate delta y of the edges
\r
260 scan.invDeltaY[0] = core::reciprocal( ca );
\r
261 scan.invDeltaY[1] = core::reciprocal( ba );
\r
262 scan.invDeltaY[2] = core::reciprocal( cb );
\r
264 if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) )
\r
267 // find if the major edge is left or right aligned
\r
270 temp[0] = a->Pos.x - c->Pos.x;
\r
272 temp[2] = b->Pos.x - a->Pos.x;
\r
275 scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1;
\r
276 scan.right = 1 - scan.left;
\r
278 // calculate slopes for the major edge
\r
279 scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0];
\r
280 scan.x[0] = a->Pos.x;
\r
283 scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0];
\r
284 scan.z[0] = a->Pos.z;
\r
288 scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0];
\r
289 scan.w[0] = a->Pos.w;
\r
293 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0];
\r
294 scan.c[0] = a->Color[0];
\r
298 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0];
\r
299 scan.t[0][0] = a->Tex[0];
\r
303 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0];
\r
304 scan.t[1][0] = a->Tex[1];
\r
307 // top left fill convention y run
\r
315 // rasterize upper sub-triangle
\r
316 if ( F32_GREATER_0 ( scan.invDeltaY[1] ) )
\r
318 // calculate slopes for top edge
\r
319 scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1];
\r
320 scan.x[1] = a->Pos.x;
\r
323 scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1];
\r
324 scan.z[1] = a->Pos.z;
\r
328 scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1];
\r
329 scan.w[1] = a->Pos.w;
\r
333 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1];
\r
334 scan.c[1] = a->Color[0];
\r
338 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1];
\r
339 scan.t[0][1] = a->Tex[0];
\r
343 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1];
\r
344 scan.t[1][1] = a->Tex[1];
\r
347 // apply top-left fill convention, top part
\r
348 yStart = core::ceil32_fast( a->Pos.y );
\r
349 yEnd = core::ceil32_fast( b->Pos.y ) - 1;
\r
352 subPixel = ( (f32) yStart ) - a->Pos.y;
\r
354 // correct to pixel center
\r
355 scan.x[0] += scan.slopeX[0] * subPixel;
\r
356 scan.x[1] += scan.slopeX[1] * subPixel;
\r
359 scan.z[0] += scan.slopeZ[0] * subPixel;
\r
360 scan.z[1] += scan.slopeZ[1] * subPixel;
\r
364 scan.w[0] += scan.slopeW[0] * subPixel;
\r
365 scan.w[1] += scan.slopeW[1] * subPixel;
\r
369 scan.c[0] += scan.slopeC[0] * subPixel;
\r
370 scan.c[1] += scan.slopeC[1] * subPixel;
\r
374 scan.t[0][0] += scan.slopeT[0][0] * subPixel;
\r
375 scan.t[0][1] += scan.slopeT[0][1] * subPixel;
\r
379 scan.t[1][0] += scan.slopeT[1][0] * subPixel;
\r
380 scan.t[1][1] += scan.slopeT[1][1] * subPixel;
\r
385 // rasterize the edge scanlines
\r
386 for( line.y = yStart; line.y <= yEnd; ++line.y)
\r
388 line.x[scan.left] = scan.x[0];
\r
389 line.x[scan.right] = scan.x[1];
\r
392 line.z[scan.left] = scan.z[0];
\r
393 line.z[scan.right] = scan.z[1];
\r
397 line.w[scan.left] = scan.w[0];
\r
398 line.w[scan.right] = scan.w[1];
\r
402 line.c[scan.left] = scan.c[0];
\r
403 line.c[scan.right] = scan.c[1];
\r
407 line.t[0][scan.left] = scan.t[0][0];
\r
408 line.t[0][scan.right] = scan.t[0][1];
\r
412 line.t[1][scan.left] = scan.t[1][0];
\r
413 line.t[1][scan.right] = scan.t[1][1];
\r
416 // render a scanline
\r
417 scanline_bilinear2 ();
\r
419 scan.x[0] += scan.slopeX[0];
\r
420 scan.x[1] += scan.slopeX[1];
\r
423 scan.z[0] += scan.slopeZ[0];
\r
424 scan.z[1] += scan.slopeZ[1];
\r
428 scan.w[0] += scan.slopeW[0];
\r
429 scan.w[1] += scan.slopeW[1];
\r
433 scan.c[0] += scan.slopeC[0];
\r
434 scan.c[1] += scan.slopeC[1];
\r
438 scan.t[0][0] += scan.slopeT[0][0];
\r
439 scan.t[0][1] += scan.slopeT[0][1];
\r
443 scan.t[1][0] += scan.slopeT[1][0];
\r
444 scan.t[1][1] += scan.slopeT[1][1];
\r
450 // rasterize lower sub-triangle
\r
451 //if ( (f32) 0.0 != scan.invDeltaY[2] )
\r
452 if ( F32_GREATER_0 ( scan.invDeltaY[2] ) )
\r
454 // advance to middle point
\r
455 if ( F32_GREATER_0 ( scan.invDeltaY[1] ) )
\r
457 temp[0] = b->Pos.y - a->Pos.y; // dy
\r
459 scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0];
\r
461 scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0];
\r
464 scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0];
\r
467 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0];
\r
470 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0];
\r
473 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0];
\r
478 // calculate slopes for bottom edge
\r
479 scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2];
\r
480 scan.x[1] = b->Pos.x;
\r
483 scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2];
\r
484 scan.z[1] = b->Pos.z;
\r
488 scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2];
\r
489 scan.w[1] = b->Pos.w;
\r
493 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2];
\r
494 scan.c[1] = b->Color[0];
\r
498 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2];
\r
499 scan.t[0][1] = b->Tex[0];
\r
503 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2];
\r
504 scan.t[1][1] = b->Tex[1];
\r
507 // apply top-left fill convention, top part
\r
508 yStart = core::ceil32_fast( b->Pos.y );
\r
509 yEnd = core::ceil32_fast( c->Pos.y ) - 1;
\r
513 subPixel = ( (f32) yStart ) - b->Pos.y;
\r
515 // correct to pixel center
\r
516 scan.x[0] += scan.slopeX[0] * subPixel;
\r
517 scan.x[1] += scan.slopeX[1] * subPixel;
\r
520 scan.z[0] += scan.slopeZ[0] * subPixel;
\r
521 scan.z[1] += scan.slopeZ[1] * subPixel;
\r
525 scan.w[0] += scan.slopeW[0] * subPixel;
\r
526 scan.w[1] += scan.slopeW[1] * subPixel;
\r
530 scan.c[0] += scan.slopeC[0] * subPixel;
\r
531 scan.c[1] += scan.slopeC[1] * subPixel;
\r
535 scan.t[0][0] += scan.slopeT[0][0] * subPixel;
\r
536 scan.t[0][1] += scan.slopeT[0][1] * subPixel;
\r
540 scan.t[1][0] += scan.slopeT[1][0] * subPixel;
\r
541 scan.t[1][1] += scan.slopeT[1][1] * subPixel;
\r
546 // rasterize the edge scanlines
\r
547 for( line.y = yStart; line.y <= yEnd; ++line.y)
\r
549 line.x[scan.left] = scan.x[0];
\r
550 line.x[scan.right] = scan.x[1];
\r
553 line.z[scan.left] = scan.z[0];
\r
554 line.z[scan.right] = scan.z[1];
\r
558 line.w[scan.left] = scan.w[0];
\r
559 line.w[scan.right] = scan.w[1];
\r
563 line.c[scan.left] = scan.c[0];
\r
564 line.c[scan.right] = scan.c[1];
\r
568 line.t[0][scan.left] = scan.t[0][0];
\r
569 line.t[0][scan.right] = scan.t[0][1];
\r
573 line.t[1][scan.left] = scan.t[1][0];
\r
574 line.t[1][scan.right] = scan.t[1][1];
\r
577 // render a scanline
\r
578 scanline_bilinear2 ();
\r
580 scan.x[0] += scan.slopeX[0];
\r
581 scan.x[1] += scan.slopeX[1];
\r
584 scan.z[0] += scan.slopeZ[0];
\r
585 scan.z[1] += scan.slopeZ[1];
\r
589 scan.w[0] += scan.slopeW[0];
\r
590 scan.w[1] += scan.slopeW[1];
\r
594 scan.c[0] += scan.slopeC[0];
\r
595 scan.c[1] += scan.slopeC[1];
\r
599 scan.t[0][0] += scan.slopeT[0][0];
\r
600 scan.t[0][1] += scan.slopeT[0][1];
\r
604 scan.t[1][0] += scan.slopeT[1][0];
\r
605 scan.t[1][1] += scan.slopeT[1][1];
\r
614 } // end namespace video
\r
615 } // end namespace irr
\r
617 #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
626 //! creates a flat triangle renderer
\r
627 IBurningShader* createTriangleRendererTextureLightMap2_M1(CBurningVideoDriver* driver)
\r
629 #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
630 return new CTRTextureLightMap2_M1(driver);
\r
633 #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
637 } // end namespace video
\r
638 } // end namespace irr
\r