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
79 class CTRTextureGouraudAdd2 : public IBurningShader
\r
84 CTRTextureGouraudAdd2(CBurningVideoDriver* driver);
\r
86 //! draws an indexed triangle list
\r
87 virtual void drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c) _IRR_OVERRIDE_;
\r
91 void fragmentShader();
\r
95 CTRTextureGouraudAdd2::CTRTextureGouraudAdd2(CBurningVideoDriver* driver)
\r
96 : IBurningShader(driver)
\r
99 setDebugName("CTRTextureGouraudAdd2");
\r
107 void CTRTextureGouraudAdd2::fragmentShader()
\r
134 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES];
\r
137 // apply top-left fill-convention, left
\r
138 xStart = fill_convention_left( line.x[0] );
\r
139 xEnd = fill_convention_right( line.x[1] );
\r
141 dx = xEnd - xStart;
\r
147 const f32 invDeltaX = fill_step_x( line.x[1] - line.x[0] );
\r
150 slopeZ = (line.z[1] - line.z[0]) * invDeltaX;
\r
153 slopeW = (line.w[1] - line.w[0]) * invDeltaX;
\r
156 slopeC = (line.c[1] - line.c[0]) * invDeltaX;
\r
159 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX;
\r
162 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX;
\r
166 subPixel = ( (f32) xStart ) - line.x[0];
\r
168 line.z[0] += slopeZ * subPixel;
\r
171 line.w[0] += slopeW * subPixel;
\r
174 line.c[0] += slopeC * subPixel;
\r
177 line.t[0][0] += slopeT[0] * subPixel;
\r
180 line.t[1][0] += slopeT[1] * subPixel;
\r
184 SOFTWARE_DRIVER_2_CLIPCHECK;
\r
185 dst = (tVideoSample*)RenderTarget->getData() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
\r
188 z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
\r
192 f32 inversew = FIX_POINT_F32_MUL;
\r
195 #if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff
\r
196 u32 dIndex = ( line.y & 3 ) << 2;
\r
201 tFixPoint r0, g0, b0;
\r
202 tFixPoint r1, g1, b1;
\r
206 for ( s32 i = 0; i <= dx; i += SOFTWARE_DRIVER_2_STEP_X)
\r
209 if ( line.z[0] < z[i] )
\r
212 if ( line.w[0] >= z[i] )
\r
218 inversew = fix_inverse32(line.w[0]);
\r
221 #if defined(BURNINGVIDEO_RENDERER_FAST) && COLOR_MAX==0xff
\r
223 const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ];
\r
225 dst[i] = PixelAdd32 (
\r
227 getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew),
\r
228 d + tofix ( line.t[0][0].y,inversew) )
\r
232 tx0 = tofix ( line.t[0][0].x,inversew);
\r
233 ty0 = tofix ( line.t[0][0].y,inversew);
\r
234 getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 );
\r
236 color_to_fix ( r1, g1, b1, dst[i] );
\r
238 dst[i] = fix_to_sample( clampfix_maxcolor ( r1 + r0 ),
\r
239 clampfix_maxcolor ( g1 + g0 ),
\r
240 clampfix_maxcolor ( b1 + b0 )
\r
254 line.z[0] += slopeZ;
\r
257 line.w[0] += slopeW;
\r
260 line.c[0] += slopeC;
\r
263 line.t[0][0] += slopeT[0];
\r
266 line.t[1][0] += slopeT[1];
\r
272 void CTRTextureGouraudAdd2::drawTriangle(const s4DVertex* burning_restrict a, const s4DVertex* burning_restrict b, const s4DVertex* burning_restrict c)
\r
274 // sort on height, y
\r
275 if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
\r
276 if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c);
\r
277 if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
\r
279 const f32 ca = c->Pos.y - a->Pos.y;
\r
280 const f32 ba = b->Pos.y - a->Pos.y;
\r
281 const f32 cb = c->Pos.y - b->Pos.y;
\r
282 // calculate delta y of the edges
\r
283 scan.invDeltaY[0] = fill_step_y( ca );
\r
284 scan.invDeltaY[1] = fill_step_y( ba );
\r
285 scan.invDeltaY[2] = fill_step_y( cb );
\r
287 // find if the major edge is left or right aligned
\r
290 temp[0] = a->Pos.x - c->Pos.x;
\r
292 temp[2] = b->Pos.x - a->Pos.x;
\r
295 scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1;
\r
296 scan.right = 1 - scan.left;
\r
298 // calculate slopes for the major edge
\r
299 scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0];
\r
300 scan.x[0] = a->Pos.x;
\r
303 scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0];
\r
304 scan.z[0] = a->Pos.z;
\r
308 scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0];
\r
309 scan.w[0] = a->Pos.w;
\r
313 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0];
\r
314 scan.c[0] = a->Color[0];
\r
318 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0];
\r
319 scan.t[0][0] = a->Tex[0];
\r
323 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0];
\r
324 scan.t[1][0] = a->Tex[1];
\r
327 // top left fill convention y run
\r
335 // rasterize upper sub-triangle
\r
336 if ( F32_GREATER_0 ( scan.invDeltaY[1] ) )
\r
338 // calculate slopes for top edge
\r
339 scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1];
\r
340 scan.x[1] = a->Pos.x;
\r
343 scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1];
\r
344 scan.z[1] = a->Pos.z;
\r
348 scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1];
\r
349 scan.w[1] = a->Pos.w;
\r
353 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1];
\r
354 scan.c[1] = a->Color[0];
\r
358 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1];
\r
359 scan.t[0][1] = a->Tex[0];
\r
363 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1];
\r
364 scan.t[1][1] = a->Tex[1];
\r
367 // apply top-left fill convention, top part
\r
368 yStart = fill_convention_left( a->Pos.y );
\r
369 yEnd = fill_convention_right( b->Pos.y );
\r
372 subPixel = ( (f32) yStart ) - a->Pos.y;
\r
374 // correct to pixel center
\r
375 scan.x[0] += scan.slopeX[0] * subPixel;
\r
376 scan.x[1] += scan.slopeX[1] * subPixel;
\r
379 scan.z[0] += scan.slopeZ[0] * subPixel;
\r
380 scan.z[1] += scan.slopeZ[1] * subPixel;
\r
384 scan.w[0] += scan.slopeW[0] * subPixel;
\r
385 scan.w[1] += scan.slopeW[1] * subPixel;
\r
389 scan.c[0] += scan.slopeC[0] * subPixel;
\r
390 scan.c[1] += scan.slopeC[1] * subPixel;
\r
394 scan.t[0][0] += scan.slopeT[0][0] * subPixel;
\r
395 scan.t[0][1] += scan.slopeT[0][1] * subPixel;
\r
399 scan.t[1][0] += scan.slopeT[1][0] * subPixel;
\r
400 scan.t[1][1] += scan.slopeT[1][1] * subPixel;
\r
405 // rasterize the edge scanlines
\r
406 for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y)
\r
408 line.x[scan.left] = scan.x[0];
\r
409 line.x[scan.right] = scan.x[1];
\r
412 line.z[scan.left] = scan.z[0];
\r
413 line.z[scan.right] = scan.z[1];
\r
417 line.w[scan.left] = scan.w[0];
\r
418 line.w[scan.right] = scan.w[1];
\r
422 line.c[scan.left] = scan.c[0];
\r
423 line.c[scan.right] = scan.c[1];
\r
427 line.t[0][scan.left] = scan.t[0][0];
\r
428 line.t[0][scan.right] = scan.t[0][1];
\r
432 line.t[1][scan.left] = scan.t[1][0];
\r
433 line.t[1][scan.right] = scan.t[1][1];
\r
436 // render a scanline
\r
437 interlace_scanline fragmentShader();
\r
439 scan.x[0] += scan.slopeX[0];
\r
440 scan.x[1] += scan.slopeX[1];
\r
443 scan.z[0] += scan.slopeZ[0];
\r
444 scan.z[1] += scan.slopeZ[1];
\r
448 scan.w[0] += scan.slopeW[0];
\r
449 scan.w[1] += scan.slopeW[1];
\r
453 scan.c[0] += scan.slopeC[0];
\r
454 scan.c[1] += scan.slopeC[1];
\r
458 scan.t[0][0] += scan.slopeT[0][0];
\r
459 scan.t[0][1] += scan.slopeT[0][1];
\r
463 scan.t[1][0] += scan.slopeT[1][0];
\r
464 scan.t[1][1] += scan.slopeT[1][1];
\r
470 // rasterize lower sub-triangle
\r
471 if ( (f32) 0.0 != scan.invDeltaY[2] )
\r
473 // advance to middle point
\r
474 if( (f32) 0.0 != scan.invDeltaY[1] )
\r
476 temp[0] = b->Pos.y - a->Pos.y; // dy
\r
478 scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0];
\r
480 scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0];
\r
483 scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0];
\r
486 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0];
\r
489 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0];
\r
492 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0];
\r
497 // calculate slopes for bottom edge
\r
498 scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2];
\r
499 scan.x[1] = b->Pos.x;
\r
502 scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2];
\r
503 scan.z[1] = b->Pos.z;
\r
507 scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2];
\r
508 scan.w[1] = b->Pos.w;
\r
512 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2];
\r
513 scan.c[1] = b->Color[0];
\r
517 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2];
\r
518 scan.t[0][1] = b->Tex[0];
\r
522 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2];
\r
523 scan.t[1][1] = b->Tex[1];
\r
526 // apply top-left fill convention, top part
\r
527 yStart = fill_convention_left( b->Pos.y );
\r
528 yEnd = fill_convention_right( c->Pos.y );
\r
532 subPixel = ( (f32) yStart ) - b->Pos.y;
\r
534 // correct to pixel center
\r
535 scan.x[0] += scan.slopeX[0] * subPixel;
\r
536 scan.x[1] += scan.slopeX[1] * subPixel;
\r
539 scan.z[0] += scan.slopeZ[0] * subPixel;
\r
540 scan.z[1] += scan.slopeZ[1] * subPixel;
\r
544 scan.w[0] += scan.slopeW[0] * subPixel;
\r
545 scan.w[1] += scan.slopeW[1] * subPixel;
\r
549 scan.c[0] += scan.slopeC[0] * subPixel;
\r
550 scan.c[1] += scan.slopeC[1] * subPixel;
\r
554 scan.t[0][0] += scan.slopeT[0][0] * subPixel;
\r
555 scan.t[0][1] += scan.slopeT[0][1] * subPixel;
\r
559 scan.t[1][0] += scan.slopeT[1][0] * subPixel;
\r
560 scan.t[1][1] += scan.slopeT[1][1] * subPixel;
\r
565 // rasterize the edge scanlines
\r
566 for( line.y = yStart; line.y <= yEnd; line.y += SOFTWARE_DRIVER_2_STEP_Y)
\r
568 line.x[scan.left] = scan.x[0];
\r
569 line.x[scan.right] = scan.x[1];
\r
572 line.z[scan.left] = scan.z[0];
\r
573 line.z[scan.right] = scan.z[1];
\r
577 line.w[scan.left] = scan.w[0];
\r
578 line.w[scan.right] = scan.w[1];
\r
582 line.c[scan.left] = scan.c[0];
\r
583 line.c[scan.right] = scan.c[1];
\r
587 line.t[0][scan.left] = scan.t[0][0];
\r
588 line.t[0][scan.right] = scan.t[0][1];
\r
592 line.t[1][scan.left] = scan.t[1][0];
\r
593 line.t[1][scan.right] = scan.t[1][1];
\r
596 // render a scanline
\r
597 interlace_scanline fragmentShader();
\r
599 scan.x[0] += scan.slopeX[0];
\r
600 scan.x[1] += scan.slopeX[1];
\r
603 scan.z[0] += scan.slopeZ[0];
\r
604 scan.z[1] += scan.slopeZ[1];
\r
608 scan.w[0] += scan.slopeW[0];
\r
609 scan.w[1] += scan.slopeW[1];
\r
613 scan.c[0] += scan.slopeC[0];
\r
614 scan.c[1] += scan.slopeC[1];
\r
618 scan.t[0][0] += scan.slopeT[0][0];
\r
619 scan.t[0][1] += scan.slopeT[0][1];
\r
623 scan.t[1][0] += scan.slopeT[1][0];
\r
624 scan.t[1][1] += scan.slopeT[1][1];
\r
633 } // end namespace video
\r
634 } // end namespace irr
\r
636 #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
643 //! creates a flat triangle renderer
\r
644 IBurningShader* createTRTextureGouraudAdd2(CBurningVideoDriver* driver)
\r
646 //ETR_TEXTURE_GOURAUD_ADD
\r
648 #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
649 return new CTRTextureGouraudAdd2(driver);
\r
652 #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
\r
656 } // end namespace video
\r
657 } // end namespace irr
\r