MotionVectors.ankiprog 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. // Calculates the motion vectors that will be used to sample from the previous frame
  6. #pragma anki technique vert pixel comp
  7. #include <AnKi/Shaders/QuadVert.hlsl>
  8. #if ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER
  9. # include <AnKi/Shaders/Functions.hlsl>
  10. SamplerState g_nearesetAnyClampSampler : register(s0);
  11. Texture2D g_currentDepthTex : register(t0);
  12. Texture2D g_velocityTex : register(t1);
  13. struct Constants
  14. {
  15. Mat4 m_currentViewProjMat;
  16. Mat4 m_currentInvViewProjMat;
  17. Mat4 m_prevViewProjMat;
  18. };
  19. ConstantBuffer<Constants> g_consts : register(b0);
  20. # if ANKI_COMPUTE_SHADER
  21. RWTexture2D<Vec2> g_motionVectorsStorageTex : register(u0);
  22. # endif
  23. # if ANKI_COMPUTE_SHADER
  24. [numthreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
  25. # else
  26. struct PixelOut
  27. {
  28. Vec2 m_motionVectors : SV_TARGET0;
  29. };
  30. PixelOut main(VertOut input)
  31. # endif
  32. {
  33. # if ANKI_COMPUTE_SHADER
  34. Vec2 texSize;
  35. g_motionVectorsStorageTex.GetDimensions(texSize.x, texSize.y);
  36. const Vec2 uv = (Vec2(svDispatchThreadId) + 0.5f) / texSize;
  37. # else
  38. const Vec2 uv = input.m_uv;
  39. # endif
  40. const Vec2 velocity = g_velocityTex.SampleLevel(g_nearesetAnyClampSampler, uv, 0.0).rg;
  41. Vec2 historyUv;
  42. if(velocity.x != 1.0)
  43. {
  44. historyUv = uv + velocity;
  45. }
  46. else
  47. {
  48. // Don't use a reprojection matrix or other kind of optimizations. Due to numerical precision it produces slightly off result. Big enough to
  49. // create slight visual issues. Do it the hard way.
  50. const F32 depth = g_currentDepthTex.SampleLevel(g_nearesetAnyClampSampler, uv, 0.0).r;
  51. const Vec4 v4 = mul(g_consts.m_currentInvViewProjMat, Vec4(uvToNdc(uv), depth, 1.0));
  52. const Vec3 worldPos = v4.xyz / v4.w;
  53. Vec4 clipPos = mul(g_consts.m_currentViewProjMat, Vec4(worldPos, 1.0));
  54. clipPos.xy /= clipPos.w;
  55. Vec4 prevClipPos = mul(g_consts.m_prevViewProjMat, Vec4(worldPos, 1.0));
  56. prevClipPos.xy /= prevClipPos.w;
  57. const Vec2 diff = ndcToUv(prevClipPos.xy) - ndcToUv(clipPos.xy);
  58. historyUv = uv + diff;
  59. }
  60. // Write out
  61. # if ANKI_COMPUTE_SHADER
  62. g_motionVectorsStorageTex[svDispatchThreadId] = historyUv - uv;
  63. # else
  64. PixelOut output;
  65. output.m_motionVectors = historyUv - uv;
  66. return output;
  67. # endif
  68. }
  69. #endif // ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER