MotionBlurFinalPassCS.hlsl 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // RUN: %dxc -E main -T cs_6_0 %s | FileCheck %s
  2. // CHECK: threadId
  3. // CHECK: Sqrt
  4. // CHECK: FMin
  5. // CHECK: sampleLevel
  6. // CHECK: sampleLevel
  7. // CHECK: Round_pi
  8. // CHECK: sampleLevel
  9. // CHECK: sampleLevel
  10. //
  11. // Copyright (c) Microsoft. All rights reserved.
  12. // This code is licensed under the MIT License (MIT).
  13. // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
  14. // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
  15. // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
  16. // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
  17. //
  18. // Developed by Minigraph
  19. //
  20. // Author: James Stanard
  21. //
  22. #include "MotionBlurRS.hlsli"
  23. Texture2D<float3> SrcColor : register(t0); // final output color (blurred and temporally blended)
  24. Texture2D<float2> MotionBuffer : register(t1); // full resolution motion vectors
  25. Texture2D<float4> PrepBuffer : register(t2); // 1/4 resolution pre-weighted blurred color samples
  26. RWTexture2D<float3> DstColor : register(u0); // final output color (blurred and temporally blended)
  27. #ifdef TEMPORAL_UPSAMPLE
  28. Texture2D<float4> TemporalIn : register(t3); // saved result from last frame
  29. RWTexture2D<float4> TemporalOut : register(u1); // color to save for next frame including its validity in alpha
  30. #endif
  31. SamplerState LinearSampler : register(s0);
  32. cbuffer c0 : register(b0)
  33. {
  34. float2 RcpBufferDim; // 1 / width, 1 / height
  35. uint MAX_SAMPLE_COUNT;
  36. float STEP_SIZE;
  37. }
  38. [RootSignature(MotionBlur_RootSig)]
  39. [numthreads( 8, 8, 1 )]
  40. void main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )
  41. {
  42. uint2 st = DTid.xy;
  43. float2 position = st + 0.5;
  44. float2 uv = position * RcpBufferDim;
  45. float2 motionVec = MotionBuffer[st] * 32;
  46. float3 thisColor = SrcColor[st];
  47. // Computing speed in this way will set the step size to two-pixel increments in the dominant
  48. // direction.
  49. float speed = length(motionVec);
  50. [branch]
  51. if (speed >= 4)
  52. {
  53. float4 accum = float4(thisColor, 1);
  54. // Half of the speed goes in each direction
  55. float halfSampleCount = min(MAX_SAMPLE_COUNT * 0.5, speed * 0.5 / STEP_SIZE);
  56. // Accumulate low-res, pre-weighted samples, summing their weights in alpha.
  57. // The center sample is skipped because we are alpha blending onto it in the
  58. // destination buffer. Only its weight is considered. Accumulating low-res
  59. // samples is not so egregious because the center weight is still high res.
  60. // Also, each of the low res samples is comprised of four pre-weighted high-
  61. // res samples, so they are effectively masked at full resolution.
  62. float2 deltaUV = motionVec / speed * RcpBufferDim * STEP_SIZE;
  63. float2 uv1 = uv;
  64. float2 uv2 = uv;
  65. // First accumulate the whole samples
  66. for (float i = halfSampleCount - 1.0; i > 0.0; i -= 1.0)
  67. {
  68. accum += PrepBuffer.SampleLevel(LinearSampler, uv1 += deltaUV, 0);
  69. accum += PrepBuffer.SampleLevel(LinearSampler, uv2 -= deltaUV, 0);
  70. }
  71. // This is almost the same as 'frac(halfSampleCount)' replaces 0 with 1.
  72. float remainder = 1 + halfSampleCount - ceil(halfSampleCount);
  73. // Then accumulate the fractional samples
  74. deltaUV *= remainder;
  75. accum += PrepBuffer.SampleLevel(LinearSampler, uv1 + deltaUV, 0) * remainder;
  76. accum += PrepBuffer.SampleLevel(LinearSampler, uv2 - deltaUV, 0) * remainder;
  77. thisColor = accum.rgb / accum.a;
  78. #ifdef TEMPORAL_UPSAMPLE
  79. TemporalOut[st] = 0;
  80. }
  81. else
  82. {
  83. float thisValidity = 1.0 - speed * 0.25;
  84. float4 prevColor = TemporalIn.SampleLevel( LinearSampler, (position + motionVec) * RcpBufferDim, 0 );
  85. #if 1
  86. // 2x super sampling with no feedback
  87. TemporalOut[st] = float4( thisColor, thisValidity );
  88. thisColor = lerp( thisColor, prevColor.rgb, 0.5 * min(thisValidity, prevColor.a) );
  89. #else
  90. // 4x super sampling via controlled feedback
  91. thisColor = lerp( thisColor, prevColor.rgb, TemporalBlendFactor * min(thisValidity, prevColor.a));
  92. TemporalOut[st] = float4( thisColor, thisValidity );
  93. #endif
  94. #endif
  95. }
  96. DstColor[st] = thisColor;
  97. }