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_Add : public IBurningShader
\r
82 CTRTextureLightMap2_Add(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 fragmentShader();
\r
94 CTRTextureLightMap2_Add::CTRTextureLightMap2_Add(CBurningVideoDriver* driver)
\r
95 : IBurningShader(driver)
\r
98 setDebugName("CTRTextureLightMap2_Add");
\r
106 REALINLINE void CTRTextureLightMap2_Add::fragmentShader()
\r
133 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES];
\r
136 // apply top-left fill-convention, left
\r
137 xStart = fill_convention_left( line.x[0] );
\r
138 xEnd = fill_convention_right( line.x[1] );
\r
140 dx = xEnd - xStart;
\r
146 const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] );
\r
149 slopeZ = (line.z[1] - line.z[0]) * invDeltaX;
\r
152 slopeW = (line.w[1] - line.w[0]) * invDeltaX;
\r
155 slopeC = (line.c[1] - line.c[0]) * invDeltaX;
\r
158 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX;
\r
161 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX;
\r
165 subPixel = ( (f32) xStart ) - line.x[0];
\r
167 line.z[0] += slopeZ * subPixel;
\r
170 line.w[0] += slopeW * subPixel;
\r
173 line.c[0] += slopeC * subPixel;
\r
176 line.t[0][0] += slopeT[0] * subPixel;
\r
179 line.t[1][0] += slopeT[1] * subPixel;
\r
183 SOFTWARE_DRIVER_2_CLIPCHECK;
\r
184 dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
\r
187 z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
\r
191 f32 inversew = FIX_POINT_F32_MUL;
\r
193 #if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff
\r
194 u32 dIndex = ( line.y & 3 ) << 2;
\r
197 tFixPoint r0, g0, b0;
\r
198 tFixPoint r1, g1, b1;
\r
202 for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X)
\r
205 if ( line.z[0] < z[i] )
\r
208 if ( line.w[0] >= z[i] )
\r
220 inversew = fix_inverse32(line.w[0]);
\r
223 #if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff
\r
225 const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ];
\r
227 dst[i] = PixelAdd32 (
\r
228 getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew),
\r
229 d + tofix ( line.t[0][0].y,inversew) ),
\r
230 getTexel_plain ( &IT[1], d + tofix ( line.t[1][0].x,inversew),
\r
231 d + tofix ( line.t[1][0].y,inversew) )
\r
236 getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) );
\r
237 getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) );
\r
239 dst[i] = fix_to_sample( clampfix_maxcolor ( r0 + r1 ),
\r
240 clampfix_maxcolor ( g0 + g1 ),
\r
241 clampfix_maxcolor ( b0 + b1 )
\r
248 line.z[0] += slopeZ;
\r
251 line.w[0] += slopeW;
\r
254 line.c[0] += slopeC;
\r
257 line.t[0][0] += slopeT[0];
\r
260 line.t[1][0] += slopeT[1];
\r
266 void CTRTextureLightMap2_Add::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c)
\r
268 // sort on height, y
\r
269 if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
\r
270 if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c);
\r
271 if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
\r
273 const f32 ca = c->Pos.y - a->Pos.y;
\r
274 const f32 ba = b->Pos.y - a->Pos.y;
\r
275 const f32 cb = c->Pos.y - b->Pos.y;
\r
276 // calculate delta y of the edges
\r
277 scan.invDeltaY[0] = fill_step_y( ca );
\r
278 scan.invDeltaY[1] = fill_step_y( ba );
\r
279 scan.invDeltaY[2] = fill_step_y( cb );
\r
281 if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) )
\r
284 // find if the major edge is left or right aligned
\r
287 temp[0] = a->Pos.x - c->Pos.x;
\r
289 temp[2] = b->Pos.x - a->Pos.x;
\r
292 scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1;
\r
293 scan.right = 1 - scan.left;
\r
295 // calculate slopes for the major edge
\r
296 scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0];
\r
297 scan.x[0] = a->Pos.x;
\r
300 scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0];
\r
301 scan.z[0] = a->Pos.z;
\r
305 scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0];
\r
306 scan.w[0] = a->Pos.w;
\r
310 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0];
\r
311 scan.c[0] = a->Color[0];
\r
315 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0];
\r
316 scan.t[0][0] = a->Tex[0];
\r
320 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0];
\r
321 scan.t[1][0] = a->Tex[1];
\r
324 // top left fill convention y run
\r
332 // rasterize upper sub-triangle
\r
333 if ( (f32) 0.0 != scan.invDeltaY[1] )
\r
335 // calculate slopes for top edge
\r
336 scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1];
\r
337 scan.x[1] = a->Pos.x;
\r
340 scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1];
\r
341 scan.z[1] = a->Pos.z;
\r
345 scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1];
\r
346 scan.w[1] = a->Pos.w;
\r
350 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1];
\r
351 scan.c[1] = a->Color[0];
\r
355 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1];
\r
356 scan.t[0][1] = a->Tex[0];
\r
360 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1];
\r
361 scan.t[1][1] = a->Tex[1];
\r
364 // apply top-left fill convention, top part
\r
365 yStart = fill_convention_left( a->Pos.y );
\r
366 yEnd = fill_convention_right( b->Pos.y );
\r
369 subPixel = ( (f32) yStart ) - a->Pos.y;
\r
371 // correct to pixel center
\r
372 scan.x[0] += scan.slopeX[0] * subPixel;
\r
373 scan.x[1] += scan.slopeX[1] * subPixel;
\r
376 scan.z[0] += scan.slopeZ[0] * subPixel;
\r
377 scan.z[1] += scan.slopeZ[1] * subPixel;
\r
381 scan.w[0] += scan.slopeW[0] * subPixel;
\r
382 scan.w[1] += scan.slopeW[1] * subPixel;
\r
386 scan.c[0] += scan.slopeC[0] * subPixel;
\r
387 scan.c[1] += scan.slopeC[1] * subPixel;
\r
391 scan.t[0][0] += scan.slopeT[0][0] * subPixel;
\r
392 scan.t[0][1] += scan.slopeT[0][1] * subPixel;
\r
396 scan.t[1][0] += scan.slopeT[1][0] * subPixel;
\r
397 scan.t[1][1] += scan.slopeT[1][1] * subPixel;
\r
402 // rasterize the edge scanlines
\r
403 for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y)
\r
405 line.x[scan.left] = scan.x[0];
\r
406 line.x[scan.right] = scan.x[1];
\r
409 line.z[scan.left] = scan.z[0];
\r
410 line.z[scan.right] = scan.z[1];
\r
414 line.w[scan.left] = scan.w[0];
\r
415 line.w[scan.right] = scan.w[1];
\r
419 line.c[scan.left] = scan.c[0];
\r
420 line.c[scan.right] = scan.c[1];
\r
424 line.t[0][scan.left] = scan.t[0][0];
\r
425 line.t[0][scan.right] = scan.t[0][1];
\r
429 line.t[1][scan.left] = scan.t[1][0];
\r
430 line.t[1][scan.right] = scan.t[1][1];
\r
433 // render a scanline
\r
434 interlace_scanline fragmentShader();
\r
436 scan.x[0] += scan.slopeX[0];
\r
437 scan.x[1] += scan.slopeX[1];
\r
440 scan.z[0] += scan.slopeZ[0];
\r
441 scan.z[1] += scan.slopeZ[1];
\r
445 scan.w[0] += scan.slopeW[0];
\r
446 scan.w[1] += scan.slopeW[1];
\r
450 scan.c[0] += scan.slopeC[0];
\r
451 scan.c[1] += scan.slopeC[1];
\r
455 scan.t[0][0] += scan.slopeT[0][0];
\r
456 scan.t[0][1] += scan.slopeT[0][1];
\r
460 scan.t[1][0] += scan.slopeT[1][0];
\r
461 scan.t[1][1] += scan.slopeT[1][1];
\r
467 // rasterize lower sub-triangle
\r
468 if ( (f32) 0.0 != scan.invDeltaY[2] )
\r
470 // advance to middle point
\r
471 if( (f32) 0.0 != scan.invDeltaY[1] )
\r
473 temp[0] = b->Pos.y - a->Pos.y; // dy
\r
475 scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0];
\r
477 scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0];
\r
480 scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0];
\r
483 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0];
\r
486 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0];
\r
489 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0];
\r
494 // calculate slopes for bottom edge
\r
495 scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2];
\r
496 scan.x[1] = b->Pos.x;
\r
499 scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2];
\r
500 scan.z[1] = b->Pos.z;
\r
504 scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2];
\r
505 scan.w[1] = b->Pos.w;
\r
509 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2];
\r
510 scan.c[1] = b->Color[0];
\r
514 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2];
\r
515 scan.t[0][1] = b->Tex[0];
\r
519 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2];
\r
520 scan.t[1][1] = b->Tex[1];
\r
523 // apply top-left fill convention, top part
\r
524 yStart = fill_convention_left( b->Pos.y );
\r
525 yEnd = fill_convention_right( c->Pos.y );
\r
529 subPixel = ( (f32) yStart ) - b->Pos.y;
\r
531 // correct to pixel center
\r
532 scan.x[0] += scan.slopeX[0] * subPixel;
\r
533 scan.x[1] += scan.slopeX[1] * subPixel;
\r
536 scan.z[0] += scan.slopeZ[0] * subPixel;
\r
537 scan.z[1] += scan.slopeZ[1] * subPixel;
\r
541 scan.w[0] += scan.slopeW[0] * subPixel;
\r
542 scan.w[1] += scan.slopeW[1] * subPixel;
\r
546 scan.c[0] += scan.slopeC[0] * subPixel;
\r
547 scan.c[1] += scan.slopeC[1] * subPixel;
\r
551 scan.t[0][0] += scan.slopeT[0][0] * subPixel;
\r
552 scan.t[0][1] += scan.slopeT[0][1] * subPixel;
\r
556 scan.t[1][0] += scan.slopeT[1][0] * subPixel;
\r
557 scan.t[1][1] += scan.slopeT[1][1] * subPixel;
\r
562 // rasterize the edge scanlines
\r
563 for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y)
\r
565 line.x[scan.left] = scan.x[0];
\r
566 line.x[scan.right] = scan.x[1];
\r
569 line.z[scan.left] = scan.z[0];
\r
570 line.z[scan.right] = scan.z[1];
\r
574 line.w[scan.left] = scan.w[0];
\r
575 line.w[scan.right] = scan.w[1];
\r
579 line.c[scan.left] = scan.c[0];
\r
580 line.c[scan.right] = scan.c[1];
\r
584 line.t[0][scan.left] = scan.t[0][0];
\r
585 line.t[0][scan.right] = scan.t[0][1];
\r
589 line.t[1][scan.left] = scan.t[1][0];
\r
590 line.t[1][scan.right] = scan.t[1][1];
\r
593 // render a scanline
\r
594 interlace_scanline fragmentShader();
\r
596 scan.x[0] += scan.slopeX[0];
\r
597 scan.x[1] += scan.slopeX[1];
\r
600 scan.z[0] += scan.slopeZ[0];
\r
601 scan.z[1] += scan.slopeZ[1];
\r
605 scan.w[0] += scan.slopeW[0];
\r
606 scan.w[1] += scan.slopeW[1];
\r
610 scan.c[0] += scan.slopeC[0];
\r
611 scan.c[1] += scan.slopeC[1];
\r
615 scan.t[0][0] += scan.slopeT[0][0];
\r
616 scan.t[0][1] += scan.slopeT[0][1];
\r
620 scan.t[1][0] += scan.slopeT[1][0];
\r
621 scan.t[1][1] += scan.slopeT[1][1];
\r
631 } // end namespace video
\r
632 } // end namespace irr
\r
634 #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
641 //! creates a flat triangle renderer
\r
642 IBurningShader* createTriangleRendererTextureLightMap2_Add(CBurningVideoDriver* driver)
\r
644 /* ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD */
\r
645 #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
646 return new CTRTextureLightMap2_Add(driver);
\r
649 #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
653 } // end namespace video
\r
654 } // end namespace irr
\r