FXAAPass2CS.hlsli 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //
  2. // Copyright (c) Microsoft. All rights reserved.
  3. // This code is licensed under the MIT License (MIT).
  4. // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
  5. // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
  6. // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
  7. // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
  8. //
  9. // Developed by Minigraph
  10. //
  11. // Author: James Stanard
  12. //
  13. #include "FXAARootSignature.hlsli"
  14. cbuffer CB : register( b0 )
  15. {
  16. float2 RcpTextureSize;
  17. };
  18. Texture2D<float> Luma : register(t0);
  19. Texture2D<float3> SrcColor : register(t1); // this must alias DstColor
  20. StructuredBuffer<uint> WorkQueue : register(t2);
  21. Buffer<float3> ColorQueue : register(t3);
  22. RWTexture2D<float3> DstColor : register(u0);
  23. SamplerState LinearSampler : register(s0);
  24. // Note that the number of samples in each direction is one less than the number of sample distances. The last
  25. // is the maximum distance that should be used, but whether that sample is "good" or "bad" doesn't affect the result,
  26. // so we don't need to load it.
  27. #ifdef FXAA_EXTREME_QUALITY
  28. #define NUM_SAMPLES 11
  29. static const float s_SampleDistances[12] = // FXAA_QUALITY__PRESET == 39
  30. {
  31. 1.0, 2.0, 3.0, 4.0, 5.0, 6.5, 8.5, 10.5, 12.5, 14.5, 18.5, 36.5,
  32. };
  33. #else
  34. #define NUM_SAMPLES 7
  35. static const float s_SampleDistances[8] = // FXAA_QUALITY__PRESET == 25
  36. {
  37. 1.0, 2.5, 4.5, 6.5, 8.5, 10.5, 14.5, 22.5
  38. };
  39. #endif
  40. [RootSignature(FXAA_RootSig)]
  41. [numthreads(64, 1, 1)]
  42. void main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )
  43. {
  44. uint WorkHeader = WorkQueue[DTid.x];
  45. uint2 ST = uint2(WorkHeader >> 8, WorkHeader >> 20) & 0xFFF;
  46. uint GradientDir = WorkHeader & 1; // Determines which side of the pixel has the highest contrast
  47. float Subpix = (WorkHeader & 0xFE) / 254.0 * 0.5; // 7-bits to encode [0, 0.5]
  48. #ifdef VERTICAL_ORIENTATION
  49. float NextLuma = Luma[ST + int2(GradientDir * 2 - 1, 0)];
  50. float2 StartUV = (ST + float2(GradientDir, 0.5)) * RcpTextureSize;
  51. #else
  52. float NextLuma = Luma[ST + int2(0, GradientDir * 2 - 1)];
  53. float2 StartUV = (ST + float2(0.5, GradientDir)) * RcpTextureSize;
  54. #endif
  55. float ThisLuma = Luma[ST];
  56. float CenterLuma = (NextLuma + ThisLuma) * 0.5; // Halfway between this and next; center of the contrasting edge
  57. float GradientSgn = sign(NextLuma - ThisLuma); // Going down in brightness or up?
  58. float GradientMag = abs(NextLuma - ThisLuma) * 0.25; // How much contrast? When can we stop looking?
  59. float NegDist = s_SampleDistances[NUM_SAMPLES];
  60. float PosDist = s_SampleDistances[NUM_SAMPLES];
  61. bool NegGood = false;
  62. bool PosGood = false;
  63. for (uint iter = 0; iter < NUM_SAMPLES; ++iter)
  64. {
  65. const float Distance = s_SampleDistances[iter];
  66. #ifdef VERTICAL_ORIENTATION
  67. float2 NegUV = StartUV - float2(0, RcpTextureSize.y) * Distance;
  68. float2 PosUV = StartUV + float2(0, RcpTextureSize.y) * Distance;
  69. #else
  70. float2 NegUV = StartUV - float2(RcpTextureSize.x, 0) * Distance;
  71. float2 PosUV = StartUV + float2(RcpTextureSize.x, 0) * Distance;
  72. #endif
  73. // Check for a negative endpoint
  74. float NegGrad = Luma.SampleLevel(LinearSampler, NegUV, 0) - CenterLuma;
  75. if (abs(NegGrad) >= GradientMag && Distance < NegDist)
  76. {
  77. NegDist = Distance;
  78. NegGood = sign(NegGrad) == GradientSgn;
  79. }
  80. // Check for a positive endpoint
  81. float PosGrad = Luma.SampleLevel(LinearSampler, PosUV, 0) - CenterLuma;
  82. if (abs(PosGrad) >= GradientMag && Distance < PosDist)
  83. {
  84. PosDist = Distance;
  85. PosGood = sign(PosGrad) == GradientSgn;
  86. }
  87. }
  88. // Ranges from 0.0 to 0.5
  89. float PixelShift = 0.5 - min(NegDist, PosDist) / (PosDist + NegDist);
  90. bool GoodSpan = NegDist < PosDist ? NegGood : PosGood;
  91. PixelShift = max(Subpix, GoodSpan ? PixelShift : 0.0);
  92. if (PixelShift > 0.01)
  93. {
  94. #ifdef DEBUG_OUTPUT
  95. DstColor[ST] = float3(2.0 * PixelShift, 1.0 - 2.0 * PixelShift, 0);
  96. #else
  97. DstColor[ST] = lerp(SrcColor[ST], ColorQueue[DTid.x], PixelShift);
  98. #endif
  99. }
  100. #ifdef DEBUG_OUTPUT
  101. else
  102. DstColor[ST] = float3(0, 0, 0.25);
  103. #endif
  104. }