SkyViewLUT.azsl 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. // Based on https://github.com/sebh/UnrealEngineSkyAtmosphere by Sébastien Hillaire
  9. // SkyViewLUT does not support shadows currently because it does not bind or sample the depth buffer
  10. #define ENABLE_ATMOSPHERE_SHADOWS 0
  11. #include <viewsrg_all.srgi>
  12. #include <Atom/Features/PostProcessing/FullscreenVertex.azsli>
  13. #include <Atom/Features/ColorManagement/TransformColor.azsli>
  14. #include <SkyAtmosphereCommon.azsli>
  15. struct SkyViewLutPSOutput
  16. {
  17. float4 m_skyViewLut : SV_Target0;
  18. };
  19. SkyViewLutPSOutput SkyViewLutPS(VSOutput Input)
  20. {
  21. SkyViewLutPSOutput OUT = (SkyViewLutPSOutput)0;
  22. AtmosphereParameters Atmosphere = GetAtmosphereParameters();
  23. const float worldScale = 0.001;
  24. const float depth = 0.0;
  25. float2 ndcPos = float2(Input.m_texCoord.x, 1.0 - Input.m_texCoord.y) * 2.0 - 1.0;
  26. float4 positionWS = mul(ViewSrg::m_viewProjectionInverseMatrix, float4(ndcPos, depth, 1.0));
  27. float3 worldDir = normalize(positionWS.xyz / positionWS.w - ViewSrg::m_worldPosition);
  28. const float worldDepthKm = length(worldDir);
  29. float3 worldPosKm = ViewSrg::m_worldPosition * worldScale - Atmosphere.PlanetOrigin;
  30. float viewHeight = length(worldPosKm);
  31. float3 upVector = worldPosKm / viewHeight;
  32. // prevent the camera from going below the surface or getting too close -
  33. // we do not current support drawing from under the surface
  34. if (viewHeight < Atmosphere.BottomRadius + SKY_MINIMUM_GROUND_OFFSET_KM)
  35. {
  36. viewHeight = Atmosphere.BottomRadius + SKY_MINIMUM_GROUND_OFFSET_KM;
  37. worldPosKm = upVector * viewHeight;
  38. }
  39. float viewZenithCosAngle;
  40. float lightViewCosAngle;
  41. UvToSkyViewLutParams(Atmosphere, viewZenithCosAngle, lightViewCosAngle, viewHeight, Input.m_texCoord.xy);
  42. float sunZenithCosAngle = dot(upVector, PassSrg::m_constants.m_sunDirection);
  43. float3 sunDir = float3(0.0, 0.0, sunZenithCosAngle);
  44. const float epsilon = 0.0001;
  45. if((sunZenithCosAngle < 1.0 - epsilon) && (sunZenithCosAngle > -1.0 + epsilon))
  46. {
  47. sunDir = normalize(float3(sqrt(1.0 - sunZenithCosAngle * sunZenithCosAngle), 0.0, sunZenithCosAngle));
  48. }
  49. worldPosKm = float3(0.0, 0.0, viewHeight);
  50. float viewZenithSinAngle = sqrt(1.0 - viewZenithCosAngle * viewZenithCosAngle);
  51. worldDir = float3(
  52. viewZenithSinAngle * lightViewCosAngle,
  53. viewZenithSinAngle * sqrt(1.0 - lightViewCosAngle * lightViewCosAngle),
  54. viewZenithCosAngle);
  55. float distanceToAtmosphere = 1.0;
  56. if (!MoveToAtmosphere(Atmosphere, worldPosKm, distanceToAtmosphere, worldDir, worldDepthKm))
  57. {
  58. // ray does not intersect the atmosphere
  59. OUT.m_skyViewLut = float4(0.0, 0.0, 0.0, 1.0);
  60. return OUT;
  61. }
  62. const bool ground = true;
  63. const float sampleCountIni = 30.0;
  64. const float depthBufferValue = -1.0;
  65. const bool variablesampleCount = true;
  66. const bool mieRayPhase = true;
  67. const float2 pixPos = Input.m_position.xy;
  68. SingleScatteringResult ss = IntegrateScatteredLuminance(pixPos, worldPosKm, worldDir, sunDir, Atmosphere, ground, sampleCountIni, depthBufferValue, variablesampleCount, mieRayPhase);
  69. OUT.m_skyViewLut = float4(ss.L, 1.0);
  70. return OUT;
  71. }