説明なし
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

ShadowSamplingTent.hlsl 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #ifndef SHADOW_SAMPLING_TENT_INCLUDED
  2. #define SHADOW_SAMPLING_TENT_INCLUDED
  3. // ------------------------------------------------------------------
  4. // PCF Filtering Tent Functions
  5. // ------------------------------------------------------------------
  6. // Assuming a isoceles right angled triangle of height "triangleHeight" (as drawn below).
  7. // This function return the area of the triangle above the first texel.
  8. //
  9. // |\ <-- 45 degree slop isosceles right angled triangle
  10. // | \
  11. // ---- <-- length of this side is "triangleHeight"
  12. // _ _ _ _ <-- texels
  13. real SampleShadow_GetTriangleTexelArea(real triangleHeight)
  14. {
  15. return triangleHeight - 0.5;
  16. }
  17. // Assuming a isoceles triangle of 1.5 texels height and 3 texels wide lying on 4 texels.
  18. // This function return the area of the triangle above each of those texels.
  19. // | <-- offset from -0.5 to 0.5, 0 meaning triangle is exactly in the center
  20. // / \ <-- 45 degree slop isosceles triangle (ie tent projected in 2D)
  21. // / \
  22. // _ _ _ _ <-- texels
  23. // X Y Z W <-- result indices (in computedArea.xyzw and computedAreaUncut.xyzw)
  24. void SampleShadow_GetTexelAreas_Tent_3x3(real offset, out real4 computedArea, out real4 computedAreaUncut)
  25. {
  26. // Compute the exterior areas
  27. real offset01SquaredHalved = (offset + 0.5) * (offset + 0.5) * 0.5;
  28. computedAreaUncut.x = computedArea.x = offset01SquaredHalved - offset;
  29. computedAreaUncut.w = computedArea.w = offset01SquaredHalved;
  30. // Compute the middle areas
  31. // For Y : We find the area in Y of as if the left section of the isoceles triangle would
  32. // intersect the axis between Y and Z (ie where offset = 0).
  33. computedAreaUncut.y = SampleShadow_GetTriangleTexelArea(1.5 - offset);
  34. // This area is superior to the one we are looking for if (offset < 0) thus we need to
  35. // subtract the area of the triangle defined by (0,1.5-offset), (0,1.5+offset), (-offset,1.5).
  36. real clampedOffsetLeft = min(offset,0);
  37. real areaOfSmallLeftTriangle = clampedOffsetLeft * clampedOffsetLeft;
  38. computedArea.y = computedAreaUncut.y - areaOfSmallLeftTriangle;
  39. // We do the same for the Z but with the right part of the isoceles triangle
  40. computedAreaUncut.z = SampleShadow_GetTriangleTexelArea(1.5 + offset);
  41. real clampedOffsetRight = max(offset,0);
  42. real areaOfSmallRightTriangle = clampedOffsetRight * clampedOffsetRight;
  43. computedArea.z = computedAreaUncut.z - areaOfSmallRightTriangle;
  44. }
  45. // Assuming a isoceles triangle of 1.5 texels height and 3 texels wide lying on 4 texels.
  46. // This function return the weight of each texels area relative to the full triangle area.
  47. void SampleShadow_GetTexelWeights_Tent_3x3(real offset, out real4 computedWeight)
  48. {
  49. real4 dummy;
  50. SampleShadow_GetTexelAreas_Tent_3x3(offset, computedWeight, dummy);
  51. computedWeight *= 0.44444;//0.44 == 1/(the triangle area)
  52. }
  53. // Assuming a isoceles triangle of 2.5 texel height and 5 texels wide lying on 6 texels.
  54. // This function return the weight of each texels area relative to the full triangle area.
  55. // / \
  56. // _ _ _ _ _ _ <-- texels
  57. // 0 1 2 3 4 5 <-- computed area indices (in texelsWeights[])
  58. void SampleShadow_GetTexelWeights_Tent_5x5(real offset, out real3 texelsWeightsA, out real3 texelsWeightsB)
  59. {
  60. // See _UnityInternalGetAreaPerTexel_3TexelTriangleFilter for details.
  61. real4 computedArea_From3texelTriangle;
  62. real4 computedAreaUncut_From3texelTriangle;
  63. SampleShadow_GetTexelAreas_Tent_3x3(offset, computedArea_From3texelTriangle, computedAreaUncut_From3texelTriangle);
  64. // Triangle slope is 45 degree thus we can almost reuse the result of the 3 texel wide computation.
  65. // the 5 texel wide triangle can be seen as the 3 texel wide one but shifted up by one unit/texel.
  66. // 0.16 is 1/(the triangle area)
  67. texelsWeightsA.x = 0.16 * (computedArea_From3texelTriangle.x);
  68. texelsWeightsA.y = 0.16 * (computedAreaUncut_From3texelTriangle.y);
  69. texelsWeightsA.z = 0.16 * (computedArea_From3texelTriangle.y + 1);
  70. texelsWeightsB.x = 0.16 * (computedArea_From3texelTriangle.z + 1);
  71. texelsWeightsB.y = 0.16 * (computedAreaUncut_From3texelTriangle.z);
  72. texelsWeightsB.z = 0.16 * (computedArea_From3texelTriangle.w);
  73. }
  74. // Assuming a isoceles triangle of 3.5 texel height and 7 texels wide lying on 8 texels.
  75. // This function return the weight of each texels area relative to the full triangle area.
  76. // / \
  77. // _ _ _ _ _ _ _ _ <-- texels
  78. // 0 1 2 3 4 5 6 7 <-- computed area indices (in texelsWeights[])
  79. void SampleShadow_GetTexelWeights_Tent_7x7(real offset, out real4 texelsWeightsA, out real4 texelsWeightsB)
  80. {
  81. // See _UnityInternalGetAreaPerTexel_3TexelTriangleFilter for details.
  82. real4 computedArea_From3texelTriangle;
  83. real4 computedAreaUncut_From3texelTriangle;
  84. SampleShadow_GetTexelAreas_Tent_3x3(offset, computedArea_From3texelTriangle, computedAreaUncut_From3texelTriangle);
  85. // Triangle slope is 45 degree thus we can almost reuse the result of the 3 texel wide computation.
  86. // the 7 texel wide triangle can be seen as the 3 texel wide one but shifted up by two unit/texel.
  87. // 0.081632 is 1/(the triangle area)
  88. texelsWeightsA.x = 0.081632 * (computedArea_From3texelTriangle.x);
  89. texelsWeightsA.y = 0.081632 * (computedAreaUncut_From3texelTriangle.y);
  90. texelsWeightsA.z = 0.081632 * (computedAreaUncut_From3texelTriangle.y + 1);
  91. texelsWeightsA.w = 0.081632 * (computedArea_From3texelTriangle.y + 2);
  92. texelsWeightsB.x = 0.081632 * (computedArea_From3texelTriangle.z + 2);
  93. texelsWeightsB.y = 0.081632 * (computedAreaUncut_From3texelTriangle.z + 1);
  94. texelsWeightsB.z = 0.081632 * (computedAreaUncut_From3texelTriangle.z);
  95. texelsWeightsB.w = 0.081632 * (computedArea_From3texelTriangle.w);
  96. }
  97. // 3x3 Tent filter (45 degree sloped triangles in U and V)
  98. void SampleShadow_ComputeSamples_Tent_3x3(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[4], out real2 fetchesUV[4])
  99. {
  100. // tent base is 3x3 base thus covering from 9 to 12 texels, thus we need 4 bilinear PCF fetches
  101. real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
  102. real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
  103. real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
  104. // find the weight of each texel based
  105. real4 texelsWeightsU, texelsWeightsV;
  106. SampleShadow_GetTexelWeights_Tent_3x3(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU);
  107. SampleShadow_GetTexelWeights_Tent_3x3(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV);
  108. // each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
  109. real2 fetchesWeightsU = texelsWeightsU.xz + texelsWeightsU.yw;
  110. real2 fetchesWeightsV = texelsWeightsV.xz + texelsWeightsV.yw;
  111. // move the PCF bilinear fetches to respect texels weights
  112. real2 fetchesOffsetsU = texelsWeightsU.yw / fetchesWeightsU.xy + real2(-1.5,0.5);
  113. real2 fetchesOffsetsV = texelsWeightsV.yw / fetchesWeightsV.xy + real2(-1.5,0.5);
  114. fetchesOffsetsU *= shadowMapTexture_TexelSize.xx;
  115. fetchesOffsetsV *= shadowMapTexture_TexelSize.yy;
  116. real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
  117. fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
  118. fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
  119. fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
  120. fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
  121. fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
  122. fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
  123. fetchesWeights[2] = fetchesWeightsU.x * fetchesWeightsV.y;
  124. fetchesWeights[3] = fetchesWeightsU.y * fetchesWeightsV.y;
  125. }
  126. // 5x5 Tent filter (45 degree sloped triangles in U and V)
  127. void SampleShadow_ComputeSamples_Tent_5x5(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[9], out real2 fetchesUV[9])
  128. {
  129. // tent base is 5x5 base thus covering from 25 to 36 texels, thus we need 9 bilinear PCF fetches
  130. real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
  131. real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
  132. real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
  133. // find the weight of each texel based on the area of a 45 degree slop tent above each of them.
  134. real3 texelsWeightsU_A, texelsWeightsU_B;
  135. real3 texelsWeightsV_A, texelsWeightsV_B;
  136. SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B);
  137. SampleShadow_GetTexelWeights_Tent_5x5(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B);
  138. // each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
  139. real3 fetchesWeightsU = real3(texelsWeightsU_A.xz, texelsWeightsU_B.y) + real3(texelsWeightsU_A.y, texelsWeightsU_B.xz);
  140. real3 fetchesWeightsV = real3(texelsWeightsV_A.xz, texelsWeightsV_B.y) + real3(texelsWeightsV_A.y, texelsWeightsV_B.xz);
  141. // move the PCF bilinear fetches to respect texels weights
  142. real3 fetchesOffsetsU = real3(texelsWeightsU_A.y, texelsWeightsU_B.xz) / fetchesWeightsU.xyz + real3(-2.5,-0.5,1.5);
  143. real3 fetchesOffsetsV = real3(texelsWeightsV_A.y, texelsWeightsV_B.xz) / fetchesWeightsV.xyz + real3(-2.5,-0.5,1.5);
  144. fetchesOffsetsU *= shadowMapTexture_TexelSize.xxx;
  145. fetchesOffsetsV *= shadowMapTexture_TexelSize.yyy;
  146. real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
  147. fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
  148. fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
  149. fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x);
  150. fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
  151. fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
  152. fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y);
  153. fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z);
  154. fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z);
  155. fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z);
  156. fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
  157. fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
  158. fetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x;
  159. fetchesWeights[3] = fetchesWeightsU.x * fetchesWeightsV.y;
  160. fetchesWeights[4] = fetchesWeightsU.y * fetchesWeightsV.y;
  161. fetchesWeights[5] = fetchesWeightsU.z * fetchesWeightsV.y;
  162. fetchesWeights[6] = fetchesWeightsU.x * fetchesWeightsV.z;
  163. fetchesWeights[7] = fetchesWeightsU.y * fetchesWeightsV.z;
  164. fetchesWeights[8] = fetchesWeightsU.z * fetchesWeightsV.z;
  165. }
  166. // 7x7 Tent filter (45 degree sloped triangles in U and V)
  167. void SampleShadow_ComputeSamples_Tent_7x7(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[16], out real2 fetchesUV[16])
  168. {
  169. // tent base is 7x7 base thus covering from 49 to 64 texels, thus we need 16 bilinear PCF fetches
  170. real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
  171. real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
  172. real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
  173. // find the weight of each texel based on the area of a 45 degree slop tent above each of them.
  174. real4 texelsWeightsU_A, texelsWeightsU_B;
  175. real4 texelsWeightsV_A, texelsWeightsV_B;
  176. SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsU_A, texelsWeightsU_B);
  177. SampleShadow_GetTexelWeights_Tent_7x7(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsV_A, texelsWeightsV_B);
  178. // each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels
  179. real4 fetchesWeightsU = real4(texelsWeightsU_A.xz, texelsWeightsU_B.xz) + real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw);
  180. real4 fetchesWeightsV = real4(texelsWeightsV_A.xz, texelsWeightsV_B.xz) + real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw);
  181. // move the PCF bilinear fetches to respect texels weights
  182. real4 fetchesOffsetsU = real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw) / fetchesWeightsU.xyzw + real4(-3.5,-1.5,0.5,2.5);
  183. real4 fetchesOffsetsV = real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw) / fetchesWeightsV.xyzw + real4(-3.5,-1.5,0.5,2.5);
  184. fetchesOffsetsU *= shadowMapTexture_TexelSize.xxxx;
  185. fetchesOffsetsV *= shadowMapTexture_TexelSize.yyyy;
  186. real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
  187. fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
  188. fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
  189. fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x);
  190. fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.x);
  191. fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
  192. fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
  193. fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y);
  194. fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.y);
  195. fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z);
  196. fetchesUV[9] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z);
  197. fetchesUV[10] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z);
  198. fetchesUV[11] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.z);
  199. fetchesUV[12] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.w);
  200. fetchesUV[13] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.w);
  201. fetchesUV[14] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.w);
  202. fetchesUV[15] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.w);
  203. fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
  204. fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;
  205. fetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x;
  206. fetchesWeights[3] = fetchesWeightsU.w * fetchesWeightsV.x;
  207. fetchesWeights[4] = fetchesWeightsU.x * fetchesWeightsV.y;
  208. fetchesWeights[5] = fetchesWeightsU.y * fetchesWeightsV.y;
  209. fetchesWeights[6] = fetchesWeightsU.z * fetchesWeightsV.y;
  210. fetchesWeights[7] = fetchesWeightsU.w * fetchesWeightsV.y;
  211. fetchesWeights[8] = fetchesWeightsU.x * fetchesWeightsV.z;
  212. fetchesWeights[9] = fetchesWeightsU.y * fetchesWeightsV.z;
  213. fetchesWeights[10] = fetchesWeightsU.z * fetchesWeightsV.z;
  214. fetchesWeights[11] = fetchesWeightsU.w * fetchesWeightsV.z;
  215. fetchesWeights[12] = fetchesWeightsU.x * fetchesWeightsV.w;
  216. fetchesWeights[13] = fetchesWeightsU.y * fetchesWeightsV.w;
  217. fetchesWeights[14] = fetchesWeightsU.z * fetchesWeightsV.w;
  218. fetchesWeights[15] = fetchesWeightsU.w * fetchesWeightsV.w;
  219. }
  220. #endif