/src/dep/src/irrlicht/CTRTextureLightMap2_Add.cpp

https://gitlab.com/Lumirion/M2Viewer · C++ · 672 lines · 486 code · 152 blank · 34 comment · 17 complexity · 79fd30705c610cbfe58c2d991df979c2 MD5 · raw file

  1. // Copyright (C) 2002-2012 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
  4. #include "IrrCompileConfig.h"
  5. #include "IBurningShader.h"
  6. #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
  7. // compile flag for this file
  8. #undef USE_ZBUFFER
  9. #undef IPOL_Z
  10. #undef CMP_Z
  11. #undef WRITE_Z
  12. #undef IPOL_W
  13. #undef CMP_W
  14. #undef WRITE_W
  15. #undef SUBTEXEL
  16. #undef INVERSE_W
  17. #undef IPOL_C0
  18. #undef IPOL_T0
  19. #undef IPOL_T1
  20. // define render case
  21. #define SUBTEXEL
  22. #define INVERSE_W
  23. #define USE_ZBUFFER
  24. #define IPOL_W
  25. #define CMP_W
  26. #define WRITE_W
  27. //#define IPOL_C0
  28. #define IPOL_T0
  29. #define IPOL_T1
  30. // apply global override
  31. #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
  32. #undef INVERSE_W
  33. #endif
  34. #ifndef SOFTWARE_DRIVER_2_SUBTEXEL
  35. #undef SUBTEXEL
  36. #endif
  37. #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR
  38. #undef IPOL_C0
  39. #endif
  40. #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER )
  41. #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
  42. #undef IPOL_W
  43. #endif
  44. #define IPOL_Z
  45. #ifdef CMP_W
  46. #undef CMP_W
  47. #define CMP_Z
  48. #endif
  49. #ifdef WRITE_W
  50. #undef WRITE_W
  51. #define WRITE_Z
  52. #endif
  53. #endif
  54. namespace irr
  55. {
  56. namespace video
  57. {
  58. class CTRTextureLightMap2_Add : public IBurningShader
  59. {
  60. public:
  61. //! constructor
  62. CTRTextureLightMap2_Add(CBurningVideoDriver* driver);
  63. //! draws an indexed triangle list
  64. virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c );
  65. private:
  66. void scanline_bilinear ();
  67. sScanConvertData scan;
  68. sScanLineData line;
  69. };
  70. //! constructor
  71. CTRTextureLightMap2_Add::CTRTextureLightMap2_Add(CBurningVideoDriver* driver)
  72. : IBurningShader(driver)
  73. {
  74. #ifdef _DEBUG
  75. setDebugName("CTRTextureLightMap2_Add");
  76. #endif
  77. }
  78. /*!
  79. */
  80. REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear ()
  81. {
  82. tVideoSample *dst;
  83. #ifdef USE_ZBUFFER
  84. fp24 *z;
  85. #endif
  86. s32 xStart;
  87. s32 xEnd;
  88. s32 dx;
  89. #ifdef SUBTEXEL
  90. f32 subPixel;
  91. #endif
  92. #ifdef IPOL_Z
  93. f32 slopeZ;
  94. #endif
  95. #ifdef IPOL_W
  96. fp24 slopeW;
  97. #endif
  98. #ifdef IPOL_C0
  99. sVec4 slopeC;
  100. #endif
  101. #ifdef IPOL_T0
  102. sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES];
  103. #endif
  104. // apply top-left fill-convention, left
  105. xStart = core::ceil32( line.x[0] );
  106. xEnd = core::ceil32( line.x[1] ) - 1;
  107. dx = xEnd - xStart;
  108. if ( dx < 0 )
  109. return;
  110. // slopes
  111. const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] );
  112. #ifdef IPOL_Z
  113. slopeZ = (line.z[1] - line.z[0]) * invDeltaX;
  114. #endif
  115. #ifdef IPOL_W
  116. slopeW = (line.w[1] - line.w[0]) * invDeltaX;
  117. #endif
  118. #ifdef IPOL_C0
  119. slopeC = (line.c[1] - line.c[0]) * invDeltaX;
  120. #endif
  121. #ifdef IPOL_T0
  122. slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX;
  123. #endif
  124. #ifdef IPOL_T1
  125. slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX;
  126. #endif
  127. #ifdef SUBTEXEL
  128. subPixel = ( (f32) xStart ) - line.x[0];
  129. #ifdef IPOL_Z
  130. line.z[0] += slopeZ * subPixel;
  131. #endif
  132. #ifdef IPOL_W
  133. line.w[0] += slopeW * subPixel;
  134. #endif
  135. #ifdef IPOL_C0
  136. line.c[0] += slopeC * subPixel;
  137. #endif
  138. #ifdef IPOL_T0
  139. line.t[0][0] += slopeT[0] * subPixel;
  140. #endif
  141. #ifdef IPOL_T1
  142. line.t[1][0] += slopeT[1] * subPixel;
  143. #endif
  144. #endif
  145. dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
  146. #ifdef USE_ZBUFFER
  147. z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
  148. #endif
  149. #ifdef BURNINGVIDEO_RENDERER_FAST
  150. u32 dIndex = ( line.y & 3 ) << 2;
  151. #else
  152. //
  153. tFixPoint r0, g0, b0;
  154. tFixPoint r1, g1, b1;
  155. #endif
  156. for ( s32 i = 0; i <= dx; i++ )
  157. {
  158. #ifdef CMP_Z
  159. if ( line.z[0] < z[i] )
  160. #endif
  161. #ifdef CMP_W
  162. if ( line.w[0] >= z[i] )
  163. #endif
  164. {
  165. #ifdef WRITE_Z
  166. z[i] = line.z[0];
  167. #endif
  168. #ifdef WRITE_W
  169. z[i] = line.w[0];
  170. #endif
  171. #ifdef BURNINGVIDEO_RENDERER_FAST
  172. #ifdef INVERSE_W
  173. const f32 inversew = fix_inverse32 ( line.w[0] );
  174. const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ];
  175. dst[i] = PixelAdd32 (
  176. getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew),
  177. d + tofix ( line.t[0][0].y,inversew) ),
  178. getTexel_plain ( &IT[1], d + tofix ( line.t[1][0].x,inversew),
  179. d + tofix ( line.t[1][0].y,inversew) )
  180. );
  181. #else
  182. const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ];
  183. dst[i] = PixelAdd32 (
  184. getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x),
  185. d + tofix ( line.t[0][0].y) ),
  186. getTexel_plain ( &IT[1], d + tofix ( line.t[1][0].x),
  187. d + tofix ( line.t[1][0].y) )
  188. );
  189. #endif
  190. #else
  191. const f32 inversew = fix_inverse32 ( line.w[0] );
  192. getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) );
  193. getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[0][1].x,inversew), tofix ( line.t[0][1].y,inversew) );
  194. dst[i] = fix_to_color ( clampfix_maxcolor ( r0 + r1 ),
  195. clampfix_maxcolor ( g0 + g1 ),
  196. clampfix_maxcolor ( b0 + b1 )
  197. );
  198. #endif
  199. }
  200. #ifdef IPOL_Z
  201. line.z[0] += slopeZ;
  202. #endif
  203. #ifdef IPOL_W
  204. line.w[0] += slopeW;
  205. #endif
  206. #ifdef IPOL_C0
  207. line.c[0] += slopeC;
  208. #endif
  209. #ifdef IPOL_T0
  210. line.t[0][0] += slopeT[0];
  211. #endif
  212. #ifdef IPOL_T1
  213. line.t[1][0] += slopeT[1];
  214. #endif
  215. }
  216. }
  217. void CTRTextureLightMap2_Add::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c )
  218. {
  219. // sort on height, y
  220. if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
  221. if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c);
  222. if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b);
  223. const f32 ca = c->Pos.y - a->Pos.y;
  224. const f32 ba = b->Pos.y - a->Pos.y;
  225. const f32 cb = c->Pos.y - b->Pos.y;
  226. // calculate delta y of the edges
  227. scan.invDeltaY[0] = core::reciprocal( ca );
  228. scan.invDeltaY[1] = core::reciprocal( ba );
  229. scan.invDeltaY[2] = core::reciprocal( cb );
  230. if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) )
  231. return;
  232. // find if the major edge is left or right aligned
  233. f32 temp[4];
  234. temp[0] = a->Pos.x - c->Pos.x;
  235. temp[1] = -ca;
  236. temp[2] = b->Pos.x - a->Pos.x;
  237. temp[3] = ba;
  238. scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1;
  239. scan.right = 1 - scan.left;
  240. // calculate slopes for the major edge
  241. scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0];
  242. scan.x[0] = a->Pos.x;
  243. #ifdef IPOL_Z
  244. scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0];
  245. scan.z[0] = a->Pos.z;
  246. #endif
  247. #ifdef IPOL_W
  248. scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0];
  249. scan.w[0] = a->Pos.w;
  250. #endif
  251. #ifdef IPOL_C0
  252. scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0];
  253. scan.c[0] = a->Color[0];
  254. #endif
  255. #ifdef IPOL_T0
  256. scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0];
  257. scan.t[0][0] = a->Tex[0];
  258. #endif
  259. #ifdef IPOL_T1
  260. scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0];
  261. scan.t[1][0] = a->Tex[1];
  262. #endif
  263. // top left fill convention y run
  264. s32 yStart;
  265. s32 yEnd;
  266. #ifdef SUBTEXEL
  267. f32 subPixel;
  268. #endif
  269. // rasterize upper sub-triangle
  270. if ( (f32) 0.0 != scan.invDeltaY[1] )
  271. {
  272. // calculate slopes for top edge
  273. scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1];
  274. scan.x[1] = a->Pos.x;
  275. #ifdef IPOL_Z
  276. scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1];
  277. scan.z[1] = a->Pos.z;
  278. #endif
  279. #ifdef IPOL_W
  280. scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1];
  281. scan.w[1] = a->Pos.w;
  282. #endif
  283. #ifdef IPOL_C0
  284. scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1];
  285. scan.c[1] = a->Color[0];
  286. #endif
  287. #ifdef IPOL_T0
  288. scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1];
  289. scan.t[0][1] = a->Tex[0];
  290. #endif
  291. #ifdef IPOL_T1
  292. scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1];
  293. scan.t[1][1] = a->Tex[1];
  294. #endif
  295. // apply top-left fill convention, top part
  296. yStart = core::ceil32( a->Pos.y );
  297. yEnd = core::ceil32( b->Pos.y ) - 1;
  298. #ifdef SUBTEXEL
  299. subPixel = ( (f32) yStart ) - a->Pos.y;
  300. // correct to pixel center
  301. scan.x[0] += scan.slopeX[0] * subPixel;
  302. scan.x[1] += scan.slopeX[1] * subPixel;
  303. #ifdef IPOL_Z
  304. scan.z[0] += scan.slopeZ[0] * subPixel;
  305. scan.z[1] += scan.slopeZ[1] * subPixel;
  306. #endif
  307. #ifdef IPOL_W
  308. scan.w[0] += scan.slopeW[0] * subPixel;
  309. scan.w[1] += scan.slopeW[1] * subPixel;
  310. #endif
  311. #ifdef IPOL_C0
  312. scan.c[0] += scan.slopeC[0] * subPixel;
  313. scan.c[1] += scan.slopeC[1] * subPixel;
  314. #endif
  315. #ifdef IPOL_T0
  316. scan.t[0][0] += scan.slopeT[0][0] * subPixel;
  317. scan.t[0][1] += scan.slopeT[0][1] * subPixel;
  318. #endif
  319. #ifdef IPOL_T1
  320. scan.t[1][0] += scan.slopeT[1][0] * subPixel;
  321. scan.t[1][1] += scan.slopeT[1][1] * subPixel;
  322. #endif
  323. #endif
  324. // rasterize the edge scanlines
  325. for( line.y = yStart; line.y <= yEnd; ++line.y)
  326. {
  327. line.x[scan.left] = scan.x[0];
  328. line.x[scan.right] = scan.x[1];
  329. #ifdef IPOL_Z
  330. line.z[scan.left] = scan.z[0];
  331. line.z[scan.right] = scan.z[1];
  332. #endif
  333. #ifdef IPOL_W
  334. line.w[scan.left] = scan.w[0];
  335. line.w[scan.right] = scan.w[1];
  336. #endif
  337. #ifdef IPOL_C0
  338. line.c[scan.left] = scan.c[0];
  339. line.c[scan.right] = scan.c[1];
  340. #endif
  341. #ifdef IPOL_T0
  342. line.t[0][scan.left] = scan.t[0][0];
  343. line.t[0][scan.right] = scan.t[0][1];
  344. #endif
  345. #ifdef IPOL_T1
  346. line.t[1][scan.left] = scan.t[1][0];
  347. line.t[1][scan.right] = scan.t[1][1];
  348. #endif
  349. // render a scanline
  350. scanline_bilinear ();
  351. scan.x[0] += scan.slopeX[0];
  352. scan.x[1] += scan.slopeX[1];
  353. #ifdef IPOL_Z
  354. scan.z[0] += scan.slopeZ[0];
  355. scan.z[1] += scan.slopeZ[1];
  356. #endif
  357. #ifdef IPOL_W
  358. scan.w[0] += scan.slopeW[0];
  359. scan.w[1] += scan.slopeW[1];
  360. #endif
  361. #ifdef IPOL_C0
  362. scan.c[0] += scan.slopeC[0];
  363. scan.c[1] += scan.slopeC[1];
  364. #endif
  365. #ifdef IPOL_T0
  366. scan.t[0][0] += scan.slopeT[0][0];
  367. scan.t[0][1] += scan.slopeT[0][1];
  368. #endif
  369. #ifdef IPOL_T1
  370. scan.t[1][0] += scan.slopeT[1][0];
  371. scan.t[1][1] += scan.slopeT[1][1];
  372. #endif
  373. }
  374. }
  375. // rasterize lower sub-triangle
  376. if ( (f32) 0.0 != scan.invDeltaY[2] )
  377. {
  378. // advance to middle point
  379. if( (f32) 0.0 != scan.invDeltaY[1] )
  380. {
  381. temp[0] = b->Pos.y - a->Pos.y; // dy
  382. scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0];
  383. #ifdef IPOL_Z
  384. scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0];
  385. #endif
  386. #ifdef IPOL_W
  387. scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0];
  388. #endif
  389. #ifdef IPOL_C0
  390. scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0];
  391. #endif
  392. #ifdef IPOL_T0
  393. scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0];
  394. #endif
  395. #ifdef IPOL_T1
  396. scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0];
  397. #endif
  398. }
  399. // calculate slopes for bottom edge
  400. scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2];
  401. scan.x[1] = b->Pos.x;
  402. #ifdef IPOL_Z
  403. scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2];
  404. scan.z[1] = b->Pos.z;
  405. #endif
  406. #ifdef IPOL_W
  407. scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2];
  408. scan.w[1] = b->Pos.w;
  409. #endif
  410. #ifdef IPOL_C0
  411. scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2];
  412. scan.c[1] = b->Color[0];
  413. #endif
  414. #ifdef IPOL_T0
  415. scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2];
  416. scan.t[0][1] = b->Tex[0];
  417. #endif
  418. #ifdef IPOL_T1
  419. scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2];
  420. scan.t[1][1] = b->Tex[1];
  421. #endif
  422. // apply top-left fill convention, top part
  423. yStart = core::ceil32( b->Pos.y );
  424. yEnd = core::ceil32( c->Pos.y ) - 1;
  425. #ifdef SUBTEXEL
  426. subPixel = ( (f32) yStart ) - b->Pos.y;
  427. // correct to pixel center
  428. scan.x[0] += scan.slopeX[0] * subPixel;
  429. scan.x[1] += scan.slopeX[1] * subPixel;
  430. #ifdef IPOL_Z
  431. scan.z[0] += scan.slopeZ[0] * subPixel;
  432. scan.z[1] += scan.slopeZ[1] * subPixel;
  433. #endif
  434. #ifdef IPOL_W
  435. scan.w[0] += scan.slopeW[0] * subPixel;
  436. scan.w[1] += scan.slopeW[1] * subPixel;
  437. #endif
  438. #ifdef IPOL_C0
  439. scan.c[0] += scan.slopeC[0] * subPixel;
  440. scan.c[1] += scan.slopeC[1] * subPixel;
  441. #endif
  442. #ifdef IPOL_T0
  443. scan.t[0][0] += scan.slopeT[0][0] * subPixel;
  444. scan.t[0][1] += scan.slopeT[0][1] * subPixel;
  445. #endif
  446. #ifdef IPOL_T1
  447. scan.t[1][0] += scan.slopeT[1][0] * subPixel;
  448. scan.t[1][1] += scan.slopeT[1][1] * subPixel;
  449. #endif
  450. #endif
  451. // rasterize the edge scanlines
  452. for( line.y = yStart; line.y <= yEnd; ++line.y)
  453. {
  454. line.x[scan.left] = scan.x[0];
  455. line.x[scan.right] = scan.x[1];
  456. #ifdef IPOL_Z
  457. line.z[scan.left] = scan.z[0];
  458. line.z[scan.right] = scan.z[1];
  459. #endif
  460. #ifdef IPOL_W
  461. line.w[scan.left] = scan.w[0];
  462. line.w[scan.right] = scan.w[1];
  463. #endif
  464. #ifdef IPOL_C0
  465. line.c[scan.left] = scan.c[0];
  466. line.c[scan.right] = scan.c[1];
  467. #endif
  468. #ifdef IPOL_T0
  469. line.t[0][scan.left] = scan.t[0][0];
  470. line.t[0][scan.right] = scan.t[0][1];
  471. #endif
  472. #ifdef IPOL_T1
  473. line.t[1][scan.left] = scan.t[1][0];
  474. line.t[1][scan.right] = scan.t[1][1];
  475. #endif
  476. // render a scanline
  477. scanline_bilinear ();
  478. scan.x[0] += scan.slopeX[0];
  479. scan.x[1] += scan.slopeX[1];
  480. #ifdef IPOL_Z
  481. scan.z[0] += scan.slopeZ[0];
  482. scan.z[1] += scan.slopeZ[1];
  483. #endif
  484. #ifdef IPOL_W
  485. scan.w[0] += scan.slopeW[0];
  486. scan.w[1] += scan.slopeW[1];
  487. #endif
  488. #ifdef IPOL_C0
  489. scan.c[0] += scan.slopeC[0];
  490. scan.c[1] += scan.slopeC[1];
  491. #endif
  492. #ifdef IPOL_T0
  493. scan.t[0][0] += scan.slopeT[0][0];
  494. scan.t[0][1] += scan.slopeT[0][1];
  495. #endif
  496. #ifdef IPOL_T1
  497. scan.t[1][0] += scan.slopeT[1][0];
  498. scan.t[1][1] += scan.slopeT[1][1];
  499. #endif
  500. }
  501. }
  502. }
  503. } // end namespace video
  504. } // end namespace irr
  505. #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
  506. namespace irr
  507. {
  508. namespace video
  509. {
  510. //! creates a flat triangle renderer
  511. IBurningShader* createTriangleRendererTextureLightMap2_Add(CBurningVideoDriver* driver)
  512. {
  513. #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
  514. return new CTRTextureLightMap2_Add(driver);
  515. #else
  516. return 0;
  517. #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
  518. }
  519. } // end namespace video
  520. } // end namespace irr