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 #if BURNING_MATERIAL_MAX_COLORS < 1
\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* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_;
\r
89 void scanline_bilinear2 ();
\r
94 CTRTextureLightMap2_M1::CTRTextureLightMap2_M1(CBurningVideoDriver* driver)
\r
95 : IBurningShader(driver)
\r
98 setDebugName("CTRTextureLightMap2_M1");
\r
104 REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 ()
\r
115 // apply top-left fill-convention, left
\r
116 xStart = fill_convention_left( line.x[0] );
\r
117 xEnd = fill_convention_right( line.x[1] );
\r
119 dx = xEnd - xStart;
\r
124 const f32 invDeltaX = reciprocal_zero2( line.x[1] - line.x[0] );
\r
126 // search z-buffer for first not occulled pixel
\r
127 z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
\r
130 const f32 subPixel = ( (f32) xStart ) - line.x[0];
\r
133 const f32 b = (line.w[1] - line.w[0]) * invDeltaX;
\r
134 f32 a = line.w[0] + ( b * subPixel );
\r
138 while ( a <= z[i] )
\r
147 // lazy setup rest of scanline
\r
152 const f32 b = (line.z[1] - line.z[0]) * invDeltaX;
\r
153 f32 a = line.z[0] + ( b * subPixel );
\r
166 // lazy setup rest of scanline
\r
171 SOFTWARE_DRIVER_2_CLIPCHECK;
\r
172 dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
\r
174 a = (f32) i + subPixel;
\r
176 line.t[0][1] = (line.t[0][1] - line.t[0][0]) * invDeltaX;
\r
177 line.t[1][1] = (line.t[1][1] - line.t[1][0]) * invDeltaX;
\r
179 line.t[0][0] += line.t[0][1] * a;
\r
180 line.t[1][0] += line.t[1][1] * a;
\r
183 #ifdef BURNINGVIDEO_RENDERER_FAST
\r
184 u32 dIndex = ( line.y & 3 ) << 2;
\r
186 tFixPoint r0, g0, b0;
\r
187 tFixPoint r1, g1, b1;
\r
191 tFixPoint r0, g0, b0;
\r
192 tFixPoint r1, g1, b1;
\r
196 for ( ;i <= dx; i++ )
\r
199 if ( line.w[0] >= z[i] )
\r
203 if ( line.z[0] < z[i] )
\r
208 #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
\r
209 f32 inversew = fix_inverse32 ( line.w[0] );
\r
211 f32 inversew = FIX_POINT_F32_MUL;
\r
216 #ifdef BURNINGVIDEO_RENDERER_FAST
\r
218 const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ];
\r
220 getSample_texture ( r0, g0, b0, &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) );
\r
221 getSample_texture ( r1, g1, b1, &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) );
\r
223 getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) );
\r
224 getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) );
\r
228 dst[i] = fix_to_sample( imulFix_tex1 ( r0, r1 ),
\r
229 imulFix_tex1 ( g0, g1 ),
\r
230 imulFix_tex1 ( b0, b1 )
\r
235 line.w[0] += line.w[1];
\r
237 line.z[0] += line.z[1];
\r
239 line.t[0][0] += line.t[0][1];
\r
240 line.t[1][0] += line.t[1][1];
\r
246 void CTRTextureLightMap2_M1::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c)
\r
249 // sort on height, y
\r
250 if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
\r
251 if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c);
\r
252 if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
\r
254 const f32 ca = c->Pos.y - a->Pos.y;
\r
255 const f32 ba = b->Pos.y - a->Pos.y;
\r
256 const f32 cb = c->Pos.y - b->Pos.y;
\r
257 // calculate delta y of the edges
\r
258 scan.invDeltaY[0] = reciprocal_zero( ca );
\r
259 scan.invDeltaY[1] = reciprocal_zero( ba );
\r
260 scan.invDeltaY[2] = reciprocal_zero( cb );
\r
262 if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) )
\r
265 // find if the major edge is left or right aligned
\r
268 temp[0] = a->Pos.x - c->Pos.x;
\r
270 temp[2] = b->Pos.x - a->Pos.x;
\r
273 scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1;
\r
274 scan.right = 1 - scan.left;
\r
276 // calculate slopes for the major edge
\r
277 scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0];
\r
278 scan.x[0] = a->Pos.x;
\r
281 scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0];
\r
282 scan.z[0] = a->Pos.z;
\r
286 scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0];
\r
287 scan.w[0] = a->Pos.w;
\r
291 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0];
\r
292 scan.c[0] = a->Color[0];
\r
296 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0];
\r
297 scan.t[0][0] = a->Tex[0];
\r
301 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0];
\r
302 scan.t[1][0] = a->Tex[1];
\r
305 // top left fill convention y run
\r
313 // rasterize upper sub-triangle
\r
314 if ( F32_GREATER_0 ( scan.invDeltaY[1] ) )
\r
316 // calculate slopes for top edge
\r
317 scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1];
\r
318 scan.x[1] = a->Pos.x;
\r
321 scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1];
\r
322 scan.z[1] = a->Pos.z;
\r
326 scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1];
\r
327 scan.w[1] = a->Pos.w;
\r
331 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1];
\r
332 scan.c[1] = a->Color[0];
\r
336 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1];
\r
337 scan.t[0][1] = a->Tex[0];
\r
341 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1];
\r
342 scan.t[1][1] = a->Tex[1];
\r
345 // apply top-left fill convention, top part
\r
346 yStart = fill_convention_left( a->Pos.y );
\r
347 yEnd = fill_convention_right( b->Pos.y );
\r
350 subPixel = ( (f32) yStart ) - a->Pos.y;
\r
352 // correct to pixel center
\r
353 scan.x[0] += scan.slopeX[0] * subPixel;
\r
354 scan.x[1] += scan.slopeX[1] * subPixel;
\r
357 scan.z[0] += scan.slopeZ[0] * subPixel;
\r
358 scan.z[1] += scan.slopeZ[1] * subPixel;
\r
362 scan.w[0] += scan.slopeW[0] * subPixel;
\r
363 scan.w[1] += scan.slopeW[1] * subPixel;
\r
367 scan.c[0] += scan.slopeC[0] * subPixel;
\r
368 scan.c[1] += scan.slopeC[1] * subPixel;
\r
372 scan.t[0][0] += scan.slopeT[0][0] * subPixel;
\r
373 scan.t[0][1] += scan.slopeT[0][1] * subPixel;
\r
377 scan.t[1][0] += scan.slopeT[1][0] * subPixel;
\r
378 scan.t[1][1] += scan.slopeT[1][1] * subPixel;
\r
383 // rasterize the edge scanlines
\r
384 for( line.y = yStart; line.y <= yEnd; ++line.y)
\r
386 line.x[scan.left] = scan.x[0];
\r
387 line.x[scan.right] = scan.x[1];
\r
390 line.z[scan.left] = scan.z[0];
\r
391 line.z[scan.right] = scan.z[1];
\r
395 line.w[scan.left] = scan.w[0];
\r
396 line.w[scan.right] = scan.w[1];
\r
400 line.c[scan.left] = scan.c[0];
\r
401 line.c[scan.right] = scan.c[1];
\r
405 line.t[0][scan.left] = scan.t[0][0];
\r
406 line.t[0][scan.right] = scan.t[0][1];
\r
410 line.t[1][scan.left] = scan.t[1][0];
\r
411 line.t[1][scan.right] = scan.t[1][1];
\r
414 // render a scanline
\r
415 scanline_bilinear2 ();
\r
417 scan.x[0] += scan.slopeX[0];
\r
418 scan.x[1] += scan.slopeX[1];
\r
421 scan.z[0] += scan.slopeZ[0];
\r
422 scan.z[1] += scan.slopeZ[1];
\r
426 scan.w[0] += scan.slopeW[0];
\r
427 scan.w[1] += scan.slopeW[1];
\r
431 scan.c[0] += scan.slopeC[0];
\r
432 scan.c[1] += scan.slopeC[1];
\r
436 scan.t[0][0] += scan.slopeT[0][0];
\r
437 scan.t[0][1] += scan.slopeT[0][1];
\r
441 scan.t[1][0] += scan.slopeT[1][0];
\r
442 scan.t[1][1] += scan.slopeT[1][1];
\r
448 // rasterize lower sub-triangle
\r
449 //if ( (f32) 0.0 != scan.invDeltaY[2] )
\r
450 if ( F32_GREATER_0 ( scan.invDeltaY[2] ) )
\r
452 // advance to middle point
\r
453 if ( F32_GREATER_0 ( scan.invDeltaY[1] ) )
\r
455 temp[0] = b->Pos.y - a->Pos.y; // dy
\r
457 scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0];
\r
459 scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0];
\r
462 scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0];
\r
465 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0];
\r
468 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0];
\r
471 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0];
\r
476 // calculate slopes for bottom edge
\r
477 scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2];
\r
478 scan.x[1] = b->Pos.x;
\r
481 scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2];
\r
482 scan.z[1] = b->Pos.z;
\r
486 scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2];
\r
487 scan.w[1] = b->Pos.w;
\r
491 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2];
\r
492 scan.c[1] = b->Color[0];
\r
496 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2];
\r
497 scan.t[0][1] = b->Tex[0];
\r
501 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2];
\r
502 scan.t[1][1] = b->Tex[1];
\r
505 // apply top-left fill convention, top part
\r
506 yStart = fill_convention_left( b->Pos.y );
\r
507 yEnd = fill_convention_right( c->Pos.y );
\r
511 subPixel = ( (f32) yStart ) - b->Pos.y;
\r
513 // correct to pixel center
\r
514 scan.x[0] += scan.slopeX[0] * subPixel;
\r
515 scan.x[1] += scan.slopeX[1] * subPixel;
\r
518 scan.z[0] += scan.slopeZ[0] * subPixel;
\r
519 scan.z[1] += scan.slopeZ[1] * subPixel;
\r
523 scan.w[0] += scan.slopeW[0] * subPixel;
\r
524 scan.w[1] += scan.slopeW[1] * subPixel;
\r
528 scan.c[0] += scan.slopeC[0] * subPixel;
\r
529 scan.c[1] += scan.slopeC[1] * subPixel;
\r
533 scan.t[0][0] += scan.slopeT[0][0] * subPixel;
\r
534 scan.t[0][1] += scan.slopeT[0][1] * subPixel;
\r
538 scan.t[1][0] += scan.slopeT[1][0] * subPixel;
\r
539 scan.t[1][1] += scan.slopeT[1][1] * subPixel;
\r
544 // rasterize the edge scanlines
\r
545 for( line.y = yStart; line.y <= yEnd; ++line.y)
\r
547 line.x[scan.left] = scan.x[0];
\r
548 line.x[scan.right] = scan.x[1];
\r
551 line.z[scan.left] = scan.z[0];
\r
552 line.z[scan.right] = scan.z[1];
\r
556 line.w[scan.left] = scan.w[0];
\r
557 line.w[scan.right] = scan.w[1];
\r
561 line.c[scan.left] = scan.c[0];
\r
562 line.c[scan.right] = scan.c[1];
\r
566 line.t[0][scan.left] = scan.t[0][0];
\r
567 line.t[0][scan.right] = scan.t[0][1];
\r
571 line.t[1][scan.left] = scan.t[1][0];
\r
572 line.t[1][scan.right] = scan.t[1][1];
\r
575 // render a scanline
\r
576 scanline_bilinear2 ();
\r
578 scan.x[0] += scan.slopeX[0];
\r
579 scan.x[1] += scan.slopeX[1];
\r
582 scan.z[0] += scan.slopeZ[0];
\r
583 scan.z[1] += scan.slopeZ[1];
\r
587 scan.w[0] += scan.slopeW[0];
\r
588 scan.w[1] += scan.slopeW[1];
\r
592 scan.c[0] += scan.slopeC[0];
\r
593 scan.c[1] += scan.slopeC[1];
\r
597 scan.t[0][0] += scan.slopeT[0][0];
\r
598 scan.t[0][1] += scan.slopeT[0][1];
\r
602 scan.t[1][0] += scan.slopeT[1][0];
\r
603 scan.t[1][1] += scan.slopeT[1][1];
\r
612 } // end namespace video
\r
613 } // end namespace irr
\r
615 #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
624 //! creates a flat triangle renderer
\r
625 IBurningShader* createTriangleRendererTextureLightMap2_M1(CBurningVideoDriver* driver)
\r
627 //ETR_TEXTURE_GOURAUD_LIGHTMAP_M1
\r
628 #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
629 return new CTRTextureLightMap2_M1(driver);
\r
632 #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
636 } // end namespace video
\r
637 } // end namespace irr
\r