/opengles/src/RasterizerTriangles.inc

http://ftk.googlecode.com/ · Pascal · 1132 lines · 232 code · 112 blank · 788 comment · 36 complexity · 557db63d3e597d20535e24c8e17c4cae MD5 · raw file

  1. // ==========================================================================
  2. //
  3. // RasterizerTriangles.inc Rasterizer Class for 3D Rendering Library
  4. //
  5. // The rasterizer converts transformed and lit primitives and creates a
  6. // raster image in the current rendering surface.
  7. //
  8. // This files contains the triangle rasterization code, which was
  9. // previously in the Rasterizer.cpp source file.
  10. //
  11. // --------------------------------------------------------------------------
  12. //
  13. // 05-22-2004 Hans-Martin Will initial version
  14. //
  15. // --------------------------------------------------------------------------
  16. //
  17. // Copyright (c) 2004, Hans-Martin Will. All rights reserved.
  18. //
  19. // Redistribution and use in source and binary forms, with or without
  20. // modification, are permitted provided that the following conditions are
  21. // met:
  22. //
  23. // * Redistributions of source code must retain the above copyright
  24. // notice, this list of conditions and the following disclaimer.
  25. // * Redistributions in binary form must reproduce the above copyright
  26. // notice, this list of conditions and the following disclaimer in the
  27. // documentation and/or other materials provided with the distribution.
  28. //
  29. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  30. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  31. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  32. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  33. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  34. // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  35. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  36. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  37. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  38. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  39. // THE POSSIBILITY OF SUCH DAMAGE.
  40. //
  41. // ==========================================================================
  42. // The following macros need to be defined for this include file:
  43. //
  44. // InitScanlineStart
  45. // InitScanlineDeltas
  46. // RasterTriangle
  47. //
  48. // HasFog
  49. // HasDepth
  50. // HasColor
  51. // HasTexture
  52. // HasStencil
  53. // HasScissor
  54. #ifndef InitScanlineStart
  55. #error "InitScanlineStart is not defined"
  56. #endif
  57. #ifndef InitScanlineDeltas
  58. #error "InitScanlineDeltas is not defined"
  59. #endif
  60. #ifndef RasterTriangle
  61. #error "RasterTriangle is not defined"
  62. #endif
  63. #ifndef HasFog
  64. #error "HasFog is not defined"
  65. #endif
  66. #ifndef HasDepth
  67. #error "HasDepth is not defined"
  68. #endif
  69. #ifndef HasColor
  70. #error "HasColor is not defined"
  71. #endif
  72. #ifndef HasTexture
  73. #error "HasTexture is not defined"
  74. #endif
  75. #ifndef HasStencil
  76. #error "HasStencil is not defined"
  77. #endif
  78. #ifndef HasScissor
  79. #error "HasScissor is not defined"
  80. #endif
  81. namespace {
  82. inline void InitScanlineStart(const RasterInfo & rasterInfo, EdgePos & start, const Gradients & grad,
  83. EGL_Fixed xPreStep, EGL_Fixed yPreStep,
  84. const FractionalColor& color, EGL_Fixed fog, EGL_Fixed depth, EGL_Fixed invZ, EGL_Fixed tuOverZ[], EGL_Fixed tvOverZ[]) {
  85. #if HasDepth
  86. start.m_WindowCoords.depth =
  87. depth + EGL_Mul(grad.dx.m_WindowCoords.depth, xPreStep)
  88. + EGL_Mul(grad.dy.m_WindowCoords.depth, yPreStep);
  89. #endif
  90. #if HasColor
  91. start.m_Color.r =
  92. color.r + EGL_Mul(grad.dx.m_Color.r, xPreStep)
  93. + EGL_Mul(grad.dy.m_Color.r, yPreStep);
  94. start.m_Color.g =
  95. color.g + EGL_Mul(grad.dx.m_Color.g, xPreStep)
  96. + EGL_Mul(grad.dy.m_Color.g, yPreStep);
  97. start.m_Color.b =
  98. color.b + EGL_Mul(grad.dx.m_Color.b, xPreStep)
  99. + EGL_Mul(grad.dy.m_Color.b, yPreStep);
  100. start.m_Color.a =
  101. color.a + EGL_Mul(grad.dx.m_Color.a, xPreStep)
  102. + EGL_Mul(grad.dy.m_Color.a, yPreStep);
  103. #endif
  104. #if HasTexture
  105. start.m_WindowCoords.invZ =
  106. invZ + EGL_Mul(grad.dx.m_WindowCoords.invZ, xPreStep)
  107. + EGL_Mul(grad.dy.m_WindowCoords.invZ, yPreStep);
  108. for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
  109. if (!rasterInfo.Textures[index])
  110. continue;
  111. start.m_TextureCoords[index].tu =
  112. tuOverZ[index]
  113. + EGL_Mul(grad.dx.m_TextureCoords[index].tu, xPreStep)
  114. + EGL_Mul(grad.dy.m_TextureCoords[index].tu, yPreStep);
  115. start.m_TextureCoords[index].tv =
  116. tvOverZ[index]
  117. + EGL_Mul(grad.dx.m_TextureCoords[index].tv, xPreStep)
  118. + EGL_Mul(grad.dy.m_TextureCoords[index].tv, yPreStep);
  119. #if EGL_MIPMAP_PER_TEXEL
  120. // ------------------------------------------------------------------
  121. // Determine partial derivatives of texture functions,
  122. // see eq. (2) and (3) in
  123. // J. P. Ewins et al (1998),
  124. // "MIP-Map Level Selection for Texture Mapping",
  125. // IEEE Transactions on Visualization and Computer Graphics,
  126. // Vol 4, No. 4
  127. // ------------------------------------------------------------------
  128. start.m_TextureCoords[index].dtudx =
  129. Det2x2(grad.dx.m_TextureCoords[index].tu, tuOverZ[index], grad.dx.m_WindowCoords.invZ, invZ)
  130. + EGL_Mul(grad.dy.m_TextureCoords[index].dtudx, yPreStep);
  131. // Swap the following two assignments as reported by user
  132. start.m_TextureCoords[index].dtvdx =
  133. Det2x2(grad.dx.m_TextureCoords[index].tv, tvOverZ[index], grad.dx.m_WindowCoords.invZ, invZ)
  134. + EGL_Mul(grad.dx.m_TextureCoords[index].dtudy, xPreStep);
  135. start.m_TextureCoords[index].dtudy =
  136. Det2x2(grad.dy.m_TextureCoords[index].tu, tuOverZ[index], grad.dy.m_WindowCoords.invZ, invZ)
  137. + EGL_Mul(grad.dy.m_TextureCoords[index].dtvdx, yPreStep);
  138. start.m_TextureCoords[index].dtvdy =
  139. Det2x2(grad.dy.m_TextureCoords[index].tv, tvOverZ[index], grad.dy.m_WindowCoords.invZ, invZ)
  140. + EGL_Mul(grad.dx.m_TextureCoords[index].dtvdy, xPreStep);
  141. #endif
  142. }
  143. #endif
  144. #if HasFog
  145. start.m_FogDensity =
  146. fog + EGL_Mul(grad.dx.m_FogDensity, xPreStep)
  147. + EGL_Mul(grad.dy.m_FogDensity, yPreStep);
  148. #endif
  149. }
  150. inline void InitScanlineDeltas(const RasterInfo & rasterInfo, EdgePos & deltaSmall, EdgePos & deltaBig,
  151. const Gradients & gradients,
  152. EGL_Fixed dxdy, I32 dXdYStepInt) {
  153. deltaSmall.m_WindowCoords.x = dxdy; // x offset is stepped for each line (could consider removing fractional part from scanline function)
  154. #if HasDepth
  155. deltaSmall.m_WindowCoords.depth = gradients.dx.m_WindowCoords.depth * dXdYStepInt + gradients.dy.m_WindowCoords.depth;
  156. #endif
  157. #if HasColor
  158. deltaSmall.m_Color.r = gradients.dx.m_Color.r * dXdYStepInt + gradients.dy.m_Color.r;
  159. deltaSmall.m_Color.g = gradients.dx.m_Color.g * dXdYStepInt + gradients.dy.m_Color.g;
  160. deltaSmall.m_Color.b = gradients.dx.m_Color.b * dXdYStepInt + gradients.dy.m_Color.b;
  161. deltaSmall.m_Color.a = gradients.dx.m_Color.a * dXdYStepInt + gradients.dy.m_Color.a;
  162. #endif
  163. #if HasTexture
  164. deltaSmall.m_WindowCoords.invZ = gradients.dx.m_WindowCoords.invZ * dXdYStepInt + gradients.dy.m_WindowCoords.invZ;
  165. for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
  166. if (!rasterInfo.Textures[index])
  167. continue;
  168. deltaSmall.m_TextureCoords[index].tu =
  169. gradients.dx.m_TextureCoords[index].tu * dXdYStepInt
  170. + gradients.dy.m_TextureCoords[index].tu;
  171. deltaSmall.m_TextureCoords[index].tv =
  172. gradients.dx.m_TextureCoords[index].tv * dXdYStepInt
  173. + gradients.dy.m_TextureCoords[index].tv;
  174. #if EGL_MIPMAP_PER_TEXEL
  175. deltaSmall.m_TextureCoords[index].dtudx =
  176. gradients.dy.m_TextureCoords[index].dtudx;
  177. deltaSmall.m_TextureCoords[index].dtudy =
  178. gradients.dx.m_TextureCoords[index].dtudy * dXdYStepInt;
  179. deltaSmall.m_TextureCoords[index].dtvdx =
  180. gradients.dy.m_TextureCoords[index].dtvdx;
  181. deltaSmall.m_TextureCoords[index].dtvdy =
  182. gradients.dx.m_TextureCoords[index].dtvdy * dXdYStepInt;
  183. #endif
  184. }
  185. #endif
  186. #if HasFog
  187. deltaSmall.m_FogDensity = gradients.dx.m_FogDensity * dXdYStepInt + gradients.dy.m_FogDensity;
  188. #endif
  189. deltaBig.m_WindowCoords.x = dxdy;
  190. if (dxdy >= 0) {
  191. #if HasDepth
  192. deltaBig.m_WindowCoords.depth = deltaSmall.m_WindowCoords.depth + gradients.dx.m_WindowCoords.depth;
  193. #endif
  194. #if HasColor
  195. deltaBig.m_Color.r = deltaSmall.m_Color.r + gradients.dx.m_Color.r;
  196. deltaBig.m_Color.g = deltaSmall.m_Color.g + gradients.dx.m_Color.g;
  197. deltaBig.m_Color.b = deltaSmall.m_Color.b + gradients.dx.m_Color.b;
  198. deltaBig.m_Color.a = deltaSmall.m_Color.a + gradients.dx.m_Color.a;
  199. #endif
  200. #if HasTexture
  201. deltaBig.m_WindowCoords.invZ = deltaSmall.m_WindowCoords.invZ + gradients.dx.m_WindowCoords.invZ;
  202. for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
  203. if (!rasterInfo.Textures[index])
  204. continue;
  205. deltaBig.m_TextureCoords[index].tu = deltaSmall.m_TextureCoords[index].tu + gradients.dx.m_TextureCoords[index].tu;
  206. deltaBig.m_TextureCoords[index].tv = deltaSmall.m_TextureCoords[index].tv + gradients.dx.m_TextureCoords[index].tv;
  207. #if EGL_MIPMAP_PER_TEXEL
  208. deltaBig.m_TextureCoords[index].dtudx = deltaSmall.m_TextureCoords[index].dtudx;
  209. deltaBig.m_TextureCoords[index].dtudy = deltaSmall.m_TextureCoords[index].dtudy + gradients.dx.m_TextureCoords[index].dtudy;
  210. deltaBig.m_TextureCoords[index].dtvdx = deltaSmall.m_TextureCoords[index].dtvdx;
  211. deltaBig.m_TextureCoords[index].dtvdy = deltaSmall.m_TextureCoords[index].dtvdy + gradients.dx.m_TextureCoords[index].dtvdy;
  212. #endif
  213. }
  214. #endif
  215. #if HasFog
  216. deltaBig.m_FogDensity = deltaSmall.m_FogDensity + gradients.dx.m_FogDensity;
  217. #endif
  218. } else {
  219. #if HasDepth
  220. deltaBig.m_WindowCoords.depth = deltaSmall.m_WindowCoords.depth - gradients.dx.m_WindowCoords.depth;
  221. #endif
  222. #if HasColor
  223. deltaBig.m_Color.r = deltaSmall.m_Color.r - gradients.dx.m_Color.r;
  224. deltaBig.m_Color.g = deltaSmall.m_Color.g - gradients.dx.m_Color.g;
  225. deltaBig.m_Color.b = deltaSmall.m_Color.b - gradients.dx.m_Color.b;
  226. deltaBig.m_Color.a = deltaSmall.m_Color.a - gradients.dx.m_Color.a;
  227. #endif
  228. #if HasTexture
  229. deltaBig.m_WindowCoords.invZ = deltaSmall.m_WindowCoords.invZ - gradients.dx.m_WindowCoords.invZ;
  230. for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
  231. if (!rasterInfo.Textures[index])
  232. continue;
  233. deltaBig.m_TextureCoords[index].tu = deltaSmall.m_TextureCoords[index].tu - gradients.dx.m_TextureCoords[index].tu;
  234. deltaBig.m_TextureCoords[index].tv = deltaSmall.m_TextureCoords[index].tv - gradients.dx.m_TextureCoords[index].tv;
  235. #if EGL_MIPMAP_PER_TEXEL
  236. deltaBig.m_TextureCoords[index].dtudx = deltaSmall.m_TextureCoords[index].dtudx;
  237. deltaBig.m_TextureCoords[index].dtudy = deltaSmall.m_TextureCoords[index].dtudy - gradients.dx.m_TextureCoords[index].dtudy;
  238. deltaBig.m_TextureCoords[index].dtvdx = deltaSmall.m_TextureCoords[index].dtvdx;
  239. deltaBig.m_TextureCoords[index].dtvdy = deltaSmall.m_TextureCoords[index].dtvdy + gradients.dx.m_TextureCoords[index].dtvdy;
  240. #endif
  241. }
  242. #endif
  243. #if HasFog
  244. deltaBig.m_FogDensity = deltaSmall.m_FogDensity - gradients.dx.m_FogDensity;
  245. #endif
  246. }
  247. }
  248. // --------------------------------------------------------------------------
  249. // Scanline to scanline increment
  250. // --------------------------------------------------------------------------
  251. #if HasFog
  252. #define ScanlineDeltaFogBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  253. start.m_FogDensity += deltaBig.m_FogDensity;
  254. #define ScanlineDeltaFogSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  255. start.m_FogDensity += deltaSmall.m_FogDensity; \
  256. #else
  257. #define ScanlineDeltaFogBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
  258. #define ScanlineDeltaFogSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
  259. #endif
  260. #if HasDepth
  261. #define ScanlineDeltaDepthBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  262. start.m_WindowCoords.depth += deltaBig.m_WindowCoords.depth;
  263. #define ScanlineDeltaDepthSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  264. start.m_WindowCoords.depth += deltaSmall.m_WindowCoords.depth;
  265. #define ScanlineDeltaDepth(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  266. rasterInfo.DepthBuffer += rasterInfo.SurfaceWidth; \
  267. #else
  268. #define ScanlineDeltaDepthBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
  269. #define ScanlineDeltaDepthSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
  270. #define ScanlineDeltaDepth(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
  271. #endif
  272. #if HasTexture
  273. #if EGL_MIPMAP_PER_TEXEL
  274. #define ScanlineDeltaTextureBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  275. start.m_WindowCoords.invZ += deltaBig.m_WindowCoords.invZ; \
  276. for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) { \
  277. if (!m_RasterInfo.Textures[index]) continue; \
  278. start.m_TextureCoords[index].tu += deltaBig.m_TextureCoords[index].tu; \
  279. start.m_TextureCoords[index].tv += deltaBig.m_TextureCoords[index].tv; \
  280. start.m_TextureCoords[index].dtudx += deltaBig.m_TextureCoords[index].dtudx; \
  281. start.m_TextureCoords[index].dtudy += deltaBig.m_TextureCoords[index].dtudy; \
  282. start.m_TextureCoords[index].dtvdx += deltaBig.m_TextureCoords[index].dtvdx; \
  283. start.m_TextureCoords[index].dtvdy += deltaBig.m_TextureCoords[index].dtvdy; \
  284. }
  285. #define ScanlineDeltaTextureSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  286. start.m_WindowCoords.invZ += deltaSmall.m_WindowCoords.invZ; \
  287. for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) { \
  288. if (!m_RasterInfo.Textures[index]) continue; \
  289. start.m_TextureCoords[index].tu += deltaSmall.m_TextureCoords[index].tu; \
  290. start.m_TextureCoords[index].tv += deltaSmall.m_TextureCoords[index].tv; \
  291. start.m_TextureCoords[index].dtudx += deltaSmall.m_TextureCoords[index].dtudx; \
  292. start.m_TextureCoords[index].dtudy += deltaSmall.m_TextureCoords[index].dtudy; \
  293. start.m_TextureCoords[index].dtvdx += deltaSmall.m_TextureCoords[index].dtvdx; \
  294. start.m_TextureCoords[index].dtvdy += deltaSmall.m_TextureCoords[index].dtvdy; \
  295. }
  296. #else
  297. #define ScanlineDeltaTextureBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  298. start.m_WindowCoords.invZ += deltaBig.m_WindowCoords.invZ; \
  299. for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) { \
  300. if (!m_RasterInfo.Textures[index]) continue; \
  301. start.m_TextureCoords[index].tu += deltaBig.m_TextureCoords[index].tu; \
  302. start.m_TextureCoords[index].tv += deltaBig.m_TextureCoords[index].tv; \
  303. }
  304. #define ScanlineDeltaTextureSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  305. start.m_WindowCoords.invZ += deltaSmall.m_WindowCoords.invZ; \
  306. for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) { \
  307. if (!m_RasterInfo.Textures[index]) continue; \
  308. start.m_TextureCoords[index].tu += deltaSmall.m_TextureCoords[index].tu; \
  309. start.m_TextureCoords[index].tv += deltaSmall.m_TextureCoords[index].tv; \
  310. }
  311. #endif // EGL_MIPMAP_PER_TEXEL
  312. #else
  313. #define ScanlineDeltaTextureBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
  314. #define ScanlineDeltaTextureSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
  315. #endif
  316. #if HasColor
  317. #define ScanlineDeltaColorBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  318. start.m_Color += deltaBig.m_Color;
  319. #define ScanlineDeltaColorSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  320. start.m_Color += deltaSmall.m_Color;
  321. #else
  322. #define ScanlineDeltaColorBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
  323. #define ScanlineDeltaColorSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
  324. #endif
  325. #if HasStencil
  326. #define ScanlineDeltaStencil(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  327. rasterInfo.StencilBuffer += rasterInfo.SurfaceWidth;
  328. #else
  329. #define ScanlineDeltaStencil(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
  330. #endif
  331. #define ScanlineDelta(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  332. xError += xStepError; \
  333. if (xError >= EGL_ONE) { \
  334. xError -= EGL_ONE; \
  335. start.m_WindowCoords.x += deltaBig.m_WindowCoords.x; \
  336. ScanlineDeltaColorBig (rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  337. ScanlineDeltaTextureBig (rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  338. ScanlineDeltaFogBig (rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  339. ScanlineDeltaDepthBig (rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  340. } else { \
  341. start.m_WindowCoords.x += deltaSmall.m_WindowCoords.x; \
  342. ScanlineDeltaColorSmall (rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  343. ScanlineDeltaTextureSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  344. ScanlineDeltaFogSmall (rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  345. ScanlineDeltaDepthSmall (rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  346. } \
  347. delta.m_WindowCoords.x += dxdy; \
  348. ScanlineDeltaDepth (rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  349. ScanlineDeltaStencil(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
  350. rasterInfo.ColorBuffer += rasterInfo.SurfaceWidth; \
  351. rasterInfo.AlphaBuffer += rasterInfo.SurfaceWidth;
  352. }
  353. // ---------------------------------------------------------------------------
  354. // Ultimately, we have the following variantions on rastering a triangle:
  355. //
  356. // - With or without color
  357. // - With or without texture
  358. // - With or without depth
  359. // - With or without fog
  360. // - With or without alpha buffer
  361. // - With or without stencil buffer
  362. // - With or without scissor test
  363. //
  364. // ---------------------------------------------------------------------------
  365. // ---------------------------------------------------------------------------
  366. // Render the triangle specified by the three transformed and lit vertices
  367. // passed as arguments.
  368. //
  369. // Parameters:
  370. // a, b, c The three vertices of the triangle
  371. //
  372. // Returns:
  373. // N/A
  374. // --------------------------------------------------------------------------
  375. void Rasterizer :: RasterTriangle(const RasterPos& a, const RasterPos& b,
  376. const RasterPos& c) {
  377. // ----------------------------------------------------------------------
  378. // sort vertices by y
  379. // ----------------------------------------------------------------------
  380. const RasterPos * pos[3];
  381. pos[0] = &a;
  382. pos[1] = &b;
  383. pos[2] = &c;
  384. const I8 * permutation = SortPermutation(a.m_WindowCoords.y, b.m_WindowCoords.y, c.m_WindowCoords.y);
  385. const RasterPos &pos1 = *pos[permutation[0]];
  386. const RasterPos &pos2 = *pos[permutation[1]];
  387. const RasterPos &pos3 = *pos[permutation[2]];
  388. // ----------------------------------------------------------------------
  389. // Calculate the screen area of the triangle
  390. // ----------------------------------------------------------------------
  391. EGL_Fixed denominator =
  392. Det2x2(
  393. pos2.m_WindowCoords.x - pos1.m_WindowCoords.x, pos2.m_WindowCoords.y - pos1.m_WindowCoords.y,
  394. pos3.m_WindowCoords.x - pos1.m_WindowCoords.x, pos3.m_WindowCoords.y - pos1.m_WindowCoords.y);
  395. // ----------------------------------------------------------------------
  396. // calculate all gradients for interpolation
  397. // ----------------------------------------------------------------------
  398. EGL_Fixed invDenominator = 0;
  399. Gradients grad;
  400. EGL_Fixed tuOverZ1[EGL_NUM_TEXTURE_UNITS],
  401. tuOverZ2[EGL_NUM_TEXTURE_UNITS],
  402. tuOverZ3[EGL_NUM_TEXTURE_UNITS],
  403. tvOverZ1[EGL_NUM_TEXTURE_UNITS],
  404. tvOverZ2[EGL_NUM_TEXTURE_UNITS],
  405. tvOverZ3[EGL_NUM_TEXTURE_UNITS];
  406. if (!denominator) {
  407. memset(&grad, 0, sizeof grad);
  408. } else {
  409. invDenominator = EGL_Inverse(denominator);
  410. #if HasColor
  411. SOLVE_XY(m_Color.r, invDenominator);
  412. SOLVE_XY(m_Color.g, invDenominator);
  413. SOLVE_XY(m_Color.b, invDenominator);
  414. SOLVE_XY(m_Color.a, invDenominator);
  415. #endif
  416. #if HasFog
  417. SOLVE_XY(m_FogDensity, invDenominator);
  418. #endif
  419. #if HasDepth
  420. SOLVE_XY(m_WindowCoords.depth, invDenominator);
  421. #endif
  422. #if HasTexture
  423. SOLVE_XY(m_WindowCoords.invZ, invDenominator);
  424. for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
  425. if (!m_RasterInfo.Textures[index])
  426. continue;
  427. tuOverZ1[index] = EGL_Mul(pos1.m_TextureCoords[index].tu, pos1.m_WindowCoords.invZ);
  428. tuOverZ2[index] = EGL_Mul(pos2.m_TextureCoords[index].tu, pos2.m_WindowCoords.invZ);
  429. tuOverZ3[index] = EGL_Mul(pos3.m_TextureCoords[index].tu, pos3.m_WindowCoords.invZ);
  430. tvOverZ1[index] = EGL_Mul(pos1.m_TextureCoords[index].tv, pos1.m_WindowCoords.invZ);
  431. tvOverZ2[index] = EGL_Mul(pos2.m_TextureCoords[index].tv, pos2.m_WindowCoords.invZ);
  432. tvOverZ3[index] = EGL_Mul(pos3.m_TextureCoords[index].tv, pos3.m_WindowCoords.invZ);
  433. SOLVE_PARAM_XY(m_TextureCoords[index].tu, tuOverZ1[index], tuOverZ2[index], tuOverZ3[index], invDenominator);
  434. SOLVE_PARAM_XY(m_TextureCoords[index].tv, tvOverZ1[index], tvOverZ2[index], tvOverZ3[index], invDenominator);
  435. #if EGL_MIPMAP_PER_TEXEL
  436. // ------------------------------------------------------------------
  437. // Determine partial derivatives of texture functions,
  438. // see eq. (2) and (3) in
  439. // J. P. Ewins et al (1998),
  440. // "MIP-Map Level Selection for Texture Mapping",
  441. // IEEE Transactions on Visualization and Computer Graphics,
  442. // Vol 4, No. 4
  443. // ------------------------------------------------------------------
  444. EGL_Fixed A = grad.dx.m_TextureCoords[index].tu;
  445. EGL_Fixed B = grad.dy.m_TextureCoords[index].tu;
  446. EGL_Fixed D = grad.dx.m_WindowCoords.invZ;
  447. EGL_Fixed E = grad.dy.m_WindowCoords.invZ;
  448. EGL_Fixed F = pos1.m_WindowCoords.invZ;
  449. EGL_Fixed G = grad.dx.m_TextureCoords[index].tv;
  450. EGL_Fixed H = grad.dy.m_TextureCoords[index].tv;
  451. EGL_Fixed K1 = Det2x2(A, B, D, E);
  452. EGL_Fixed K2 = Det2x2(G, H, D, E);
  453. grad.dy.m_TextureCoords[index].dtudx = K1;
  454. grad.dy.m_TextureCoords[index].dtudy = 0;
  455. grad.dy.m_TextureCoords[index].dtvdx = K2;
  456. grad.dy.m_TextureCoords[index].dtvdy = 0;
  457. grad.dx.m_TextureCoords[index].dtudx = 0;
  458. grad.dx.m_TextureCoords[index].dtudy = -K1;
  459. grad.dx.m_TextureCoords[index].dtvdx = 0;
  460. grad.dx.m_TextureCoords[index].dtvdy = -K2;
  461. #endif
  462. }
  463. #endif
  464. }
  465. // ----------------------------------------------------------------------
  466. // Constants to determine partial derivatives, see eq. (2) and (3) in
  467. // J. P. Ewins et al (1998), "MIP-Map Level Selection for Texture Mapping",
  468. // IEEE Transactions on Visualization and Computer Graphics, Vol 4, No. 4
  469. // ----------------------------------------------------------------------
  470. // Share the gradient in x direction for scanline function
  471. EdgePos& delta = grad.dx;
  472. // ----------------------------------------------------------------------
  473. // determine if the depth coordinate needs to be adjusted to
  474. // support polygon-offset
  475. // ----------------------------------------------------------------------
  476. //#if HasDepth
  477. EGL_Fixed depth1 = pos1.m_WindowCoords.depth;
  478. EGL_Fixed depth2 = pos2.m_WindowCoords.depth;
  479. EGL_Fixed depth3 = pos3.m_WindowCoords.depth;
  480. //#endif
  481. #if HasDepth
  482. if (m_State->m_Polygon.OffsetFillEnabled) {
  483. EGL_Fixed factor = m_State->m_Polygon.OffsetFactor;
  484. EGL_Fixed units = m_State->m_Polygon.OffsetUnits;
  485. // calculation here
  486. EGL_Fixed gradX = EGL_Abs(grad.dx.m_WindowCoords.depth);
  487. EGL_Fixed gradY = EGL_Abs(grad.dy.m_WindowCoords.depth);
  488. EGL_Fixed depthSlope = gradX > gradY ? gradX : gradY;
  489. I32 offset = EGL_Mul(factor, depthSlope) + EGL_IntFromFixed(units * PolygonOffsetUnitSize);
  490. if (offset > 0) {
  491. depth1 = depth1 < DepthRangeMax - offset ? depth1 + offset : DepthRangeMax;
  492. depth2 = depth2 < DepthRangeMax - offset ? depth2 + offset : DepthRangeMax;
  493. depth3 = depth3 < DepthRangeMax - offset ? depth3 + offset : DepthRangeMax;
  494. } else {
  495. depth1 = depth1 > -offset ? depth1 + offset : 0;
  496. depth2 = depth2 > -offset ? depth2 + offset : 0;
  497. depth3 = depth3 > -offset ? depth3 + offset : 0;
  498. }
  499. }
  500. #endif
  501. // ----------------------------------------------------------------------
  502. // determine the appropriate mipmapping level
  503. // ----------------------------------------------------------------------
  504. //#if HasTexture
  505. EGL_Fixed invZ1 = pos1.m_WindowCoords.invZ;
  506. EGL_Fixed invZ2 = pos2.m_WindowCoords.invZ;
  507. EGL_Fixed invZ3 = pos3.m_WindowCoords.invZ;
  508. //#endif
  509. #if !EGL_MIPMAP_PER_TEXEL && HasTexture
  510. for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
  511. if (!m_RasterInfo.Textures[index])
  512. continue;
  513. if (m_UseMipmap[index]) {
  514. int logWidth = Log2(m_Texture[index]->GetTexture(0)->GetWidth());
  515. int logHeight = Log2(m_Texture[index]->GetTexture(0)->GetHeight());
  516. int maxLevel = m_RasterInfo.MaxMipmapLevel[index];
  517. if (invDenominator) {
  518. EGL_Fixed textureArea =
  519. Det2x2(
  520. (pos2.m_TextureCoords[index].tu - pos1.m_TextureCoords[index].tu) << logWidth,
  521. (pos2.m_TextureCoords[index].tv - pos1.m_TextureCoords[index].tv) << logHeight,
  522. (pos3.m_TextureCoords[index].tu - pos1.m_TextureCoords[index].tu) << logWidth,
  523. (pos3.m_TextureCoords[index].tv - pos1.m_TextureCoords[index].tv) << logHeight);
  524. EGL_Fixed ratio = EGL_Mul(textureArea, invDenominator) >> EGL_PRECISION;
  525. int logRatio = Log2(ratio);
  526. if (logRatio <= 0) {
  527. m_RasterInfo.MipmapLevel[index] = 0;
  528. } else {
  529. m_RasterInfo.MipmapLevel[index] = logRatio / 2;
  530. if (m_RasterInfo.MipmapLevel[index] > maxLevel) {
  531. m_RasterInfo.MipmapLevel[index] = maxLevel;
  532. }
  533. }
  534. } else {
  535. m_RasterInfo.MipmapLevel[index] = maxLevel;
  536. }
  537. } else {
  538. m_RasterInfo.MipmapLevel[index] = 0;
  539. }
  540. }
  541. #endif
  542. // ----------------------------------------------------------------------
  543. //
  544. // - Raster top part of triangle
  545. // determine integer (i.e. each line) and fractional increments per edgebuffer
  546. // determine y-pre step and x-pre step for first pixel of first scanline
  547. // determine error for x-stepping.
  548. //
  549. // - Raster bottom part of triangle
  550. // ----------------------------------------------------------------------
  551. EGL_Fixed yRounded1 = EGL_NearestInt(pos1.m_WindowCoords.y);
  552. EGL_Fixed yPreStep1 = yRounded1 + (EGL_ONE/2) - pos1.m_WindowCoords.y;
  553. I32 y = EGL_IntFromFixed(yRounded1);
  554. EGL_Fixed yRounded2 = EGL_NearestInt(pos2.m_WindowCoords.y);
  555. EGL_Fixed yPreStep2 = yRounded2 + (EGL_ONE/2) - pos2.m_WindowCoords.y;
  556. I32 y2 = EGL_IntFromFixed(yRounded2);
  557. EGL_Fixed yRounded3 = EGL_NearestInt(pos3.m_WindowCoords.y);
  558. I32 y3 = EGL_IntFromFixed(yRounded3);
  559. m_RasterInfo.Init(m_Surface, y);
  560. I32 yScissorStart = m_State->m_ScissorTest.Y;
  561. I32 yScissorEnd = yScissorStart + m_State->m_ScissorTest.Height;
  562. // ----------------------------------------------------------------------
  563. // Determine edge increments and scanline starting point
  564. // ----------------------------------------------------------------------
  565. EGL_Fixed deltaY2 = pos2.m_WindowCoords.y - pos1.m_WindowCoords.y;
  566. EGL_Fixed deltaY3 = pos3.m_WindowCoords.y - pos1.m_WindowCoords.y;
  567. EGL_Fixed deltaY23 = pos3.m_WindowCoords.y - pos2.m_WindowCoords.y;
  568. if (y >= y3) {
  569. // Always, the triangle is empty
  570. return;
  571. }
  572. if (y == y2) {
  573. // do special case here
  574. EGL_Fixed invDeltaY3 = EGL_Inverse(deltaY3); // deltaY3 == 0 should not occur, triangle would already have been skipped
  575. EGL_Fixed invDeltaY23 = EGL_Inverse(deltaY23);
  576. EGL_Fixed deltaX3 = pos3.m_WindowCoords.x - pos1.m_WindowCoords.x;
  577. EGL_Fixed deltaX23 = pos3.m_WindowCoords.x - pos2.m_WindowCoords.x;
  578. EGL_Fixed dXdY3 = EGL_Mul(deltaX3, invDeltaY3);
  579. EGL_Fixed dXdY23 = EGL_Mul(deltaX23, invDeltaY23);
  580. if (dXdY23 < dXdY3) {
  581. // move beginning of scanline along p1->p3
  582. // ------------------------------------------------------------------
  583. // initialize start onto first pixel right off line p1->p3
  584. // ------------------------------------------------------------------
  585. EGL_Fixed xStepped1L = pos1.m_WindowCoords.x + EGL_Mul(yPreStep1, dXdY3);
  586. EGL_Fixed xRounded1 = EGL_NearestInt(xStepped1L);
  587. EGL_Fixed xPreStep1 = xRounded1 + (EGL_ONE/2) - pos1.m_WindowCoords.x;
  588. EdgePos start;
  589. start.m_WindowCoords.x =
  590. xStepped1L + ((EGL_ONE/2) - 1); // added offset so round down will be round to nearest
  591. InitScanlineStart(m_RasterInfo, start, grad, xPreStep1, yPreStep1,
  592. pos1.m_Color, pos1.m_FogDensity, depth1, invZ1, tuOverZ1, tvOverZ1);
  593. // ------------------------------------------------------------------
  594. // initialize edge buffer delta2Int & delta2Frac
  595. // ------------------------------------------------------------------
  596. // determine integer x step/y
  597. I32 dXdYStep1Int = dXdY3 >= 0 ? EGL_IntFromFixed(dXdY3) : -EGL_IntFromFixed(-dXdY3);
  598. EdgePos delta3Small, delta3Big;
  599. InitScanlineDeltas(m_RasterInfo, delta3Small, delta3Big, grad, dXdY3, dXdYStep1Int);
  600. // ------------------------------------------------------------------
  601. // Stepping for right edge
  602. // ------------------------------------------------------------------
  603. EGL_Fixed xStepped1R = pos2.m_WindowCoords.x + EGL_Mul(pos1.m_WindowCoords.y - pos2.m_WindowCoords.y + yPreStep1, dXdY23);
  604. delta.m_WindowCoords.x =
  605. xStepped1R + ((EGL_ONE/2) - 1); // added offset so round down will be round to nearest
  606. // ------------------------------------------------------------------
  607. // initialize the x-step error
  608. // ------------------------------------------------------------------
  609. EGL_Fixed xStepError, xError;
  610. if (dXdY3 >= 0) {
  611. xStepError = dXdY3 - EGL_FixedFromInt(dXdYStep1Int);
  612. assert(xStepError >= 0 && xStepError < EGL_ONE);
  613. xError = EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
  614. } else {
  615. xStepError = -dXdY3 + EGL_FixedFromInt(dXdYStep1Int);
  616. assert(xStepError >= 0 && xStepError < EGL_ONE);
  617. xError = (EGL_ONE-1) - EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
  618. }
  619. // ------------------------------------------------------------------
  620. // Raster the top part of the triangle
  621. // ------------------------------------------------------------------
  622. for (; y < y3; ++y) {
  623. #if HasScissor
  624. if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
  625. #endif
  626. RasterScanLine(m_RasterInfo, start, delta);
  627. ScanlineDelta(m_RasterInfo, start, delta, delta3Small, delta3Big,
  628. xError, xStepError, dXdY23);
  629. }
  630. } else {
  631. // move beginning of scanline along p2->p3
  632. // ------------------------------------------------------------------
  633. // now do second part of triangle
  634. //
  635. // ------------------------------------------------------------------
  636. //
  637. // initialize start onto first pixel right off line p2->p3
  638. // ------------------------------------------------------------------
  639. EGL_Fixed xStepped2L = pos2.m_WindowCoords.x + EGL_Mul(yPreStep2, dXdY23);
  640. EGL_Fixed xRounded2 = EGL_NearestInt(xStepped2L);
  641. EGL_Fixed xPreStep2 = xRounded2 + (EGL_ONE/2) - pos2.m_WindowCoords.x;
  642. EdgePos start;
  643. start.m_WindowCoords.x =
  644. xStepped2L + ((EGL_ONE/2) - 1); // added offset so round down will be round to nearest
  645. InitScanlineStart(m_RasterInfo, start, grad, xPreStep2, yPreStep1,
  646. pos2.m_Color, pos2.m_FogDensity, depth2, invZ2, tuOverZ2, tvOverZ2);
  647. // ------------------------------------------------------------------
  648. // initialize edge buffer delta2Int & delta2Frac
  649. // ------------------------------------------------------------------
  650. // determine integer x step/y
  651. I32 dXdYStep2Int = dXdY23 >= 0 ? EGL_IntFromFixed(dXdY23) : -EGL_IntFromFixed(-dXdY23);
  652. EdgePos delta23Small, delta23Big;
  653. InitScanlineDeltas(m_RasterInfo, delta23Small, delta23Big, grad, dXdY23, dXdYStep2Int);
  654. // ------------------------------------------------------------------
  655. // initialize the x coordinate for right edge
  656. // ------------------------------------------------------------------
  657. EGL_Fixed xStepped1R = pos1.m_WindowCoords.x + EGL_Mul(pos2.m_WindowCoords.y - pos1.m_WindowCoords.y + yPreStep2, dXdY3);
  658. delta.m_WindowCoords.x =
  659. xStepped1R + ((EGL_ONE/2) - 1); // added offset so round down will be round to nearest
  660. // ------------------------------------------------------------------
  661. // initialize the x-step error
  662. // ------------------------------------------------------------------
  663. EGL_Fixed xStepError, xError;
  664. if (dXdY23 >= 0) {
  665. xStepError = dXdY23 - EGL_FixedFromInt(dXdYStep2Int);
  666. assert(xStepError >= 0 && xStepError < EGL_ONE);
  667. xError = EGL_FractionFromFixed(xStepped2L + EGL_ONE/2);
  668. } else {
  669. xStepError = -dXdY23 + EGL_FixedFromInt(dXdYStep2Int);
  670. assert(xStepError >= 0 && xStepError < EGL_ONE);
  671. xError = (EGL_ONE-1) - EGL_FractionFromFixed(xStepped2L + EGL_ONE/2);
  672. }
  673. // ------------------------------------------------------------------
  674. // Raster the triangle
  675. // ------------------------------------------------------------------
  676. for (; y < y3; ++y) {
  677. #if HasScissor
  678. if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
  679. #endif
  680. RasterScanLine(m_RasterInfo, start, delta);
  681. ScanlineDelta(m_RasterInfo, start, delta, delta23Small, delta23Big,
  682. xError, xStepError, dXdY3);
  683. }
  684. }
  685. return;
  686. }
  687. EGL_Fixed invDeltaY2 = EGL_Inverse(deltaY2);
  688. EGL_Fixed invDeltaY3 = EGL_Inverse(deltaY3); // deltaY3 == 0 should not occur, triangle would already have been skipped
  689. EGL_Fixed deltaX2 = pos2.m_WindowCoords.x - pos1.m_WindowCoords.x;
  690. EGL_Fixed deltaX3 = pos3.m_WindowCoords.x - pos1.m_WindowCoords.x;
  691. EGL_Fixed dXdY2 = EGL_Mul(deltaX2, invDeltaY2);
  692. EGL_Fixed dXdY3 = EGL_Mul(deltaX3, invDeltaY3);
  693. if (dXdY2 < dXdY3) {
  694. // ------------------------------------------------------------------
  695. // initialize start onto first pixel right off line p1->p2
  696. // ------------------------------------------------------------------
  697. EGL_Fixed xStepped1L = pos1.m_WindowCoords.x + EGL_Mul(yPreStep1, dXdY2);
  698. EGL_Fixed xStepped1R = pos1.m_WindowCoords.x + EGL_Mul(yPreStep1, dXdY3);
  699. EGL_Fixed xRounded1 = EGL_NearestInt(xStepped1L);
  700. EGL_Fixed xPreStep1 = xRounded1 + (EGL_ONE/2) - pos1.m_WindowCoords.x;
  701. EdgePos start;
  702. start.m_WindowCoords.x =
  703. xStepped1L + ((EGL_ONE/2) - 1); // added offset so round down will be round to nearest
  704. InitScanlineStart(m_RasterInfo, start, grad, xPreStep1, yPreStep1,
  705. pos1.m_Color, pos1.m_FogDensity, depth1, invZ1, tuOverZ1, tvOverZ1);
  706. // ------------------------------------------------------------------
  707. // initialize edge buffer delta2Int & delta2Frac
  708. // ------------------------------------------------------------------
  709. // determine integer x step/y
  710. I32 dXdYStep1Int = dXdY2 >= 0 ? EGL_IntFromFixed(dXdY2) : -EGL_IntFromFixed(-dXdY2);
  711. EdgePos delta2Small, delta2Big;
  712. InitScanlineDeltas(m_RasterInfo, delta2Small, delta2Big, grad, dXdY2, dXdYStep1Int);
  713. // ------------------------------------------------------------------
  714. // initialize the x coordinate for right edge
  715. // ------------------------------------------------------------------
  716. delta.m_WindowCoords.x =
  717. xStepped1R + ((EGL_ONE/2) - 1); // added offset so round down will be round to nearest
  718. // ------------------------------------------------------------------
  719. // initialize the x-step error
  720. // ------------------------------------------------------------------
  721. EGL_Fixed xStepError, xError;
  722. if (dXdY2 >= 0) {
  723. xStepError = dXdY2 - EGL_FixedFromInt(dXdYStep1Int);
  724. assert(xStepError >= 0 && xStepError < EGL_ONE);
  725. xError = EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
  726. assert(xError >= 0 && xError < EGL_ONE);
  727. } else {
  728. xStepError = -dXdY2 + EGL_FixedFromInt(dXdYStep1Int);
  729. assert(xStepError >= 0 && xStepError < EGL_ONE);
  730. xError = (EGL_ONE-1) - EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
  731. assert(xError >= 0 && xError < EGL_ONE);
  732. }
  733. // ------------------------------------------------------------------
  734. // Raster the top part of the triangle
  735. // ------------------------------------------------------------------
  736. for (; y < y2; ++y) {
  737. #if HasScissor
  738. if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
  739. #endif
  740. RasterScanLine(m_RasterInfo, start, delta);
  741. ScanlineDelta(m_RasterInfo, start, delta, delta2Small, delta2Big,
  742. xError, xStepError, dXdY3);
  743. }
  744. if (y >= y3)
  745. return;
  746. EGL_Fixed invDeltaY23 = EGL_Inverse(deltaY23);
  747. EGL_Fixed deltaX23 = pos3.m_WindowCoords.x - pos2.m_WindowCoords.x;
  748. EGL_Fixed dXdY23 = EGL_Mul(deltaX23, invDeltaY23);
  749. // ------------------------------------------------------------------
  750. // now do second part of triangle
  751. //
  752. // ------------------------------------------------------------------
  753. //
  754. // initialize start onto first pixel right off line p2->p3
  755. // ------------------------------------------------------------------
  756. EGL_Fixed xStepped2L = pos2.m_WindowCoords.x + EGL_Mul(yPreStep2, dXdY23);
  757. EGL_Fixed xRounded2 = EGL_NearestInt(xStepped2L);
  758. EGL_Fixed xPreStep2 = xRounded2 + (EGL_ONE/2) - pos2.m_WindowCoords.x;
  759. start.m_WindowCoords.x =
  760. xStepped2L + ((EGL_ONE/2) - 1); // added offset so round down will be round to nearest
  761. InitScanlineStart(m_RasterInfo, start, grad, xPreStep2, yPreStep2,
  762. pos2.m_Color, pos2.m_FogDensity, depth2, invZ2, tuOverZ2, tvOverZ2);
  763. // ------------------------------------------------------------------
  764. // initialize edge buffer delta2Int & delta2Frac
  765. // ------------------------------------------------------------------
  766. // determine integer x step/y
  767. I32 dXdYStep2Int = dXdY23 >= 0 ? EGL_IntFromFixed(dXdY23) : -EGL_IntFromFixed(-dXdY23);
  768. EdgePos delta23Small, delta23Big;
  769. InitScanlineDeltas(m_RasterInfo, delta23Small, delta23Big, grad, dXdY23, dXdYStep2Int);
  770. // ------------------------------------------------------------------
  771. // initialize the x-step error
  772. // ------------------------------------------------------------------
  773. if (dXdY23 >= 0) {
  774. xStepError = dXdY23 - EGL_FixedFromInt(dXdYStep2Int);
  775. assert(xStepError >= 0 && xStepError < EGL_ONE);
  776. xError = EGL_FractionFromFixed(xStepped2L + EGL_ONE/2);
  777. } else {
  778. xStepError = -dXdY23 + EGL_FixedFromInt(dXdYStep2Int);
  779. assert(xStepError >= 0 && xStepError < EGL_ONE);
  780. xError = (EGL_ONE-1) - EGL_FractionFromFixed(xStepped2L + EGL_ONE/2);
  781. }
  782. // ------------------------------------------------------------------
  783. // Raster the bottom part of the triangle
  784. // ------------------------------------------------------------------
  785. for (; y < y3; ++y) {
  786. #if HasScissor
  787. if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
  788. #endif
  789. RasterScanLine(m_RasterInfo, start, delta);
  790. ScanlineDelta(m_RasterInfo, start, delta, delta23Small, delta23Big,
  791. xError, xStepError, dXdY3);
  792. }
  793. } else /* dXdY2 >= dXdY3) */ {
  794. // ------------------------------------------------------------------
  795. // initialize start onto first pixel right off line p1->p3
  796. // ------------------------------------------------------------------
  797. EGL_Fixed xStepped1L = pos1.m_WindowCoords.x + EGL_Mul(yPreStep1, dXdY3);
  798. EGL_Fixed xRounded1 = EGL_NearestInt(xStepped1L);
  799. EGL_Fixed xPreStep1 = xRounded1 + (EGL_ONE/2) - pos1.m_WindowCoords.x;
  800. EdgePos start;
  801. start.m_WindowCoords.x = xStepped1L + ((EGL_ONE/2) - 1); // added offset so round down will be round to nearest
  802. InitScanlineStart(m_RasterInfo, start, grad, xPreStep1, yPreStep1,
  803. pos1.m_Color, pos1.m_FogDensity, depth1, invZ1, tuOverZ1, tvOverZ1);
  804. // ------------------------------------------------------------------
  805. // initialize edge buffer delta2Int & delta2Frac
  806. // ------------------------------------------------------------------
  807. // determine integer x step/y
  808. I32 dXdYStep1Int = dXdY3 >= 0 ? EGL_IntFromFixed(dXdY3) : -EGL_IntFromFixed(-dXdY3);
  809. EdgePos delta3Small, delta3Big;
  810. InitScanlineDeltas(m_RasterInfo, delta3Small, delta3Big, grad, dXdY3, dXdYStep1Int);
  811. // ------------------------------------------------------------------
  812. // initialize the x coordinate for right edge
  813. // ------------------------------------------------------------------
  814. EGL_Fixed xStepped1R = pos1.m_WindowCoords.x + EGL_Mul(yPreStep1, dXdY2);
  815. delta.m_WindowCoords.x =
  816. xStepped1R + ((EGL_ONE/2) - 1); // added offset so round down will be round to nearest
  817. // ------------------------------------------------------------------
  818. // initialize the x-step error
  819. // ------------------------------------------------------------------
  820. EGL_Fixed xStepError, xError;
  821. if (dXdY3 >= 0) {
  822. xStepError = dXdY3 - EGL_FixedFromInt(dXdYStep1Int);
  823. assert(xStepError >= 0 && xStepError < EGL_ONE);
  824. xError = EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
  825. } else {
  826. xStepError = -dXdY3 + EGL_FixedFromInt(dXdYStep1Int);
  827. assert(xStepError >= 0 && xStepError < EGL_ONE);
  828. xError = (EGL_ONE-1) - EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
  829. }
  830. // ------------------------------------------------------------------
  831. // Raster the top part of the triangle
  832. // ------------------------------------------------------------------
  833. for (; y < y2; ++y) {
  834. #if HasScissor
  835. if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
  836. #endif
  837. RasterScanLine(m_RasterInfo, start, delta);
  838. ScanlineDelta(m_RasterInfo, start, delta, delta3Small, delta3Big,
  839. xError, xStepError, dXdY2);
  840. }
  841. if (y >= y3)
  842. return;
  843. EGL_Fixed invDeltaY23 = EGL_Inverse(deltaY23);
  844. EGL_Fixed deltaX23 = pos3.m_WindowCoords.x - pos2.m_WindowCoords.x;
  845. EGL_Fixed dXdY23 = EGL_Mul(deltaX23, invDeltaY23);
  846. // ------------------------------------------------------------------
  847. // now do second part of triangle
  848. //
  849. // ------------------------------------------------------------------
  850. //
  851. // initialize end behind first pixel right off line p2->p3
  852. // ------------------------------------------------------------------
  853. EGL_Fixed xStepped2R = pos2.m_WindowCoords.x + EGL_Mul(yPreStep2, dXdY23);
  854. delta.m_WindowCoords.x =
  855. xStepped2R + ((EGL_ONE/2) - 1); // added offset so round down will be round to nearest
  856. for (; y < y3; ++y) {
  857. #if HasScissor
  858. if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
  859. #endif
  860. RasterScanLine(m_RasterInfo, start, delta);
  861. ScanlineDelta(m_RasterInfo, start, delta, delta3Small, delta3Big,
  862. xError, xStepError, dXdY23);
  863. }
  864. }
  865. }
  866. #undef ScanlineDelta
  867. #undef ScanlineDeltaFogBig
  868. #undef ScanlineDeltaFogSmall
  869. #undef ScanlineDeltaDepthBig
  870. #undef ScanlineDeltaDepthSmall
  871. #undef ScanlineDeltaColorBig
  872. #undef ScanlineDeltaColorSmall
  873. #undef ScanlineDeltaTextureBig
  874. #undef ScanlineDeltaTextureSmall
  875. #undef ScanlineDeltaStencil
  876. #undef ScanlineDeltaDepth
  877. #undef InitScanlineStart
  878. #undef InitScanlineDeltas
  879. #undef RasterTriangle
  880. #undef HasFog
  881. #undef HasDepth
  882. #undef HasColor
  883. #undef HasTexture
  884. #undef HasStencil
  885. #undef HasScissor