暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SphericalHarmonics.hlsl 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #ifndef UNITY_SPHERICAL_HARMONICS_INCLUDED
  2. #define UNITY_SPHERICAL_HARMONICS_INCLUDED
  3. #ifdef UNITY_COLORSPACE_GAMMA
  4. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
  5. #endif
  6. // SH Basis coefs
  7. #define kSHBasis0 0.28209479177387814347f // {0, 0} : 1/2 * sqrt(1/Pi)
  8. #define kSHBasis1 0.48860251190291992159f // {1, 0} : 1/2 * sqrt(3/Pi)
  9. #define kSHBasis2 1.09254843059207907054f // {2,-2} : 1/2 * sqrt(15/Pi)
  10. #define kSHBasis3 0.31539156525252000603f // {2, 0} : 1/4 * sqrt(5/Pi)
  11. #define kSHBasis4 0.54627421529603953527f // {2, 2} : 1/4 * sqrt(15/Pi)
  12. static const float kSHBasisCoef[] = { kSHBasis0, -kSHBasis1, kSHBasis1, -kSHBasis1, kSHBasis2, -kSHBasis2, kSHBasis3, -kSHBasis2, kSHBasis4 };
  13. // Clamped cosine convolution coefs (pre-divided by PI)
  14. // See https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/
  15. #define kClampedCosine0 (1.0f)
  16. #define kClampedCosine1 (2.0f / 3.0f)
  17. #define kClampedCosine2 (1.0f / 4.0f)
  18. static const float kClampedCosineCoefs[] = { kClampedCosine0, kClampedCosine1, kClampedCosine1, kClampedCosine1, kClampedCosine2, kClampedCosine2, kClampedCosine2, kClampedCosine2, kClampedCosine2 };
  19. // Ref: "Efficient Evaluation of Irradiance Environment Maps" from ShaderX 2
  20. real3 SHEvalLinearL0L1(real3 N, real4 shAr, real4 shAg, real4 shAb)
  21. {
  22. real4 vA = real4(N, 1.0);
  23. real3 x1;
  24. // Linear (L1) + constant (L0) polynomial terms
  25. x1.r = dot(shAr, vA);
  26. x1.g = dot(shAg, vA);
  27. x1.b = dot(shAb, vA);
  28. return x1;
  29. }
  30. real3 SHEvalLinearL1(real3 N, real3 shAr, real3 shAg, real3 shAb)
  31. {
  32. real3 x1;
  33. x1.r = dot(shAr, N);
  34. x1.g = dot(shAg, N);
  35. x1.b = dot(shAb, N);
  36. return x1;
  37. }
  38. real3 SHEvalLinearL2(real3 N, real4 shBr, real4 shBg, real4 shBb, real4 shC)
  39. {
  40. real3 x2;
  41. // 4 of the quadratic (L2) polynomials
  42. real4 vB = N.xyzz * N.yzzx;
  43. x2.r = dot(shBr, vB);
  44. x2.g = dot(shBg, vB);
  45. x2.b = dot(shBb, vB);
  46. // Final (5th) quadratic (L2) polynomial
  47. real vC = N.x * N.x - N.y * N.y;
  48. real3 x3 = shC.rgb * vC;
  49. return x2 + x3;
  50. }
  51. #if !HALF_IS_FLOAT
  52. half3 SampleSH9(half4 SHCoefficients[7], half3 N)
  53. {
  54. half4 shAr = SHCoefficients[0];
  55. half4 shAg = SHCoefficients[1];
  56. half4 shAb = SHCoefficients[2];
  57. half4 shBr = SHCoefficients[3];
  58. half4 shBg = SHCoefficients[4];
  59. half4 shBb = SHCoefficients[5];
  60. half4 shCr = SHCoefficients[6];
  61. // Linear + constant polynomial terms
  62. half3 res = SHEvalLinearL0L1(N, shAr, shAg, shAb);
  63. // Quadratic polynomials
  64. res += SHEvalLinearL2(N, shBr, shBg, shBb, shCr);
  65. #ifdef UNITY_COLORSPACE_GAMMA
  66. res = LinearToSRGB(res);
  67. #endif
  68. return res;
  69. }
  70. half3 SampleSH4_L1(half4 SHCoefficients[3], half3 N)
  71. {
  72. half4 shAr = SHCoefficients[0];
  73. half4 shAg = SHCoefficients[1];
  74. half4 shAb = SHCoefficients[2];
  75. // Linear + constant polynomial terms
  76. half3 res = SHEvalLinearL1(N, shAr.xyz, shAg.xyz, shAb.xyz);
  77. #ifdef UNITY_COLORSPACE_GAMMA
  78. res = LinearToSRGB(res);
  79. #endif
  80. return res;
  81. }
  82. #endif
  83. float3 SampleSH9(float4 SHCoefficients[7], float3 N)
  84. {
  85. float4 shAr = SHCoefficients[0];
  86. float4 shAg = SHCoefficients[1];
  87. float4 shAb = SHCoefficients[2];
  88. float4 shBr = SHCoefficients[3];
  89. float4 shBg = SHCoefficients[4];
  90. float4 shBb = SHCoefficients[5];
  91. float4 shCr = SHCoefficients[6];
  92. // Linear + constant polynomial terms
  93. float3 res = SHEvalLinearL0L1(N, shAr, shAg, shAb);
  94. // Quadratic polynomials
  95. res += SHEvalLinearL2(N, shBr, shBg, shBb, shCr);
  96. #ifdef UNITY_COLORSPACE_GAMMA
  97. res = LinearToSRGB(res);
  98. #endif
  99. return res;
  100. }
  101. float3 SampleSH9(StructuredBuffer<float4> data, float3 N)
  102. {
  103. real4 SHCoefficients[7];
  104. SHCoefficients[0] = data[0];
  105. SHCoefficients[1] = data[1];
  106. SHCoefficients[2] = data[2];
  107. SHCoefficients[3] = data[3];
  108. SHCoefficients[4] = data[4];
  109. SHCoefficients[5] = data[5];
  110. SHCoefficients[6] = data[6];
  111. return SampleSH9(SHCoefficients, N);
  112. }
  113. float3 SampleSH4_L1(float4 SHCoefficients[3], float3 N)
  114. {
  115. float4 shAr = SHCoefficients[0];
  116. float4 shAg = SHCoefficients[1];
  117. float4 shAb = SHCoefficients[2];
  118. // Linear + constant polynomial terms
  119. float3 res = SHEvalLinearL1(N, (float3)shAr, (float3)shAg, (float3)shAb);
  120. #ifdef UNITY_COLORSPACE_GAMMA
  121. res = LinearToSRGB(res);
  122. #endif
  123. return res;
  124. }
  125. void GetCornetteShanksPhaseFunction(out float3 zh, float anisotropy)
  126. {
  127. float g = anisotropy;
  128. zh.x = 0.282095f;
  129. zh.y = 0.293162f * g * (4.0f + (g * g)) / (2.0f + (g * g));
  130. zh.z = (0.126157f + 1.44179f * (g * g) + 0.324403f * (g * g) * (g * g)) / (2.0f + (g * g));
  131. }
  132. void ConvolveZonal(inout float sh[27], float3 zh)
  133. {
  134. for (int l = 0; l <= 2; l++)
  135. {
  136. float n = sqrt((4.0f * PI) / (2 * l + 1));
  137. float k = zh[l];
  138. float p = n * k;
  139. for (int m = -l; m <= l; m++)
  140. {
  141. int i = l * (l + 1) + m;
  142. for (int c = 0; c < 3; c++)
  143. {
  144. sh[c * 9 + i] = sh[c * 9 + i] * p;
  145. }
  146. }
  147. }
  148. }
  149. // Packs coefficients so that we can use Peter-Pike Sloan's shader code.
  150. // The function does not perform premultiplication with coefficients of SH basis functions, caller need to do it
  151. // See SetSHEMapConstants() in "Stupid Spherical Harmonics Tricks".
  152. // Constant + linear
  153. void PackSH(RWStructuredBuffer<float4> buffer, float sh[27])
  154. {
  155. int c = 0;
  156. for (c = 0; c < 3; c++)
  157. {
  158. buffer[c] = float4(sh[c * 9 + 3], sh[c * 9 + 1], sh[c * 9 + 2], sh[c * 9 + 0] - sh[c * 9 + 6]);
  159. }
  160. // Quadratic (4/5)
  161. for (c = 0; c < 3; c++)
  162. {
  163. buffer[3 + c] = float4(sh[c * 9 + 4], sh[c * 9 + 5], sh[c * 9 + 6] * 3.0f, sh[c * 9 + 7]);
  164. }
  165. // Quadratic (5)
  166. buffer[6] = float4(sh[0 * 9 + 8], sh[1 * 9 + 8], sh[2 * 9 + 8], 1.0f);
  167. }
  168. #endif // UNITY_SPHERICAL_HARMONICS_INCLUDED