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.

308 lines
6.5 KiB

5 years ago
  1. // Copyright (c) <2015> <Playdead>
  2. // This file is subject to the MIT License as seen in the root of this folder structure (LICENSE.TXT)
  3. // AUTHOR: Lasse Jon Fuglsang Pedersen <lasse@playdead.com>
  4. Shader "Hidden/VelocityBuffer"
  5. {
  6. CGINCLUDE
  7. //--- program begin
  8. #pragma only_renderers ps4 xboxone d3d11 d3d9 xbox360 opengl glcore gles3 metal vulkan
  9. #pragma target 3.0
  10. #pragma multi_compile CAMERA_PERSPECTIVE CAMERA_ORTHOGRAPHIC
  11. #pragma multi_compile __ TILESIZE_10 TILESIZE_20 TILESIZE_40
  12. #include "UnityCG.cginc"
  13. #include "IncDepth.cginc"
  14. #if UNITY_VERSION < 540
  15. uniform float4x4 _CameraToWorld;// UNITY_SHADER_NO_UPGRADE
  16. #endif
  17. #if UNITY_VERSION < 550
  18. #define STEREO_ARRAY
  19. #define STEREO_INDEX(x) x
  20. #else
  21. #define STEREO_ARRAY [2]
  22. #define STEREO_INDEX(x) x[unity_StereoEyeIndex]
  23. #endif
  24. uniform sampler2D_half _VelocityTex;
  25. uniform float4 _VelocityTex_TexelSize;
  26. uniform float4 _ProjectionExtents STEREO_ARRAY;// xy = frustum extents at distance 1, zw = jitter at distance 1
  27. uniform float4x4 _CurrV STEREO_ARRAY;
  28. uniform float4x4 _CurrVP STEREO_ARRAY;
  29. uniform float4x4 _CurrM;
  30. uniform float4x4 _PrevVP STEREO_ARRAY;
  31. uniform float4x4 _PrevVP_NoFlip STEREO_ARRAY;
  32. uniform float4x4 _PrevM;
  33. struct blit_v2f
  34. {
  35. float4 cs_pos : SV_POSITION;
  36. float2 ss_txc : TEXCOORD0;
  37. float2 vs_ray : TEXCOORD1;
  38. };
  39. blit_v2f blit_vert(appdata_img IN)
  40. {
  41. blit_v2f OUT;
  42. #if UNITY_VERSION < 540
  43. OUT.cs_pos = mul(UNITY_MATRIX_MVP, IN.vertex);
  44. #else
  45. OUT.cs_pos = UnityObjectToClipPos(IN.vertex);
  46. #endif
  47. #if UNITY_SINGLE_PASS_STEREO
  48. OUT.ss_txc = UnityStereoTransformScreenSpaceTex(IN.texcoord.xy);
  49. #else
  50. OUT.ss_txc = IN.texcoord.xy;
  51. #endif
  52. OUT.vs_ray = (2.0 * IN.texcoord.xy - 1.0) * STEREO_INDEX(_ProjectionExtents).xy + STEREO_INDEX(_ProjectionExtents).zw;
  53. return OUT;
  54. }
  55. float4 blit_frag_prepass(blit_v2f IN) : SV_Target
  56. {
  57. // reconstruct world position
  58. float vs_dist = depth_sample_linear(IN.ss_txc);
  59. #if CAMERA_PERSPECTIVE
  60. float3 vs_pos = float3(IN.vs_ray, 1.0) * vs_dist;
  61. #elif CAMERA_ORTHOGRAPHIC
  62. float3 vs_pos = float3(IN.vs_ray, vs_dist);
  63. #else
  64. #error "missing keyword CAMERA_..."
  65. #endif
  66. #if UNITY_VERSION < 540
  67. float4 ws_pos = mul(_CameraToWorld, float4(vs_pos, 1.0));// UNITY_SHADER_NO_UPGRADE
  68. #else
  69. float4 ws_pos = mul(unity_CameraToWorld, float4(vs_pos, 1.0));
  70. #endif
  71. //// NOTE: world space debug at 3D crane
  72. //return 0.1 * float4(ws_pos.xy - float2(595.0, -215.0), 0.0, 0.0);
  73. // reproject into previous frame
  74. float4 rp_cs_pos = mul(STEREO_INDEX(_PrevVP_NoFlip), ws_pos);
  75. float2 rp_ss_ndc = rp_cs_pos.xy / rp_cs_pos.w;
  76. float2 rp_ss_txc = 0.5 * rp_ss_ndc + 0.5;
  77. // estimate velocity
  78. #if UNITY_SINGLE_PASS_STEREO
  79. float2 ss_vel = IN.ss_txc - UnityStereoTransformScreenSpaceTex(rp_ss_txc);
  80. #else
  81. float2 ss_vel = IN.ss_txc - rp_ss_txc;
  82. #endif
  83. // output
  84. return float4(ss_vel, 0.0, 0.0);
  85. }
  86. float4 blit_frag_tilemax(blit_v2f IN) : SV_Target
  87. {
  88. #if TILESIZE_10
  89. const int support = 10;
  90. #elif TILESIZE_20
  91. const int support = 20;
  92. #elif TILESIZE_40
  93. const int support = 40;
  94. #else
  95. const int support = 1;
  96. #endif
  97. const float2 step = _VelocityTex_TexelSize.xy;
  98. const float2 base = IN.ss_txc + (0.5 - 0.5 * support) * step;
  99. const float2 du = float2(_VelocityTex_TexelSize.x, 0.0);
  100. const float2 dv = float2(0.0, _VelocityTex_TexelSize.y);
  101. float2 mv = 0.0;
  102. float rmv = 0.0;
  103. [unroll(10)]
  104. for (int i = 0; i != support; i++)
  105. {
  106. [unroll(10)]
  107. for (int j = 0; j != support; j++)
  108. {
  109. float2 v = tex2D(_VelocityTex, base + i * dv + j * du).xy;
  110. float rv = dot(v, v);
  111. if (rv > rmv)
  112. {
  113. mv = v;
  114. rmv = rv;
  115. }
  116. }
  117. }
  118. return float4(mv, 0.0, 0.0);
  119. }
  120. float4 blit_frag_neighbormax(blit_v2f IN) : SV_Target
  121. {
  122. const float2 du = float2(_VelocityTex_TexelSize.x, 0.0);
  123. const float2 dv = float2(0.0, _VelocityTex_TexelSize.y);
  124. float2 mv = 0.0;
  125. float dmv = 0.0;
  126. [unroll]
  127. for (int i = -1; i <= 1; i++)
  128. {
  129. [unroll]
  130. for (int j = -1; j <= 1; j++)
  131. {
  132. float2 v = tex2D(_VelocityTex, IN.ss_txc + i * dv + j * du).xy;
  133. float dv = dot(v, v);
  134. if (dv > dmv)
  135. {
  136. mv = v;
  137. dmv = dv;
  138. }
  139. }
  140. }
  141. return float4(mv, 0.0, 0.0);
  142. }
  143. struct v2f
  144. {
  145. float4 cs_pos : SV_POSITION;
  146. float4 ss_pos : TEXCOORD0;
  147. float3 cs_xy_curr : TEXCOORD1;
  148. float3 cs_xy_prev : TEXCOORD2;
  149. };
  150. v2f process_vertex(float4 ws_pos_curr, float4 ws_pos_prev)
  151. {
  152. v2f OUT;
  153. const float occlusion_bias = 0.03;
  154. OUT.cs_pos = mul(mul(STEREO_INDEX(_CurrVP), _CurrM), ws_pos_curr);
  155. OUT.ss_pos = ComputeScreenPos(OUT.cs_pos);
  156. OUT.ss_pos.z = -mul(mul(STEREO_INDEX(_CurrV), _CurrM), ws_pos_curr).z - occlusion_bias;// COMPUTE_EYEDEPTH
  157. OUT.cs_xy_curr = OUT.cs_pos.xyw;
  158. OUT.cs_xy_prev = mul(mul(STEREO_INDEX(_PrevVP), _PrevM), ws_pos_prev).xyw;
  159. #if UNITY_UV_STARTS_AT_TOP
  160. OUT.cs_xy_curr.y = -OUT.cs_xy_curr.y;
  161. OUT.cs_xy_prev.y = -OUT.cs_xy_prev.y;
  162. #endif
  163. return OUT;
  164. }
  165. v2f vert(appdata_base IN)
  166. {
  167. return process_vertex(IN.vertex, IN.vertex);
  168. }
  169. v2f vert_skinned(appdata_base IN)
  170. {
  171. return process_vertex(IN.vertex, float4(IN.normal, 1.0));// previous frame positions stored in normal data
  172. }
  173. float4 frag(v2f IN) : SV_Target
  174. {
  175. float2 ss_txc = IN.ss_pos.xy / IN.ss_pos.w;
  176. float scene_d =depth_sample_linear(ss_txc);
  177. // discard if occluded
  178. clip(scene_d - IN.ss_pos.z);
  179. // compute velocity in ndc
  180. float2 ndc_curr = IN.cs_xy_curr.xy / IN.cs_xy_curr.z;
  181. float2 ndc_prev = IN.cs_xy_prev.xy / IN.cs_xy_prev.z;
  182. // compute screen space velocity [0,1;0,1]
  183. #if UNITY_SINGLE_PASS_STEREO
  184. return float4(0.5 * (ndc_curr - ndc_prev) * unity_StereoScaleOffset[unity_StereoEyeIndex].xy, 0.0, 0.0);
  185. #else
  186. return float4(0.5 * (ndc_curr - ndc_prev), 0.0, 0.0);
  187. #endif
  188. }
  189. //--- program end
  190. ENDCG
  191. SubShader
  192. {
  193. // 0: prepass
  194. Pass
  195. {
  196. ZTest Always Cull Off ZWrite Off
  197. Fog { Mode Off }
  198. CGPROGRAM
  199. #pragma vertex blit_vert
  200. #pragma fragment blit_frag_prepass
  201. ENDCG
  202. }
  203. // 1: vertices
  204. Pass
  205. {
  206. ZTest LEqual Cull Back ZWrite On
  207. Fog { Mode Off }
  208. CGPROGRAM
  209. #pragma vertex vert
  210. #pragma fragment frag
  211. ENDCG
  212. }
  213. // 2: vertices skinned
  214. Pass
  215. {
  216. ZTest LEqual Cull Back ZWrite On
  217. Fog { Mode Off }
  218. CGPROGRAM
  219. #pragma vertex vert_skinned
  220. #pragma fragment frag
  221. ENDCG
  222. }
  223. // 3: tilemax
  224. Pass
  225. {
  226. ZTest Always Cull Off ZWrite Off
  227. Fog { Mode Off }
  228. CGPROGRAM
  229. #pragma vertex blit_vert
  230. #pragma fragment blit_frag_tilemax
  231. ENDCG
  232. }
  233. // 4: neighbormax
  234. Pass
  235. {
  236. ZTest Always Cull Off ZWrite Off
  237. Fog { Mode Off }
  238. CGPROGRAM
  239. #pragma vertex blit_vert
  240. #pragma fragment blit_frag_neighbormax
  241. ENDCG
  242. }
  243. }
  244. Fallback Off
  245. }