Без опису
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #ifndef UNITY_SAMPLING_INCLUDED
  2. #define UNITY_SAMPLING_INCLUDED
  3. #if SHADER_API_MOBILE || SHADER_API_GLES3 || SHADER_API_SWITCH || defined(UNITY_UNIFIED_SHADER_PRECISION_MODEL)
  4. #pragma warning (disable : 3205) // conversion of larger type to smaller
  5. #endif
  6. //-----------------------------------------------------------------------------
  7. // Sample generator
  8. //-----------------------------------------------------------------------------
  9. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Fibonacci.hlsl"
  10. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Hammersley.hlsl"
  11. //-----------------------------------------------------------------------------
  12. // Coordinate system conversion
  13. //-----------------------------------------------------------------------------
  14. // Transforms the unit vector from the spherical to the Cartesian (right-handed, Z up) coordinate.
  15. real3 SphericalToCartesian(real cosPhi, real sinPhi, real cosTheta)
  16. {
  17. real sinTheta = SinFromCos(cosTheta);
  18. return real3(real2(cosPhi, sinPhi) * sinTheta, cosTheta);
  19. }
  20. real3 SphericalToCartesian(real phi, real cosTheta)
  21. {
  22. real sinPhi, cosPhi;
  23. sincos(phi, sinPhi, cosPhi);
  24. return SphericalToCartesian(cosPhi, sinPhi, cosTheta);
  25. }
  26. // Converts Cartesian coordinates given in the right-handed coordinate system
  27. // with Z pointing upwards (OpenGL style) to the coordinates in the left-handed
  28. // coordinate system with Y pointing up and Z facing forward (DirectX style).
  29. real3 TransformGLtoDX(real3 v)
  30. {
  31. return v.xzy;
  32. }
  33. // Performs conversion from equiareal map coordinates to Cartesian (DirectX cubemap) ones.
  34. real3 ConvertEquiarealToCubemap(real u, real v)
  35. {
  36. real phi = TWO_PI - TWO_PI * u;
  37. real cosTheta = 1.0 - 2.0 * v;
  38. return TransformGLtoDX(SphericalToCartesian(phi, cosTheta));
  39. }
  40. // Convert a texel position into normalized position [-1..1]x[-1..1]
  41. real2 CubemapTexelToNVC(uint2 unPositionTXS, uint cubemapSize)
  42. {
  43. return 2.0 * real2(unPositionTXS) / real(max(cubemapSize - 1, 1)) - 1.0;
  44. }
  45. // Map cubemap face to world vector basis
  46. static const real3 CUBEMAP_FACE_BASIS_MAPPING[6][3] =
  47. {
  48. //XPOS face
  49. {
  50. real3(0.0, 0.0, -1.0),
  51. real3(0.0, -1.0, 0.0),
  52. real3(1.0, 0.0, 0.0)
  53. },
  54. //XNEG face
  55. {
  56. real3(0.0, 0.0, 1.0),
  57. real3(0.0, -1.0, 0.0),
  58. real3(-1.0, 0.0, 0.0)
  59. },
  60. //YPOS face
  61. {
  62. real3(1.0, 0.0, 0.0),
  63. real3(0.0, 0.0, 1.0),
  64. real3(0.0, 1.0, 0.0)
  65. },
  66. //YNEG face
  67. {
  68. real3(1.0, 0.0, 0.0),
  69. real3(0.0, 0.0, -1.0),
  70. real3(0.0, -1.0, 0.0)
  71. },
  72. //ZPOS face
  73. {
  74. real3(1.0, 0.0, 0.0),
  75. real3(0.0, -1.0, 0.0),
  76. real3(0.0, 0.0, 1.0)
  77. },
  78. //ZNEG face
  79. {
  80. real3(-1.0, 0.0, 0.0),
  81. real3(0.0, -1.0, 0.0),
  82. real3(0.0, 0.0, -1.0)
  83. }
  84. };
  85. // Convert a normalized cubemap face position into a direction
  86. real3 CubemapTexelToDirection(real2 positionNVC, uint faceId)
  87. {
  88. real3 dir = CUBEMAP_FACE_BASIS_MAPPING[faceId][0] * positionNVC.x
  89. + CUBEMAP_FACE_BASIS_MAPPING[faceId][1] * positionNVC.y
  90. + CUBEMAP_FACE_BASIS_MAPPING[faceId][2];
  91. return normalize(dir);
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Sampling function
  95. // Reference : http://www.cs.virginia.edu/~jdl/bib/globillum/mis/shirley96.pdf + PBRT
  96. //-----------------------------------------------------------------------------
  97. // Performs uniform sampling of the unit disk.
  98. // Ref: PBRT v3, p. 777.
  99. real2 SampleDiskUniform(real u1, real u2)
  100. {
  101. real r = sqrt(u1);
  102. real phi = TWO_PI * u2;
  103. real sinPhi, cosPhi;
  104. sincos(phi, sinPhi, cosPhi);
  105. return r * real2(cosPhi, sinPhi);
  106. }
  107. // Performs cubic sampling of the unit disk.
  108. real2 SampleDiskCubic(real u1, real u2)
  109. {
  110. real r = u1;
  111. real phi = TWO_PI * u2;
  112. real sinPhi, cosPhi;
  113. sincos(phi, sinPhi, cosPhi);
  114. return r * real2(cosPhi, sinPhi);
  115. }
  116. real3 SampleConeUniform(real u1, real u2, real cos_theta)
  117. {
  118. float r0 = cos_theta + u1 * (1.0f - cos_theta);
  119. float r = sqrt(max(0.0, 1.0 - r0 * r0));
  120. float phi = TWO_PI * u2;
  121. return float3(r * cos(phi), r * sin(phi), r0);
  122. }
  123. real3 SampleSphereUniform(real u1, real u2)
  124. {
  125. real phi = TWO_PI * u2;
  126. real cosTheta = 1.0 - 2.0 * u1;
  127. return SphericalToCartesian(phi, cosTheta);
  128. }
  129. // Performs cosine-weighted sampling of the hemisphere.
  130. // Ref: PBRT v3, p. 780.
  131. real3 SampleHemisphereCosine(real u1, real u2)
  132. {
  133. real3 localL;
  134. // Since we don't really care about the area distortion,
  135. // we substitute uniform disk sampling for the concentric one.
  136. localL.xy = SampleDiskUniform(u1, u2);
  137. // Project the point from the disk onto the hemisphere.
  138. localL.z = sqrt(1.0 - u1);
  139. return localL;
  140. }
  141. // Cosine-weighted sampling without the tangent frame.
  142. // Ref: http://www.amietia.com/lambertnotangent.html
  143. real3 SampleHemisphereCosine(real u1, real u2, real3 normal)
  144. {
  145. // This function needs to used safenormalize because there is a probability
  146. // that the generated direction is the exact opposite of the normal and that would lead
  147. // to a nan vector otheriwse.
  148. real3 pointOnSphere = SampleSphereUniform(u1, u2);
  149. return SafeNormalize(normal + pointOnSphere);
  150. }
  151. real3 SampleHemisphereUniform(real u1, real u2)
  152. {
  153. real phi = TWO_PI * u2;
  154. real cosTheta = 1.0 - u1;
  155. return SphericalToCartesian(phi, cosTheta);
  156. }
  157. void SampleSphere(real2 u,
  158. real4x4 localToWorld,
  159. real radius,
  160. out real lightPdf,
  161. out real3 P,
  162. out real3 Ns)
  163. {
  164. real u1 = u.x;
  165. real u2 = u.y;
  166. Ns = SampleSphereUniform(u1, u2);
  167. // Transform from unit sphere to world space
  168. P = radius * Ns + localToWorld[3].xyz;
  169. // pdf is inverse of area
  170. lightPdf = 1.0 / (FOUR_PI * radius * radius);
  171. }
  172. void SampleHemisphere(real2 u,
  173. real4x4 localToWorld,
  174. real radius,
  175. out real lightPdf,
  176. out real3 P,
  177. out real3 Ns)
  178. {
  179. real u1 = u.x;
  180. real u2 = u.y;
  181. // Random point at hemisphere surface
  182. Ns = -SampleHemisphereUniform(u1, u2); // We want the y down hemisphere
  183. P = radius * Ns;
  184. // Transform to world space
  185. P = mul(real4(P, 1.0), localToWorld).xyz;
  186. Ns = mul(Ns, (real3x3)(localToWorld));
  187. // pdf is inverse of area
  188. lightPdf = 1.0 / (TWO_PI * radius * radius);
  189. }
  190. // Note: The cylinder has no end caps (i.e. no disk on the side)
  191. void SampleCylinder(real2 u,
  192. real4x4 localToWorld,
  193. real radius,
  194. real width,
  195. out real lightPdf,
  196. out real3 P,
  197. out real3 Ns)
  198. {
  199. real u1 = u.x;
  200. real u2 = u.y;
  201. // Random point at cylinder surface
  202. real t = (u1 - 0.5) * width;
  203. real theta = 2.0 * PI * u2;
  204. real cosTheta = cos(theta);
  205. real sinTheta = sin(theta);
  206. // Cylinder are align on the right axis
  207. P = real3(t, radius * cosTheta, radius * sinTheta);
  208. Ns = normalize(real3(0.0, cosTheta, sinTheta));
  209. // Transform to world space
  210. P = mul(real4(P, 1.0), localToWorld).xyz;
  211. Ns = mul(Ns, (real3x3)(localToWorld));
  212. // pdf is inverse of area
  213. lightPdf = 1.0 / (TWO_PI * radius * width);
  214. }
  215. void SampleRectangle(real2 u,
  216. real4x4 localToWorld,
  217. real width,
  218. real height,
  219. out real lightPdf,
  220. out real3 P,
  221. out real3 Ns)
  222. {
  223. // Random point at rectangle surface
  224. P = real3((u.x - 0.5) * width, (u.y - 0.5) * height, 0);
  225. Ns = real3(0, 0, -1); // Light down (-Z)
  226. // Transform to world space
  227. P = mul(real4(P, 1.0), localToWorld).xyz;
  228. Ns = mul(Ns, (real3x3)(localToWorld));
  229. // pdf is inverse of area
  230. lightPdf = 1.0 / (width * height);
  231. }
  232. void SampleDisk(real2 u,
  233. real4x4 localToWorld,
  234. real radius,
  235. out real lightPdf,
  236. out real3 P,
  237. out real3 Ns)
  238. {
  239. // Random point at disk surface
  240. P = real3(radius * SampleDiskUniform(u.x, u.y), 0);
  241. Ns = real3(0.0, 0.0, -1.0); // Light down (-Z)
  242. // Transform to world space
  243. P = mul(real4(P, 1.0), localToWorld).xyz;
  244. Ns = mul(Ns, (real3x3)(localToWorld));
  245. // pdf is inverse of area
  246. lightPdf = 1.0 / (PI * radius * radius);
  247. }
  248. // Solid angle cone sampling.
  249. // Takes the cosine of the aperture as an input.
  250. void SampleCone(real2 u, real cosHalfAngle,
  251. out real3 dir, out real rcpPdf)
  252. {
  253. real cosTheta = lerp(1, cosHalfAngle, u.x);
  254. real phi = TWO_PI * u.y;
  255. dir = SphericalToCartesian(phi, cosTheta);
  256. rcpPdf = TWO_PI * (1 - cosHalfAngle);
  257. }
  258. // Returns uniformly distributed sample vectors in a cone using
  259. // "golden angle spiral method" described here: http://blog.marmakoide.org/?p=1
  260. // note: the first sample is always [0, 0, 1]
  261. real3 SampleConeStrata(uint sampleIdx, real rcpSampleCount, real cosHalfApexAngle)
  262. {
  263. real z = 1.0f - ((1.0f - cosHalfApexAngle) * sampleIdx) * rcpSampleCount;
  264. real r = sqrt(1.0f - z * z);
  265. real a = sampleIdx * 2.3999632297286f; // pi*(3-sqrt(5))
  266. real sphi = sin(a);
  267. real cphi = cos(a);
  268. return real3(r * cphi, r * sphi, z);
  269. }
  270. #if SHADER_API_MOBILE || SHADER_API_GLES3 || SHADER_API_SWITCH
  271. #pragma warning (enable : 3205) // conversion of larger type to smaller
  272. #endif
  273. #endif // UNITY_SAMPLING_INCLUDED