DownsampleMinAvgMaxCS.azsl 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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/SrgSemantics.azsli>
  9. #include <Atom/RPI/Math.azsli>
  10. ShaderResourceGroup PassSrg : SRG_PerPass
  11. {
  12. Texture2D<float4> m_inputTexture;
  13. RWTexture2D<float4> m_outputTexture;
  14. }
  15. [numthreads(8,8,1)]
  16. void MainCS(uint3 dispatch_id: SV_DispatchThreadID)
  17. {
  18. // Get input and output texture dimensions
  19. uint2 inputDimensions;
  20. uint2 outputDimenstions;
  21. PassSrg::m_inputTexture.GetDimensions(inputDimensions.x, inputDimensions.y);
  22. PassSrg::m_outputTexture.GetDimensions(outputDimenstions.x, outputDimenstions.y);
  23. uint2 outPixel = dispatch_id.xy;
  24. // Early out if thread is outside of the target image
  25. if(outPixel.x >= outputDimenstions.x || outPixel.y >= outputDimenstions.y)
  26. {
  27. return;
  28. }
  29. // Calculate input pixel position in higher detail mip. If position
  30. // is out of bounds of input texture, output black and early out.
  31. uint2 inPixel = outPixel * 2;
  32. if(inPixel.x >= inputDimensions.x || inPixel.y >= inputDimensions.y)
  33. {
  34. PassSrg::m_outputTexture[outPixel] = float4(0.0f, 0.0f, 0.0f, 0.0f);
  35. return;
  36. }
  37. // Default sample is 4 pixels in a 2x2 quad
  38. uint xLoopCount = 2;
  39. uint yLoopCount = 2;
  40. // If we're at the output border pixel, adjust the amount we sample to extend to the input border
  41. if(outPixel.x == (outputDimenstions.x - 1))
  42. {
  43. xLoopCount = inputDimensions.x - inPixel.x;
  44. }
  45. if(outPixel.y == (outputDimenstions.y - 1))
  46. {
  47. yLoopCount = inputDimensions.y - inPixel.y;
  48. }
  49. float minValue = FLOAT_32_MAX;
  50. float maxValue = 0;
  51. float avgValue = 0;
  52. float sampleCount = 0;
  53. // Gather the input samples
  54. for(uint i = 0; i < xLoopCount; ++i)
  55. {
  56. for(uint j = 0; j < yLoopCount; ++j)
  57. {
  58. uint2 samplePoint = inPixel + uint2(i, j);
  59. float3 value = PassSrg::m_inputTexture[samplePoint].rgb;
  60. minValue = min(minValue, value.x);
  61. maxValue = max(maxValue, value.z);
  62. avgValue += value.y;
  63. ++sampleCount;
  64. }
  65. }
  66. avgValue = avgValue / max(1.0f, sampleCount);
  67. float4 output = float4(minValue, avgValue, maxValue, 0.0f);
  68. // Output the color
  69. PassSrg::m_outputTexture[outPixel] = output;
  70. }