fillerTemplates.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2017 to 2023 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. #ifndef DFPSR_RENDER_FILLER_TEMPLATES
  24. #define DFPSR_RENDER_FILLER_TEMPLATES
  25. #include <cstdint>
  26. #include "../../../api/imageAPI.h"
  27. #include "../ITriangle2D.h"
  28. #include "shaderTypes.h"
  29. namespace dsr {
  30. // Function for filling pixels
  31. using PixelShadingCallback = std::function<Rgba_F32<U32x4, F32x4>(void *data, const F32x4x3 &vertexWeights)>;
  32. inline bool almostZero(float value) {
  33. return value > -0.001f && value < 0.001f;
  34. }
  35. inline bool almostZero(const FVector3D &channel) {
  36. return almostZero(channel.x) && almostZero(channel.y) && almostZero(channel.z);
  37. }
  38. inline bool almostOne(float value) {
  39. return value > 0.999f && value < 1.001f;
  40. }
  41. inline bool almostOne(const FVector3D &channel) {
  42. return almostOne(channel.x) && almostOne(channel.y) && almostOne(channel.z);
  43. }
  44. inline bool almostSame(const FVector3D &channel) {
  45. return almostZero(channel.x - channel.y) && almostZero(channel.x - channel.z) && almostZero(channel.y - channel.z);
  46. }
  47. inline const uint32_t roundUpEven(uint32_t x) {
  48. return (x + 1u) & ~1u;
  49. }
  50. inline const uint32_t roundDownEven(uint32_t x) {
  51. return x & ~1u;
  52. }
  53. template<bool CLIP_SIDES>
  54. inline U32x4 clippedRead(SafePointer<uint32_t> upperLeft, SafePointer<uint32_t> lowerLeft, bool vis0, bool vis1, bool vis2, bool vis3) {
  55. if (CLIP_SIDES) {
  56. return U32x4(vis0 ? upperLeft[0] : 0, vis1 ? upperLeft[1] : 0, vis2 ? lowerLeft[0] : 0, vis3 ? lowerLeft[1] : 0);
  57. } else {
  58. return U32x4(upperLeft[0], upperLeft[1], lowerLeft[0], lowerLeft[1]);
  59. }
  60. }
  61. inline void clippedWrite(SafePointer<uint32_t> upperLeft, SafePointer<uint32_t> lowerLeft, bool vis0, bool vis1, bool vis2, bool vis3, U32x4 vColor) {
  62. // Read back SIMD vector to scalar type
  63. UVector4D color = vColor.get();
  64. // Write colors for visible pixels
  65. if (vis0) { upperLeft[0] = color.x; }
  66. if (vis1) { upperLeft[1] = color.y; }
  67. if (vis2) { lowerLeft[0] = color.z; }
  68. if (vis3) { lowerLeft[1] = color.w; }
  69. }
  70. inline void clippedWrite(SafePointer<float> upperLeft, SafePointer<float> lowerLeft, bool vis0, bool vis1, bool vis2, bool vis3, FVector4D depth) {
  71. // Write colors for visible pixels
  72. if (vis0) { upperLeft[0] = depth.x; }
  73. if (vis1) { upperLeft[1] = depth.y; }
  74. if (vis2) { lowerLeft[0] = depth.z; }
  75. if (vis3) { lowerLeft[1] = depth.w; }
  76. }
  77. template<bool CLIP_SIDES>
  78. inline void clipPixels(int x, const RowInterval &upperRow, const RowInterval &lowerRow, bool &clip0, bool &clip1, bool &clip2, bool &clip3) {
  79. if (CLIP_SIDES) {
  80. int x2 = x + 1;
  81. clip0 = x >= upperRow.left && x < upperRow.right;
  82. clip1 = x2 >= upperRow.left && x2 < upperRow.right;
  83. clip2 = x >= lowerRow.left && x < lowerRow.right;
  84. clip3 = x2 >= lowerRow.left && x2 < lowerRow.right;
  85. } else {
  86. clip0 = true;
  87. clip1 = true;
  88. clip2 = true;
  89. clip3 = true;
  90. }
  91. }
  92. template<bool CLIP_SIDES, bool DEPTH_READ, bool AFFINE>
  93. inline void getVisibility(int x, const RowInterval &upperRow, const RowInterval &lowerRow, const FVector4D &depth, SafePointer<const float> depthDataUpper, SafePointer<const float> depthDataLower, bool &vis0, bool &vis1, bool &vis2, bool &vis3) {
  94. // Clip pixels
  95. bool clip0, clip1, clip2, clip3;
  96. clipPixels<CLIP_SIDES>(x, upperRow, lowerRow, clip0, clip1, clip2, clip3);
  97. // Compare to depth buffer
  98. bool front0, front1, front2, front3;
  99. if (DEPTH_READ) {
  100. if (AFFINE) {
  101. if (CLIP_SIDES) {
  102. front0 = clip0 ? depth.x < depthDataUpper[0] : false;
  103. front1 = clip1 ? depth.y < depthDataUpper[1] : false;
  104. front2 = clip2 ? depth.z < depthDataLower[0] : false;
  105. front3 = clip3 ? depth.w < depthDataLower[1] : false;
  106. } else {
  107. front0 = depth.x < depthDataUpper[0];
  108. front1 = depth.y < depthDataUpper[1];
  109. front2 = depth.z < depthDataLower[0];
  110. front3 = depth.w < depthDataLower[1];
  111. }
  112. } else {
  113. if (CLIP_SIDES) {
  114. front0 = clip0 ? depth.x > depthDataUpper[0] : false;
  115. front1 = clip1 ? depth.y > depthDataUpper[1] : false;
  116. front2 = clip2 ? depth.z > depthDataLower[0] : false;
  117. front3 = clip3 ? depth.w > depthDataLower[1] : false;
  118. } else {
  119. front0 = depth.x > depthDataUpper[0];
  120. front1 = depth.y > depthDataUpper[1];
  121. front2 = depth.z > depthDataLower[0];
  122. front3 = depth.w > depthDataLower[1];
  123. }
  124. }
  125. } else {
  126. front0 = true;
  127. front1 = true;
  128. front2 = true;
  129. front3 = true;
  130. }
  131. // Decide visibility
  132. vis0 = clip0 && front0;
  133. vis1 = clip1 && front1;
  134. vis2 = clip2 && front2;
  135. vis3 = clip3 && front3;
  136. }
  137. template<bool CLIP_SIDES, bool COLOR_WRITE, bool DEPTH_READ, bool DEPTH_WRITE, Filter FILTER, bool AFFINE>
  138. inline void fillQuadSuper(void *data, PixelShadingCallback pixelShaderFunction, int x, SafePointer<uint32_t> pixelDataUpper, SafePointer<uint32_t> pixelDataLower, SafePointer<float> depthDataUpper, SafePointer<float> depthDataLower, const RowInterval &upperRow, const RowInterval &lowerRow, const PackOrder &targetPackingOrder, const FVector4D &depth, const F32x4x3 &weights) {
  139. // Get visibility
  140. bool vis0, vis1, vis2, vis3;
  141. getVisibility<CLIP_SIDES, DEPTH_READ, AFFINE>(x, upperRow, lowerRow, depth, depthDataUpper, depthDataLower, vis0, vis1, vis2, vis3);
  142. // Draw if something is visible
  143. if (vis0 || vis1 || vis2 || vis3) {
  144. if (COLOR_WRITE) {
  145. // Get the color
  146. U32x4 packedColor(0u); // Allow uninitialized memory?
  147. // Execute the shader
  148. Rgba_F32<U32x4, F32x4> planarSourceColor = pixelShaderFunction(data, weights);
  149. // Apply alpha filtering
  150. if (FILTER == Filter::Alpha) {
  151. // Get opacity from the source color
  152. F32x4 opacity = planarSourceColor.alpha * (1.0f / 255.0f);
  153. // Read the packed colors for alpha blending
  154. U32x4 packedTargetColor = clippedRead<CLIP_SIDES>(pixelDataUpper, pixelDataLower, vis0, vis1, vis2, vis3);
  155. // Unpack the target color into planar RGBA format so that it can be mixed with the source color
  156. Rgba_F32<U32x4, F32x4> planarTargetColor(packedTargetColor, targetPackingOrder);
  157. // Blend linearly using floats
  158. planarSourceColor = (planarSourceColor * opacity) + (planarTargetColor * (1.0f - opacity));
  159. }
  160. // Apply channel swapping while packing to bytes
  161. packedColor = planarSourceColor.toSaturatedByte(targetPackingOrder);
  162. // Write colors
  163. clippedWrite(pixelDataUpper, pixelDataLower, vis0, vis1, vis2, vis3, packedColor);
  164. }
  165. // Write depth for visible pixels
  166. if (DEPTH_WRITE) {
  167. clippedWrite(depthDataUpper, depthDataLower, vis0, vis1, vis2, vis3, depth);
  168. }
  169. }
  170. }
  171. // CLIP_SIDES will use upperRow and lowerRow to clip pixels based on the x value. Only x values inside the ranges can be drawn.
  172. // This is used along the triangle edges.
  173. // COLOR_WRITE can be disabled to skip writing to the color buffer. Usually when none is given.
  174. // DEPTH_READ can be disabled to draw without caring if there is something already closer in the depth buffer.
  175. // DEPTH_WRITE can be disabled to skip writing to the depth buffer so that it does not occlude following draw calls.
  176. // FILTER can be set to Filter::Alpha to use the output alpha as the opacity.
  177. template<bool CLIP_SIDES, bool COLOR_WRITE, bool DEPTH_READ, bool DEPTH_WRITE, Filter FILTER, bool AFFINE>
  178. inline void fillRowSuper(void *data, PixelShadingCallback pixelShaderFunction, SafePointer<uint32_t> pixelDataUpper, SafePointer<uint32_t> pixelDataLower, SafePointer<float> depthDataUpper, SafePointer<float> depthDataLower, FVector3D pWeightUpper, FVector3D pWeightLower, const FVector3D &pWeightDx, int startX, int endX, const RowInterval &upperRow, const RowInterval &lowerRow, const PackOrder &targetPackingOrder) {
  179. if (AFFINE) {
  180. FVector3D dx2 = pWeightDx * 2.0f;
  181. F32x4 vLinearDepth(pWeightUpper.x, pWeightUpper.x + pWeightDx.x, pWeightLower.x, pWeightLower.x + pWeightDx.x);
  182. F32x4 weightB(pWeightUpper.y, pWeightUpper.y + pWeightDx.y, pWeightLower.y, pWeightLower.y + pWeightDx.y);
  183. F32x4 weightC(pWeightUpper.z, pWeightUpper.z + pWeightDx.z, pWeightLower.z, pWeightLower.z + pWeightDx.z);
  184. for (int x = startX; x < endX; x += 2) {
  185. // Get the linear depth
  186. FVector4D depth = vLinearDepth.get();
  187. // Calculate the weight of the first vertex from the other two
  188. F32x4 weightA = 1.0f - (weightB + weightC);
  189. F32x4x3 weights(weightA, weightB, weightC);
  190. fillQuadSuper<CLIP_SIDES, COLOR_WRITE, DEPTH_READ, DEPTH_WRITE, FILTER, AFFINE>(data, pixelShaderFunction, x, pixelDataUpper, pixelDataLower, depthDataUpper, depthDataLower, upperRow, lowerRow, targetPackingOrder, depth, weights);
  191. // Iterate projection
  192. vLinearDepth = vLinearDepth + dx2.x;
  193. weightB = weightB + dx2.y;
  194. weightC = weightC + dx2.z;
  195. // Iterate buffer pointers
  196. pixelDataUpper += 2; pixelDataLower += 2;
  197. depthDataUpper += 2; depthDataLower += 2;
  198. }
  199. } else {
  200. FVector3D dx2 = pWeightDx * 2.0f;
  201. F32x4 vRecDepth(pWeightUpper.x, pWeightUpper.x + pWeightDx.x, pWeightLower.x, pWeightLower.x + pWeightDx.x);
  202. F32x4 vRecU(pWeightUpper.y, pWeightUpper.y + pWeightDx.y, pWeightLower.y, pWeightLower.y + pWeightDx.y);
  203. F32x4 vRecV(pWeightUpper.z, pWeightUpper.z + pWeightDx.z, pWeightLower.z, pWeightLower.z + pWeightDx.z);
  204. for (int x = startX; x < endX; x += 2) {
  205. // Get the reciprocal depth
  206. FVector4D depth = vRecDepth.get();
  207. // After linearly interpolating (1 / W, U / W, V / W) based on the affine weights...
  208. // Divide 1 by 1 / W to get the linear depth W
  209. F32x4 vLinearDepth = reciprocal(vRecDepth);
  210. // Multiply the vertex weights to the second and third edges with the depth to compensate for that we divided them by depth before interpolating.
  211. F32x4 weightB = vRecU * vLinearDepth;
  212. F32x4 weightC = vRecV * vLinearDepth;
  213. // Calculate the weight of the first vertex from the other two
  214. F32x4 weightA = 1.0f - (weightB + weightC);
  215. F32x4x3 weights(weightA, weightB, weightC);
  216. fillQuadSuper<CLIP_SIDES, COLOR_WRITE, DEPTH_READ, DEPTH_WRITE, FILTER, AFFINE>(data, pixelShaderFunction, x, pixelDataUpper, pixelDataLower, depthDataUpper, depthDataLower, upperRow, lowerRow, targetPackingOrder, depth, weights);
  217. // Iterate projection
  218. vRecDepth = vRecDepth + dx2.x;
  219. vRecU = vRecU + dx2.y;
  220. vRecV = vRecV + dx2.z;
  221. // Iterate buffer pointers
  222. pixelDataUpper += 2; pixelDataLower += 2;
  223. depthDataUpper += 2; depthDataLower += 2;
  224. }
  225. }
  226. }
  227. template<bool COLOR_WRITE, bool DEPTH_READ, bool DEPTH_WRITE, Filter FILTER, bool AFFINE>
  228. inline void fillShapeSuper(void *data, PixelShadingCallback pixelShaderFunction, const ImageRgbaU8 &colorBuffer, const ImageF32 &depthBuffer, const ITriangle2D &triangle, const Projection &projection, const RowShape &shape) {
  229. // Prepare constants
  230. const int targetStride = image_getStride(colorBuffer);
  231. const int depthBufferStride = image_getStride(depthBuffer);
  232. const FVector3D doublePWeightDx = projection.pWeightDx * 2.0f;
  233. const int colorRowSize = image_getWidth(colorBuffer) * sizeof(uint32_t);
  234. const int depthRowSize = image_getWidth(depthBuffer) * sizeof(float);
  235. const PackOrder& targetPackingOrder = image_exists(colorBuffer) ? image_getPackOrder(colorBuffer) : PackOrder::getPackOrder(PackOrderIndex::RGBA);
  236. const int colorHeight = image_getHeight(colorBuffer);
  237. const int depthHeight = image_getHeight(depthBuffer);
  238. const int maxHeight = colorHeight > depthHeight ? colorHeight : depthHeight;
  239. // Initialize row pointers for color buffer
  240. SafePointer<uint32_t> pixelDataUpper, pixelDataLower, pixelDataUpperRow, pixelDataLowerRow;
  241. if (COLOR_WRITE) {
  242. pixelDataUpperRow = image_getSafePointer<uint32_t>(colorBuffer, shape.startRow);
  243. pixelDataLowerRow = pixelDataUpperRow; pixelDataLowerRow.increaseBytes(targetStride);
  244. }
  245. // Initialize row pointers for depth buffer
  246. SafePointer<float> depthDataUpper, depthDataLower, depthDataUpperRow, depthDataLowerRow;
  247. if (DEPTH_READ || DEPTH_WRITE) {
  248. depthDataUpperRow = image_getSafePointer<float>(depthBuffer, shape.startRow);
  249. depthDataLowerRow = depthDataUpperRow; depthDataLowerRow.increaseBytes(depthBufferStride);
  250. }
  251. for (int32_t y1 = shape.startRow; y1 < shape.startRow + shape.rowCount; y1 += 2) {
  252. int y2 = y1 + 1;
  253. RowInterval upperRow = shape.rows[y1 - shape.startRow];
  254. RowInterval lowerRow = shape.rows[y2 - shape.startRow];
  255. int outerStart = min(upperRow.left, lowerRow.left);
  256. int outerEnd = max(upperRow.right, lowerRow.right);
  257. int innerStart = max(upperRow.left, lowerRow.left);
  258. int innerEnd = min(upperRow.right, lowerRow.right);
  259. // Round exclusive intervals to multiples of two pixels
  260. int outerBlockStart = roundDownEven(outerStart);
  261. int outerBlockEnd = roundUpEven(outerEnd);
  262. int innerBlockStart = roundUpEven(innerStart);
  263. int innerBlockEnd = roundDownEven(innerEnd);
  264. // Clip last row if outside on odd height
  265. if (y2 >= maxHeight) {
  266. lowerRow.right = lowerRow.left;
  267. }
  268. // Avoid reading outside of the given bound
  269. bool hasTop = upperRow.right > upperRow.left;
  270. bool hasBottom = lowerRow.right > lowerRow.left;
  271. if (hasTop || hasBottom) {
  272. // Initialize pointers
  273. if (COLOR_WRITE) {
  274. if (hasTop) {
  275. pixelDataUpper = pixelDataUpperRow.slice("pixelDataUpper", 0, colorRowSize);
  276. } else {
  277. // Repeat the lower row to avoid reading outside
  278. pixelDataUpper = pixelDataLowerRow.slice("pixelDataUpper (from lower)", 0, colorRowSize);
  279. }
  280. if (hasBottom) {
  281. pixelDataLower = pixelDataLowerRow.slice("pixelDataLower", 0, colorRowSize);
  282. } else {
  283. // Repeat the upper row to avoid reading outside
  284. pixelDataLower = pixelDataUpperRow.slice("pixelDataLower (from upper)", 0, colorRowSize);
  285. }
  286. int startColorOffset = outerBlockStart * sizeof(uint32_t);
  287. pixelDataUpper.increaseBytes(startColorOffset);
  288. pixelDataLower.increaseBytes(startColorOffset);
  289. }
  290. if (DEPTH_READ || DEPTH_WRITE) {
  291. if (hasTop) {
  292. depthDataUpper = depthDataUpperRow.slice("depthDataUpper", 0, depthRowSize);
  293. } else {
  294. // Repeat the upper row to avoid reading outside
  295. depthDataUpper = depthDataLowerRow.slice("depthDataUpper (from lower)", 0, depthRowSize);
  296. }
  297. if (hasBottom) {
  298. depthDataLower = depthDataLowerRow.slice("depthDataLower", 0, depthRowSize);
  299. } else {
  300. // Repeat the upper row to avoid reading outside
  301. depthDataLower = depthDataUpperRow.slice("depthDataLower (from upper)", 0, depthRowSize);
  302. }
  303. depthDataUpper += outerBlockStart;
  304. depthDataLower += outerBlockStart;
  305. }
  306. // Initialize projection
  307. FVector3D pWeightUpperRow;
  308. if (AFFINE) {
  309. pWeightUpperRow = projection.getWeight_affine(IVector2D(outerBlockStart, y1));
  310. } else {
  311. pWeightUpperRow = projection.getDepthDividedWeight_perspective(IVector2D(outerBlockStart, y1));
  312. }
  313. FVector3D pWeightUpper = pWeightUpperRow;
  314. FVector3D pWeightLowerRow = pWeightUpperRow + projection.pWeightDy;
  315. FVector3D pWeightLower = pWeightLowerRow;
  316. // Render the pixels
  317. if (innerBlockEnd <= innerBlockStart) {
  318. // Clipped from left and right
  319. for (int32_t x = outerBlockStart; x < outerBlockEnd; x += 2) {
  320. fillRowSuper<true, COLOR_WRITE, DEPTH_READ, DEPTH_WRITE, FILTER, AFFINE>
  321. (data, pixelShaderFunction, pixelDataUpper, pixelDataLower, depthDataUpper, depthDataLower, pWeightUpper, pWeightLower, projection.pWeightDx, x, x + 2, upperRow, lowerRow, targetPackingOrder);
  322. if (COLOR_WRITE) { pixelDataUpper += 2; pixelDataLower += 2; }
  323. if (DEPTH_READ || DEPTH_WRITE) { depthDataUpper += 2; depthDataLower += 2; }
  324. pWeightUpper = pWeightUpper + doublePWeightDx; pWeightLower = pWeightLower + doublePWeightDx;
  325. }
  326. } else {
  327. // Left edge
  328. for (int32_t x = outerBlockStart; x < innerBlockStart; x += 2) {
  329. fillRowSuper<true, COLOR_WRITE, DEPTH_READ, DEPTH_WRITE, FILTER, AFFINE>
  330. (data, pixelShaderFunction, pixelDataUpper, pixelDataLower, depthDataUpper, depthDataLower, pWeightUpper, pWeightLower, projection.pWeightDx, x, x + 2, upperRow, lowerRow, targetPackingOrder);
  331. if (COLOR_WRITE) { pixelDataUpper += 2; pixelDataLower += 2; }
  332. if (DEPTH_READ || DEPTH_WRITE) { depthDataUpper += 2; depthDataLower += 2; }
  333. pWeightUpper = pWeightUpper + doublePWeightDx; pWeightLower = pWeightLower + doublePWeightDx;
  334. }
  335. // Full quads
  336. int width = innerBlockEnd - innerBlockStart;
  337. int quadCount = width / 2;
  338. fillRowSuper<false, COLOR_WRITE, DEPTH_READ, DEPTH_WRITE, FILTER, AFFINE>
  339. (data, pixelShaderFunction, pixelDataUpper, pixelDataLower, depthDataUpper, depthDataLower, pWeightUpper, pWeightLower, projection.pWeightDx, innerBlockStart, innerBlockEnd, RowInterval(), RowInterval(), targetPackingOrder);
  340. if (COLOR_WRITE) { pixelDataUpper += 2 * quadCount; pixelDataLower += 2 * quadCount; }
  341. if (DEPTH_READ || DEPTH_WRITE) { depthDataUpper += 2 * quadCount; depthDataLower += 2 * quadCount; }
  342. pWeightUpper = pWeightUpper + (doublePWeightDx * quadCount); pWeightLower = pWeightLower + (doublePWeightDx * quadCount);
  343. // Right edge
  344. for (int32_t x = innerBlockEnd; x < outerBlockEnd; x += 2) {
  345. fillRowSuper<true, COLOR_WRITE, DEPTH_READ, DEPTH_WRITE, FILTER, AFFINE>
  346. (data, pixelShaderFunction, pixelDataUpper, pixelDataLower, depthDataUpper, depthDataLower, pWeightUpper, pWeightLower, projection.pWeightDx, x, x + 2, upperRow, lowerRow, targetPackingOrder);
  347. if (COLOR_WRITE) { pixelDataUpper += 2; pixelDataLower += 2; }
  348. if (DEPTH_READ || DEPTH_WRITE) { depthDataUpper += 2; depthDataLower += 2; }
  349. pWeightUpper = pWeightUpper + doublePWeightDx; pWeightLower = pWeightLower + doublePWeightDx;
  350. }
  351. }
  352. }
  353. // Iterate to the next row
  354. if (COLOR_WRITE) {
  355. pixelDataUpperRow.increaseBytes(targetStride * 2);
  356. pixelDataLowerRow.increaseBytes(targetStride * 2);
  357. }
  358. if (DEPTH_READ || DEPTH_WRITE) {
  359. depthDataUpperRow.increaseBytes(depthBufferStride * 2);
  360. depthDataLowerRow.increaseBytes(depthBufferStride * 2);
  361. }
  362. }
  363. }
  364. static inline void fillShape(void *data, PixelShadingCallback pixelShaderFunction, const ImageRgbaU8 &colorBuffer, const ImageF32 &depthBuffer, const ITriangle2D &triangle, const Projection &projection, const RowShape &shape, Filter filter) {
  365. bool hasColorBuffer = image_exists(colorBuffer);
  366. bool hasDepthBuffer = image_exists(depthBuffer);
  367. if (projection.affine) {
  368. if (hasDepthBuffer) {
  369. if (hasColorBuffer) {
  370. if (filter != Filter::Solid) {
  371. // Alpha filtering with read only depth buffer
  372. fillShapeSuper<true, true, false, Filter::Alpha, true>(data, pixelShaderFunction, colorBuffer, depthBuffer, triangle, projection, shape);
  373. } else {
  374. // Solid with depth buffer
  375. fillShapeSuper<true, true, true, Filter::Solid, true>(data, pixelShaderFunction, colorBuffer, depthBuffer, triangle, projection, shape);
  376. }
  377. } else {
  378. // Solid depth
  379. fillShapeSuper<false, true, true, Filter::Solid, true>(data, pixelShaderFunction, ImageRgbaU8(), depthBuffer, triangle, projection, shape);
  380. }
  381. } else {
  382. if (hasColorBuffer) {
  383. if (filter != Filter::Solid) {
  384. // Alpha filtering without depth buffer
  385. fillShapeSuper<true, false, false, Filter::Alpha, true>(data, pixelShaderFunction, colorBuffer, ImageF32(), triangle, projection, shape);
  386. } else {
  387. // Solid without depth buffer
  388. fillShapeSuper<true, false, false, Filter::Solid, true>(data, pixelShaderFunction, colorBuffer, ImageF32(), triangle, projection, shape);
  389. }
  390. }
  391. }
  392. } else {
  393. if (hasDepthBuffer) {
  394. if (hasColorBuffer) {
  395. if (filter != Filter::Solid) {
  396. // Alpha filtering with read only depth buffer
  397. fillShapeSuper<true, true, false, Filter::Alpha, false>(data, pixelShaderFunction, colorBuffer, depthBuffer, triangle, projection, shape);
  398. } else {
  399. // Solid with depth buffer
  400. fillShapeSuper<true, true, true, Filter::Solid, false>(data, pixelShaderFunction, colorBuffer, depthBuffer, triangle, projection, shape);
  401. }
  402. } else {
  403. // Solid depth
  404. fillShapeSuper<false, true, true, Filter::Solid, false>(data, pixelShaderFunction, ImageRgbaU8(), depthBuffer, triangle, projection, shape);
  405. }
  406. } else {
  407. if (hasColorBuffer) {
  408. if (filter != Filter::Solid) {
  409. // Alpha filtering without depth buffer
  410. fillShapeSuper<true, false, false, Filter::Alpha, false>(data, pixelShaderFunction, colorBuffer, ImageF32(), triangle, projection, shape);
  411. } else {
  412. // Solid without depth buffer
  413. fillShapeSuper<true, false, false, Filter::Solid, false>(data, pixelShaderFunction, colorBuffer, ImageF32(), triangle, projection, shape);
  414. }
  415. }
  416. }
  417. }
  418. }
  419. }
  420. #endif