ReflectionCubemapCommon.bslinc 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. mixin ReflectionCubemapCommon
  2. {
  3. code
  4. {
  5. float3 getDirFromCubeFace(uint cubeFace, float2 uv)
  6. {
  7. float3 dir;
  8. if(cubeFace == 0)
  9. dir = float3(1.0f, -uv.y, -uv.x);
  10. else if(cubeFace == 1)
  11. dir = float3(-1.0f, -uv.y, uv.x);
  12. else if(cubeFace == 2)
  13. dir = float3(uv.x, 1.0f, uv.y);
  14. else if(cubeFace == 3)
  15. dir = float3(uv.x, -1.0f, -uv.y);
  16. else if(cubeFace == 4)
  17. dir = float3(uv.x, -uv.y, 1.0f);
  18. else
  19. dir = float3(-uv.x, -uv.y, -1.0f);
  20. return dir;
  21. }
  22. /**
  23. * Integrates area of a cube face projected onto the surface of the sphere, from [0, 0] to [u, v].
  24. * u & v expected in [-1, -1] to [1, 1] range.
  25. *
  26. * See http://www.rorydriscoll.com/2012/01/15/cubemap-texel-solid-angle/ for derivation.
  27. */
  28. float integrateProjectedCubeArea(float u, float v)
  29. {
  30. return atan2(u * v, sqrt(u * u + v * v + 1.0f));
  31. }
  32. /** Calculates solid angle of a texel projected onto a sphere. */
  33. float texelSolidAngle(float u, float v, float invFaceSize)
  34. {
  35. float x0 = u - invFaceSize;
  36. float x1 = u + invFaceSize;
  37. float y0 = v - invFaceSize;
  38. float y1 = v + invFaceSize;
  39. return integrateProjectedCubeArea(x1, y1)
  40. - integrateProjectedCubeArea(x0, y1)
  41. - integrateProjectedCubeArea(x1, y0)
  42. + integrateProjectedCubeArea(x0, y0);
  43. }
  44. /**
  45. * Calculates a mip level to sample from based on roughness value.
  46. *
  47. * @param roughness Roughness in range [0, 1]. Higher values yield more roughness.
  48. * @param numMips Total number of mip-map levels in the texture we'll be sampling from.
  49. * @return Index of the mipmap level to sample.
  50. */
  51. float mapRoughnessToMipLevel(float roughness, int numMips)
  52. {
  53. // We use the following equation:
  54. // mipLevel = log10(1 - roughness) / log10(dropPercent)
  55. //
  56. // Where dropPercent represent by what % to drop the roughness with each mip level.
  57. // We convert to log2 and a assume a drop percent value of 0.7. This gives us:
  58. // mipLevel = -2.8 * log2(1 - roughness);
  59. // Note: Another value that could be used is drop 0.6, which yields a multiply by -1.35692.
  60. // This more accurately covers the mip range, but early mip levels end up being too smooth,
  61. // and benefits from our cubemap importance sampling strategy seem to be lost as most samples
  62. // fall within one pixel, resulting in same effect as just trivially downsampling. With 0.7 drop
  63. // the roughness increases too early and higher mip levels don't cover the full [0, 1] range. Which
  64. // is better depends on what looks better.
  65. return max(0, -2.8f * log2(1.0f - roughness));
  66. }
  67. /**
  68. * Calculates a roughness value from the provided mip level.
  69. *
  70. * @param mipLevel Mip level to determine roughness for.
  71. * @param numMips Total number of mip-map levels in the texture we'll be sampling from.
  72. * @return Roughness value for the specific mip level.
  73. */
  74. float mapMipLevelToRoughness(int mipLevel, int numMips)
  75. {
  76. // mapRoughnessToMipLevel() solved for roughness
  77. return 1 - exp2((float)mipLevel / -2.8f);
  78. }
  79. };
  80. };