CameraMotionBlur.shader 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. Shader "Hidden/Universal Render Pipeline/CameraMotionBlur"
  2. {
  3. Properties
  4. {
  5. _MainTex("Source", 2D) = "white" {}
  6. }
  7. HLSLINCLUDE
  8. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
  9. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Random.hlsl"
  10. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  11. #include "Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/Common.hlsl"
  12. TEXTURE2D_X(_MainTex);
  13. TEXTURE2D_X_FLOAT(_CameraDepthTexture);
  14. float4x4 _ViewProjM;
  15. float4x4 _PrevViewProjM;
  16. float _Intensity;
  17. float _Clamp;
  18. float4 _MainTex_TexelSize;
  19. struct VaryingsCMB
  20. {
  21. float4 positionCS : SV_POSITION;
  22. float4 uv : TEXCOORD0;
  23. UNITY_VERTEX_OUTPUT_STEREO
  24. };
  25. VaryingsCMB VertCMB(Attributes input)
  26. {
  27. VaryingsCMB output;
  28. UNITY_SETUP_INSTANCE_ID(input);
  29. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
  30. output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
  31. float4 projPos = output.positionCS * 0.5;
  32. projPos.xy = projPos.xy + projPos.w;
  33. output.uv.xy = input.uv;
  34. output.uv.zw = projPos.xy;
  35. return output;
  36. }
  37. float2 ClampVelocity(float2 velocity, float maxVelocity)
  38. {
  39. float len = length(velocity);
  40. return (len > 0.0) ? min(len, maxVelocity) * (velocity * rcp(len)) : 0.0;
  41. }
  42. // Per-pixel camera velocity
  43. float2 GetCameraVelocity(float4 uv)
  44. {
  45. float depth = SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, uv.xy).r;
  46. #if UNITY_REVERSED_Z
  47. depth = 1.0 - depth;
  48. #endif
  49. depth = 2.0 * depth - 1.0;
  50. float3 viewPos = ComputeViewSpacePosition(uv.zw, depth, unity_CameraInvProjection);
  51. float4 worldPos = float4(mul(unity_CameraToWorld, float4(viewPos, 1.0)).xyz, 1.0);
  52. float4 prevPos = worldPos;
  53. float4 prevClipPos = mul(_PrevViewProjM, prevPos);
  54. float4 curClipPos = mul(_ViewProjM, worldPos);
  55. float2 prevPosCS = prevClipPos.xy / prevClipPos.w;
  56. float2 curPosCS = curClipPos.xy / curClipPos.w;
  57. return ClampVelocity(prevPosCS - curPosCS, _Clamp);
  58. }
  59. float3 GatherSample(float sampleNumber, float2 velocity, float invSampleCount, float2 centerUV, float randomVal, float velocitySign)
  60. {
  61. float offsetLength = (sampleNumber + 0.5) + (velocitySign * (randomVal - 0.5));
  62. float2 sampleUV = centerUV + (offsetLength * invSampleCount) * velocity * velocitySign;
  63. return SAMPLE_TEXTURE2D_X(_MainTex, sampler_PointClamp, sampleUV).xyz;
  64. }
  65. half4 DoMotionBlur(VaryingsCMB input, int iterations)
  66. {
  67. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  68. float2 uv = UnityStereoTransformScreenSpaceTex(input.uv.xy);
  69. float2 velocity = GetCameraVelocity(float4(uv, input.uv.zw)) * _Intensity;
  70. float randomVal = InterleavedGradientNoise(uv * _MainTex_TexelSize.zw, 0);
  71. float invSampleCount = rcp(iterations * 2.0);
  72. half3 color = 0.0;
  73. UNITY_UNROLL
  74. for (int i = 0; i < iterations; i++)
  75. {
  76. color += GatherSample(i, velocity, invSampleCount, uv, randomVal, -1.0);
  77. color += GatherSample(i, velocity, invSampleCount, uv, randomVal, 1.0);
  78. }
  79. return half4(color * invSampleCount, 1.0);
  80. }
  81. ENDHLSL
  82. SubShader
  83. {
  84. Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline"}
  85. LOD 100
  86. ZTest Always ZWrite Off Cull Off
  87. Pass
  88. {
  89. Name "Camera Motion Blur - Low Quality"
  90. HLSLPROGRAM
  91. #pragma vertex VertCMB
  92. #pragma fragment Frag
  93. half4 Frag(VaryingsCMB input) : SV_Target
  94. {
  95. return DoMotionBlur(input, 2);
  96. }
  97. ENDHLSL
  98. }
  99. Pass
  100. {
  101. Name "Camera Motion Blur - Medium Quality"
  102. HLSLPROGRAM
  103. #pragma vertex VertCMB
  104. #pragma fragment Frag
  105. half4 Frag(VaryingsCMB input) : SV_Target
  106. {
  107. return DoMotionBlur(input, 3);
  108. }
  109. ENDHLSL
  110. }
  111. Pass
  112. {
  113. Name "Camera Motion Blur - High Quality"
  114. HLSLPROGRAM
  115. #pragma vertex VertCMB
  116. #pragma fragment Frag
  117. half4 Frag(VaryingsCMB input) : SV_Target
  118. {
  119. return DoMotionBlur(input, 4);
  120. }
  121. ENDHLSL
  122. }
  123. }
  124. }