You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
6.3 KiB

  1. #ifndef __TAA__
  2. #define __TAA__
  3. #pragma only_renderers ps4 xboxone d3d11 d3d9 xbox360 opengl glcore
  4. #pragma exclude_renderers gles
  5. #include "UnityCG.cginc"
  6. #include "Common.cginc"
  7. // -----------------------------------------------------------------------------
  8. // Solver
  9. #define TAA_USE_STABLE_BUT_GHOSTY_VARIANT 0
  10. #if !defined(TAA_DILATE_MOTION_VECTOR_SAMPLE)
  11. #define TAA_DILATE_MOTION_VECTOR_SAMPLE 1
  12. #endif
  13. #define TAA_FRAGMENT_MOTION_HISTORY_DECAY 0.85
  14. #define TAA_FINAL_BLEND_STATIC_FACTOR _FinalBlendParameters.x
  15. #define TAA_FINAL_BLEND_DYNAMIC_FACTOR _FinalBlendParameters.y
  16. #define TAA_MOTION_AMPLIFICATION _FinalBlendParameters.z
  17. struct VaryingsSolver
  18. {
  19. float4 vertex : SV_POSITION;
  20. float4 uv : TEXCOORD0; // [xy: _MainTex.uv, zw: _HistoryTex.uv]
  21. };
  22. struct OutputSolver
  23. {
  24. float4 destination : SV_Target0;
  25. float4 history : SV_Target1;
  26. };
  27. sampler2D _HistoryTex;
  28. sampler2D _CameraMotionVectorsTexture;
  29. sampler2D _CameraDepthTexture;
  30. float4 _HistoryTex_TexelSize;
  31. float4 _CameraDepthTexture_TexelSize;
  32. float2 _Jitter;
  33. float4 _SharpenParameters;
  34. float4 _FinalBlendParameters;
  35. VaryingsSolver VertSolver(AttributesDefault input)
  36. {
  37. VaryingsSolver output;
  38. float4 vertex = UnityObjectToClipPos(input.vertex);
  39. output.vertex = vertex;
  40. output.uv = input.texcoord.xyxy;
  41. #if UNITY_UV_STARTS_AT_TOP
  42. if (_MainTex_TexelSize.y < 0)
  43. output.uv.y = 1.0 - input.texcoord.y;
  44. #endif
  45. return output;
  46. }
  47. float2 GetClosestFragment(float2 uv)
  48. {
  49. const float2 k = _CameraDepthTexture_TexelSize.xy;
  50. const float4 neighborhood = float4(
  51. SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv - k),
  52. SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv + float2(k.x, -k.y)),
  53. SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv + float2(-k.x, k.y)),
  54. SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv + k)
  55. );
  56. #if defined(UNITY_REVERSED_Z)
  57. #define COMPARE_DEPTH(a, b) step(b, a)
  58. #else
  59. #define COMPARE_DEPTH(a, b) step(a, b)
  60. #endif
  61. float3 result = float3(0.0, 0.0, SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv));
  62. result = lerp(result, float3(-1.0, -1.0, neighborhood.x), COMPARE_DEPTH(neighborhood.x, result.z));
  63. result = lerp(result, float3( 1.0, -1.0, neighborhood.y), COMPARE_DEPTH(neighborhood.y, result.z));
  64. result = lerp(result, float3(-1.0, 1.0, neighborhood.z), COMPARE_DEPTH(neighborhood.z, result.z));
  65. result = lerp(result, float3( 1.0, 1.0, neighborhood.w), COMPARE_DEPTH(neighborhood.w, result.z));
  66. return (uv + result.xy * k);
  67. }
  68. // Adapted from Playdead's TAA implementation
  69. // https://github.com/playdeadgames/temporal
  70. float4 ClipToAABB(float4 color, float p, float3 minimum, float3 maximum)
  71. {
  72. // note: only clips towards aabb center (but fast!)
  73. float3 center = 0.5 * (maximum + minimum);
  74. float3 extents = 0.5 * (maximum - minimum);
  75. // This is actually `distance`, however the keyword is reserved
  76. float4 offset = color - float4(center, p);
  77. float3 repeat = abs(offset.xyz / extents);
  78. repeat.x = max(repeat.x, max(repeat.y, repeat.z));
  79. if (repeat.x > 1.0)
  80. {
  81. // `color` is not intersecting (nor inside) the AABB; it's clipped to the closest extent
  82. return float4(center, p) + offset / repeat.x;
  83. }
  84. else
  85. {
  86. // `color` is intersecting (or inside) the AABB.
  87. // Note: for whatever reason moving this return statement from this else into a higher
  88. // scope makes the NVIDIA drivers go beyond bonkers
  89. return color;
  90. }
  91. }
  92. OutputSolver FragSolver(VaryingsSolver input)
  93. {
  94. #if TAA_DILATE_MOTION_VECTOR_SAMPLE
  95. float2 motion = tex2D(_CameraMotionVectorsTexture, GetClosestFragment(input.uv.zw)).xy;
  96. #else
  97. // Don't dilate in ortho !
  98. float2 motion = tex2D(_CameraMotionVectorsTexture, input.uv.zw).xy;
  99. #endif
  100. const float2 k = _MainTex_TexelSize.xy;
  101. float2 uv = input.uv.xy;
  102. #if UNITY_UV_STARTS_AT_TOP
  103. uv -= _MainTex_TexelSize.y < 0 ? _Jitter * float2(1.0, -1.0) : _Jitter;
  104. #else
  105. uv -= _Jitter;
  106. #endif
  107. float4 color = tex2D(_MainTex, uv);
  108. float4 topLeft = tex2D(_MainTex, uv - k * 0.5);
  109. float4 bottomRight = tex2D(_MainTex, uv + k * 0.5);
  110. float4 corners = 4.0 * (topLeft + bottomRight) - 2.0 * color;
  111. // Sharpen output
  112. color += (color - (corners * 0.166667)) * 2.718282 * _SharpenParameters.x;
  113. color = max(0.0, color);
  114. // Tonemap color and history samples
  115. float4 average = FastToneMap((corners + color) * 0.142857);
  116. topLeft = FastToneMap(topLeft);
  117. bottomRight = FastToneMap(bottomRight);
  118. color = FastToneMap(color);
  119. float4 history = tex2D(_HistoryTex, input.uv.zw - motion);
  120. // Only use this variant for arch viz or scenes that don't have any animated objects (camera animation is fine)
  121. #if TAA_USE_STABLE_BUT_GHOSTY_VARIANT
  122. float4 luma = float4(Luminance(topLeft.rgb), Luminance(bottomRight.rgb), Luminance(average.rgb), Luminance(color.rgb));
  123. float nudge = lerp(6.28318530718, 0.5, saturate(2.0 * history.a)) * max(abs(luma.z - luma.w), abs(luma.x - luma.y));
  124. float4 minimum = lerp(bottomRight, topLeft, step(luma.x, luma.y)) - nudge;
  125. float4 maximum = lerp(topLeft, bottomRight, step(luma.x, luma.y)) + nudge;
  126. #else
  127. float2 luma = float2(Luminance(average.rgb), Luminance(color.rgb));
  128. float nudge = 4.0 * abs(luma.x - luma.y);
  129. float4 minimum = min(bottomRight, topLeft) - nudge;
  130. float4 maximum = max(topLeft, bottomRight) + nudge;
  131. #endif
  132. history = FastToneMap(history);
  133. // Clip history samples
  134. history = ClipToAABB(history, history.a, minimum.xyz, maximum.xyz);
  135. // Store fragment motion history
  136. color.a = saturate(smoothstep(0.002 * _MainTex_TexelSize.z, 0.0035 * _MainTex_TexelSize.z, length(motion)));
  137. // Blend method
  138. float weight = clamp(lerp(TAA_FINAL_BLEND_STATIC_FACTOR, TAA_FINAL_BLEND_DYNAMIC_FACTOR,
  139. length(motion) * TAA_MOTION_AMPLIFICATION), TAA_FINAL_BLEND_DYNAMIC_FACTOR, TAA_FINAL_BLEND_STATIC_FACTOR);
  140. color = FastToneUnmap(lerp(color, history, weight));
  141. OutputSolver output;
  142. output.destination = color;
  143. color.a *= TAA_FRAGMENT_MOTION_HISTORY_DECAY;
  144. output.history = color;
  145. return output;
  146. }
  147. // -----------------------------------------------------------------------------
  148. // Alpha clearance
  149. float4 FragAlphaClear(VaryingsDefault input) : SV_Target
  150. {
  151. return float4(tex2D(_MainTex, input.uv).rgb, 0.0);
  152. }
  153. #endif // __TAA__