ImportanceSampling.bslinc 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. mixin ImportanceSampling
  2. {
  3. code
  4. {
  5. #define PI 3.1415926
  6. uint 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. return bits;
  15. }
  16. float2 hammersleySequence(uint i, uint count)
  17. {
  18. float2 output;
  19. output.x = i / (float)count;
  20. uint y = radicalInverse(i);
  21. // Normalizes unsigned int in range [0, 4294967295] to [0, 1]
  22. output.y = float(y) * 2.3283064365386963e-10;
  23. return output;
  24. }
  25. float2 hammersleySequence(uint i, uint count, uint2 random)
  26. {
  27. float2 output;
  28. output.x = frac(i / (float)count + float(random.x & 0xFFFF) / (1<<16));
  29. uint y = radicalInverse(i) ^ random.y;
  30. // Normalizes unsigned int in range [0, 4294967295] to [0, 1]
  31. output.y = float(y) * 2.3283064365386963e-10;
  32. return output;
  33. }
  34. // Returns cos(theta) in x and phi in y
  35. float2 importanceSampleGGX(float2 e, float roughness4)
  36. {
  37. // See GGXImportanceSample.nb for derivation (essentially, take base GGX, normalize it,
  38. // generate PDF, split PDF into marginal probability for theta and conditional probability
  39. // for phi. Plug those into the CDF, invert it.)
  40. float cosTheta = sqrt((1.0f - e.x) / (1.0f + (roughness4 - 1.0f) * e.x));
  41. float phi = 2.0f * PI * e.y;
  42. return float2(cosTheta, phi);
  43. }
  44. float3 sphericalToCartesian(float cosTheta, float sinTheta, float phi)
  45. {
  46. float3 output;
  47. output.x = sinTheta * cos(phi);
  48. output.y = sinTheta * sin(phi);
  49. output.z = cosTheta;
  50. return output;
  51. }
  52. float pdfGGX(float cosTheta, float sinTheta, float roughness4)
  53. {
  54. float d = (cosTheta*roughness4 - cosTheta) * cosTheta + 1;
  55. return roughness4 * cosTheta * sinTheta / (d*d*PI);
  56. }
  57. };
  58. };