TemporalAntialiasing.shader 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. Shader "Hidden/PostProcessing/TemporalAntialiasing"
  2. {
  3. HLSLINCLUDE
  4. #pragma exclude_renderers gles psp2
  5. #include "../StdLib.hlsl"
  6. #include "../Colors.hlsl"
  7. #if UNITY_VERSION >= 201710
  8. #define _MainTexSampler sampler_LinearClamp
  9. #else
  10. #define _MainTexSampler sampler_MainTex
  11. #endif
  12. TEXTURE2D_SAMPLER2D(_MainTex, _MainTexSampler);
  13. float4 _MainTex_TexelSize;
  14. TEXTURE2D_SAMPLER2D(_HistoryTex, sampler_HistoryTex);
  15. TEXTURE2D_SAMPLER2D(_CameraDepthTexture, sampler_CameraDepthTexture);
  16. float4 _CameraDepthTexture_TexelSize;
  17. TEXTURE2D_SAMPLER2D(_CameraMotionVectorsTexture, sampler_CameraMotionVectorsTexture);
  18. float2 _Jitter;
  19. float4 _FinalBlendParameters; // x: static, y: dynamic, z: motion amplification
  20. float _Sharpness;
  21. float2 GetClosestFragment(float2 uv)
  22. {
  23. const float2 k = _CameraDepthTexture_TexelSize.xy;
  24. const float4 neighborhood = float4(
  25. SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, UnityStereoClamp(uv - k)),
  26. SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, UnityStereoClamp(uv + float2(k.x, -k.y))),
  27. SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, UnityStereoClamp(uv + float2(-k.x, k.y))),
  28. SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, UnityStereoClamp(uv + k))
  29. );
  30. #if defined(UNITY_REVERSED_Z)
  31. #define COMPARE_DEPTH(a, b) step(b, a)
  32. #else
  33. #define COMPARE_DEPTH(a, b) step(a, b)
  34. #endif
  35. float3 result = float3(0.0, 0.0, SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, uv));
  36. result = lerp(result, float3(-1.0, -1.0, neighborhood.x), COMPARE_DEPTH(neighborhood.x, result.z));
  37. result = lerp(result, float3( 1.0, -1.0, neighborhood.y), COMPARE_DEPTH(neighborhood.y, result.z));
  38. result = lerp(result, float3(-1.0, 1.0, neighborhood.z), COMPARE_DEPTH(neighborhood.z, result.z));
  39. result = lerp(result, float3( 1.0, 1.0, neighborhood.w), COMPARE_DEPTH(neighborhood.w, result.z));
  40. return (uv + result.xy * k);
  41. }
  42. float4 ClipToAABB(float4 color, float3 minimum, float3 maximum)
  43. {
  44. // Note: only clips towards aabb center (but fast!)
  45. float3 center = 0.5 * (maximum + minimum);
  46. float3 extents = 0.5 * (maximum - minimum);
  47. // This is actually `distance`, however the keyword is reserved
  48. float3 offset = color.rgb - center;
  49. float3 ts = abs(extents / (offset + 0.0001));
  50. float t = saturate(Min3(ts.x, ts.y, ts.z));
  51. color.rgb = center + offset * t;
  52. return color;
  53. }
  54. struct OutputSolver
  55. {
  56. float4 destination : SV_Target0;
  57. float4 history : SV_Target1;
  58. };
  59. OutputSolver Solve(float2 motion, float2 texcoord)
  60. {
  61. const float2 k = _MainTex_TexelSize.xy;
  62. float2 uv = UnityStereoClamp(texcoord - _Jitter);
  63. float4 color = SAMPLE_TEXTURE2D(_MainTex, _MainTexSampler, uv);
  64. float4 topLeft = SAMPLE_TEXTURE2D(_MainTex, _MainTexSampler, UnityStereoClamp(uv - k * 0.5));
  65. float4 bottomRight = SAMPLE_TEXTURE2D(_MainTex, _MainTexSampler, UnityStereoClamp(uv + k * 0.5));
  66. float4 corners = 4.0 * (topLeft + bottomRight) - 2.0 * color;
  67. // Sharpen output
  68. color += (color - (corners * 0.166667)) * 2.718282 * _Sharpness;
  69. color = clamp(color, 0.0, HALF_MAX_MINUS1);
  70. // Tonemap color and history samples
  71. float4 average = (corners + color) * 0.142857;
  72. float4 history = SAMPLE_TEXTURE2D(_HistoryTex, sampler_HistoryTex, UnityStereoClamp(texcoord - motion));
  73. float motionLength = length(motion);
  74. float2 luma = float2(Luminance(average), Luminance(color));
  75. //float nudge = 4.0 * abs(luma.x - luma.y);
  76. float nudge = lerp(4.0, 0.25, saturate(motionLength * 100.0)) * abs(luma.x - luma.y);
  77. float4 minimum = min(bottomRight, topLeft) - nudge;
  78. float4 maximum = max(topLeft, bottomRight) + nudge;
  79. // Clip history samples
  80. history = ClipToAABB(history, minimum.xyz, maximum.xyz);
  81. // Blend method
  82. float weight = clamp(
  83. lerp(_FinalBlendParameters.x, _FinalBlendParameters.y, motionLength * _FinalBlendParameters.z),
  84. _FinalBlendParameters.y, _FinalBlendParameters.x
  85. );
  86. color = lerp(color, history, weight);
  87. color = clamp(color, 0.0, HALF_MAX_MINUS1);
  88. OutputSolver output;
  89. output.destination = color;
  90. output.history = color;
  91. return output;
  92. }
  93. OutputSolver FragSolverDilate(VaryingsDefault i)
  94. {
  95. float2 closest = GetClosestFragment(i.texcoordStereo);
  96. float2 motion = SAMPLE_TEXTURE2D(_CameraMotionVectorsTexture, sampler_CameraMotionVectorsTexture, closest).xy;
  97. return Solve(motion, i.texcoordStereo);
  98. }
  99. OutputSolver FragSolverNoDilate(VaryingsDefault i)
  100. {
  101. // Don't dilate in ortho !
  102. float2 motion = SAMPLE_TEXTURE2D(_CameraMotionVectorsTexture, sampler_CameraMotionVectorsTexture, i.texcoordStereo).xy;
  103. return Solve(motion, i.texcoordStereo);
  104. }
  105. ENDHLSL
  106. SubShader
  107. {
  108. Cull Off ZWrite Off ZTest Always
  109. // 0: Perspective
  110. Pass
  111. {
  112. HLSLPROGRAM
  113. #pragma vertex VertDefault
  114. #pragma fragment FragSolverDilate
  115. ENDHLSL
  116. }
  117. // 1: Ortho
  118. Pass
  119. {
  120. HLSLPROGRAM
  121. #pragma vertex VertDefault
  122. #pragma fragment FragSolverNoDilate
  123. ENDHLSL
  124. }
  125. }
  126. }