fillerTemplates.h 21 KB

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