Sky.hlsl 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Shaders/Common.hlsl>
  7. #include <AnKi/Shaders/Include/MiscRendererTypes.h>
  8. // These are per megameter
  9. constexpr F32 kGroundRadiusMM = 6.360f;
  10. constexpr F32 kAtmosphereRadiusMM = 6.460f;
  11. constexpr Vec3 kViewPos = Vec3(0.0f, kGroundRadiusMM + 0.0002f, 0.0f); // 200M above the ground.
  12. F32 safeacos(F32 x)
  13. {
  14. return acos(clamp(x, -1.0f, 1.0f));
  15. }
  16. Vec3 getValFromSkyLut(Texture2D<Vec4> skyLut, SamplerState linearAnyClampSampler, Vec3 rayDir, Vec3 dirToSun)
  17. {
  18. const F32 height = length(kViewPos);
  19. const Vec3 up = kViewPos / height;
  20. const F32 horizonAngle = safeacos(sqrt(height * height - kGroundRadiusMM * kGroundRadiusMM) / height);
  21. const F32 altitudeAngle = horizonAngle - acos(dot(rayDir, up)); // Between -PI/2 and PI/2
  22. F32 azimuthAngle; // Between 0 and 2*PI
  23. if(abs(altitudeAngle) > (0.5f * kPi - 0.0001f))
  24. {
  25. // Looking nearly straight up or down.
  26. azimuthAngle = 0.0f;
  27. }
  28. else
  29. {
  30. const Vec3 right = cross(dirToSun, up);
  31. const Vec3 forward = cross(up, right);
  32. const Vec3 projectedDir = normalize(rayDir - up * (dot(rayDir, up)));
  33. const F32 sinTheta = dot(projectedDir, right);
  34. const F32 cosTheta = dot(projectedDir, forward);
  35. azimuthAngle = atan2(sinTheta, cosTheta) + kPi;
  36. }
  37. // Non-linear mapping of altitude angle. See Section 5.3 of the paper.
  38. const F32 v = 0.5 + 0.5 * sign(altitudeAngle) * sqrt(abs(altitudeAngle) * 2.0 / kPi);
  39. const Vec2 uv = Vec2(azimuthAngle / (2.0f * kPi), 1.0 - v);
  40. return skyLut.SampleLevel(linearAnyClampSampler, uv, 0.0f).xyz;
  41. }
  42. Vec3 sunWithBloom(Vec3 rayDir, Vec3 dirToSun)
  43. {
  44. const F32 sunSolidAngle = 0.53f * kPi / 180.0f;
  45. const F32 minSunCosTheta = cos(sunSolidAngle);
  46. const F32 cosTheta = dot(rayDir, dirToSun);
  47. if(cosTheta >= minSunCosTheta)
  48. {
  49. return 1.0f;
  50. }
  51. const F32 offset = minSunCosTheta - cosTheta;
  52. const F32 gaussianBloom = exp(-offset * 50000.0f) * 0.5f;
  53. const F32 invBloom = 1.0f / (0.02f + offset * 300.0f) * 0.01f;
  54. return gaussianBloom + invBloom;
  55. }
  56. /// Compute the sky color.
  57. /// @param rayDir It's the vector: normalize(frag-cameraOrigin)
  58. /// @param dirToSun It's opposite direction the light travels.
  59. Vec3 computeSkyColor(Texture2D<Vec4> skyLut, SamplerState linearAnyClampSampler, Vec3 rayDir, Vec3 dirToSun, F32 sunPower, Bool drawSun)
  60. {
  61. Vec3 col = getValFromSkyLut(skyLut, linearAnyClampSampler, rayDir, dirToSun);
  62. if(drawSun)
  63. {
  64. col += sunWithBloom(rayDir, dirToSun);
  65. }
  66. col *= sunPower;
  67. return col;
  68. }
  69. template<typename T, typename Y>
  70. vector<T, 3> sampleSkyCheap(Sky sky, vector<Y, 3> direction, SamplerState trilinearClampSampler)
  71. {
  72. vector<T, 3> color;
  73. if(sky.m_type == (U32)SkyType::kSolidColor)
  74. {
  75. color = sky.m_solidColor;
  76. }
  77. else
  78. {
  79. const Vec2 uv =
  80. (sky.m_type == (U32)SkyType::kTextureWithEquirectangularMapping) ? equirectangularMapping(direction) : octahedronEncode(direction);
  81. color = getBindlessTexture2DVec4(sky.m_texture).SampleLevel(trilinearClampSampler, uv, 0.0).xyz;
  82. }
  83. return color;
  84. }