3
0

ReflectionScreenSpaceDownsampleDepthLinear.azsl 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. #include <Atom/Features/PostProcessing/FullscreenVertex.azsli>
  9. #include <Atom/Features/SrgSemantics.azsli>
  10. ShaderResourceGroup PassSrg : SRG_PerPass
  11. {
  12. Texture2D<float2> m_input;
  13. float m_invOutputScale;
  14. uint m_mipLevel;
  15. bool m_halfResolution;
  16. uint m_previousMipLevel;
  17. uint m_previousMipWidth;
  18. uint m_previousMipHeight;
  19. Sampler PointSampler
  20. {
  21. MinFilter = Point;
  22. MagFilter = Point;
  23. MipFilter = Point;
  24. AddressU = Clamp;
  25. AddressV = Clamp;
  26. AddressW = Clamp;
  27. };
  28. }
  29. struct PSOutput
  30. {
  31. float2 m_result : SV_Target0;
  32. };
  33. PSOutput MainPS(VSOutput IN)
  34. {
  35. uint2 coords = IN.m_position.xy;
  36. uint2 previousMipBaseCoords = IN.m_position.xy * 2;
  37. float minDepth = 1e27f;
  38. float sigma = 0.0f;
  39. float2 depthSamples[9]; // maximum of 3x3 samples depending on image width/height
  40. uint numSamples = 0;
  41. if (PassSrg::m_invOutputScale <= 1.0f)
  42. {
  43. // populate mip0 at 1:1 scale
  44. minDepth = PassSrg::m_input.Load(uint3(coords, 0)).r;
  45. }
  46. else
  47. {
  48. [unroll]
  49. for (int y = 0; y < 2; ++y)
  50. {
  51. [unroll]
  52. for (int x = 0; x < 2; ++x)
  53. {
  54. float2 previousMipCoords = float2(previousMipBaseCoords + float2(x, y));
  55. float2 previousMipUV = previousMipCoords / float2(PassSrg::m_previousMipWidth, PassSrg::m_previousMipHeight);
  56. depthSamples[numSamples++] = PassSrg::m_input.SampleLevel(PassSrg::PointSampler, previousMipUV, PassSrg::m_previousMipLevel).rg;
  57. }
  58. }
  59. bool oddWidth = (PassSrg::m_previousMipWidth & 1) != 0;
  60. bool oddHeight = (PassSrg::m_previousMipHeight & 1) != 0;
  61. if (oddWidth)
  62. {
  63. // add extra column
  64. [unroll]
  65. for (int y = 0; y < 2; ++y)
  66. {
  67. float2 previousMipCoords = float2(previousMipBaseCoords + float2(2, y));
  68. float2 previousMipUV = previousMipCoords / float2(PassSrg::m_previousMipWidth, PassSrg::m_previousMipHeight);
  69. depthSamples[numSamples++] = PassSrg::m_input.SampleLevel(PassSrg::PointSampler, previousMipUV, PassSrg::m_previousMipLevel).rg;
  70. }
  71. if (oddHeight)
  72. {
  73. // both width and height are odd, add corner value
  74. float2 previousMipCoords = float2(previousMipBaseCoords + float2(2, 2));
  75. float2 previousMipUV = previousMipCoords / float2(PassSrg::m_previousMipWidth, PassSrg::m_previousMipHeight);
  76. depthSamples[numSamples++] = PassSrg::m_input.SampleLevel(PassSrg::PointSampler, previousMipUV, PassSrg::m_previousMipLevel).rg;
  77. }
  78. }
  79. if (oddHeight)
  80. {
  81. // add extra row
  82. [unroll]
  83. for (int x = 0; x < 2; ++x)
  84. {
  85. float2 previousMipCoords = float2(previousMipBaseCoords + float2(x, 2));
  86. float2 previousMipUV = previousMipCoords / float2(PassSrg::m_previousMipWidth, PassSrg::m_previousMipHeight);
  87. depthSamples[numSamples++] = PassSrg::m_input.SampleLevel(PassSrg::PointSampler, previousMipUV, PassSrg::m_previousMipLevel).rg;
  88. }
  89. }
  90. }
  91. if (numSamples > 0)
  92. {
  93. // find the minimum depth and compute the mean
  94. float mean = 0.0f;
  95. for (uint i = 0; i < numSamples; ++i)
  96. {
  97. if (depthSamples[i].r < minDepth)
  98. {
  99. minDepth = depthSamples[i].r;
  100. }
  101. mean += depthSamples[i].r;
  102. }
  103. mean /= numSamples;
  104. // compute variance from depth samples
  105. float variance = 0.0f;
  106. for (uint i = 0; i < numSamples; ++i)
  107. {
  108. variance += pow(depthSamples[i].r - mean, 2);
  109. }
  110. variance /= numSamples;
  111. // compute standard deviation
  112. sigma = sqrt(variance);
  113. // find the max sigma for mip levels after the first downsampled mip
  114. // Note: this allows handling of depth discontinuities across samples as well as inside a single sample
  115. bool firstDownsampledMip = PassSrg::m_halfResolution ? (PassSrg::m_mipLevel == 0) : (PassSrg::m_mipLevel == 1);
  116. if (!firstDownsampledMip)
  117. {
  118. for (uint i = 0; i < numSamples; ++i)
  119. {
  120. if (depthSamples[i].g > sigma)
  121. {
  122. sigma = depthSamples[i].g;
  123. }
  124. }
  125. }
  126. }
  127. PSOutput OUT;
  128. OUT.m_result = float2(minDepth, sigma);
  129. return OUT;
  130. }