Shader.cpp 21 KB

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