ImportanceSampling.glsl 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. // NOTE: To visualize some of these functions go to https://www.shadertoy.com/view/wsBBzV
  6. #pragma once
  7. #include <AnKi/Shaders/Common.glsl>
  8. /// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
  9. /// Using bitfieldReverse instead of bitwise ops
  10. F32 radicalInverseVdC(U32 bits)
  11. {
  12. bits = bitfieldReverse(bits);
  13. return F32(bits) * 2.3283064365386963e-10; // / 0x100000000
  14. }
  15. /// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
  16. Vec2 hammersley2d(U32 i, U32 N)
  17. {
  18. return Vec2(F32(i) / F32(N), radicalInverseVdC(i));
  19. }
  20. /// Stolen from Unreal
  21. /// Returns three elements with 16 random bits each (0-0xffff)
  22. UVec3 rand3DPCG16(UVec3 v)
  23. {
  24. v = v * 1664525u + 1013904223u;
  25. v.x += v.y * v.z;
  26. v.y += v.z * v.x;
  27. v.z += v.x * v.y;
  28. v.x += v.y * v.z;
  29. v.y += v.z * v.x;
  30. v.z += v.x * v.y;
  31. return v >> 16u;
  32. }
  33. /// Stolen from Unreal
  34. /// It will return a uniform 2D point inside [0.0, 1.0]. For random use rand3DPCG16()
  35. Vec2 hammersleyRandom16(U32 sampleIdx, U32 sampleCount, UVec2 random)
  36. {
  37. const F32 e1 = fract(F32(sampleIdx) / F32(sampleCount) + F32(random.x) * (1.0 / 65536.0));
  38. const F32 e2 = F32((bitfieldReverse(sampleIdx) >> 16u) ^ random.y) * (1.0 / 65536.0);
  39. return Vec2(e1, e2);
  40. }
  41. /// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
  42. /// From a uniform 2D point inside a circle get a 3D point in the surface of a hemisphere. It's oriented in the z axis
  43. Vec3 hemisphereSampleUniform(Vec2 uv)
  44. {
  45. const F32 phi = uv.y * 2.0 * PI;
  46. const F32 cosTheta = 1.0 - uv.x;
  47. const F32 sinTheta = sqrt(1.0 - cosTheta * cosTheta);
  48. return Vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
  49. }
  50. /// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
  51. /// Same as hemisphereSampleUniform but it distributes points closer to the z axis
  52. Vec3 hemisphereSampleCos(Vec2 uv)
  53. {
  54. const F32 phi = uv.y * 2.0 * PI;
  55. const F32 cosTheta = sqrt(1.0 - uv.x);
  56. const F32 sinTheta = sqrt(1.0 - cosTheta * cosTheta);
  57. return Vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
  58. }
  59. /// PCG hash function.
  60. U32 hashPcg(U32 u)
  61. {
  62. const U32 state = u * 747796405u + 2891336453u;
  63. const U32 word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
  64. return (word >> 22u) ^ word;
  65. }