ImportanceSampling.bslinc 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. mixin ImportanceSampling
  2. {
  3. code
  4. {
  5. #define PI 3.1415926
  6. float radicalInverse(uint bits)
  7. {
  8. // Reverse bits. Algorithm from Hacker's Delight.
  9. bits = (bits << 16u) | (bits >> 16u);
  10. bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
  11. bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
  12. bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
  13. bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
  14. // Normalizes unsigned int in range [0, 4294967295] to [0, 1]
  15. return float(bits) * 2.3283064365386963e-10;
  16. }
  17. float2 hammersleySequence(uint i, uint count)
  18. {
  19. float2 output;
  20. output.x = i / (float)count;
  21. output.y = radicalInverse(i);
  22. return output;
  23. }
  24. // Returns cos(theta) in x and phi in y
  25. float2 importanceSampleGGX(float2 e, float roughness4)
  26. {
  27. // See GGXImportanceSample.nb for derivation (essentially, take base GGX, normalize it,
  28. // generate PDF, split PDF into marginal probability for theta and conditional probability
  29. // for phi. Plug those into the CDF, invert it.)
  30. float cosTheta = sqrt((1.0f - e.x) / (1.0f + (roughness4 - 1.0f) * e.x));
  31. float phi = 2.0f * PI * e.y;
  32. return float2(cosTheta, phi);
  33. }
  34. float3 sphericalToCartesian(float cosTheta, float sinTheta, float phi)
  35. {
  36. float3 output;
  37. output.x = sinTheta * cos(phi);
  38. output.y = sinTheta * sin(phi);
  39. output.z = cosTheta;
  40. return output;
  41. }
  42. float pdfGGX(float cosTheta, float sinTheta, float roughness4)
  43. {
  44. float d = (cosTheta*roughness4 - cosTheta) * cosTheta + 1;
  45. return roughness4 * cosTheta * sinTheta / (d*d*PI);
  46. }
  47. };
  48. };