MotionBlurComponent.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using UnityEngine.Rendering;
  4. namespace UnityEngine.PostProcessing
  5. {
  6. public sealed class MotionBlurComponent : PostProcessingComponentCommandBuffer<MotionBlurModel>
  7. {
  8. public MotionBlurComponent.ReconstructionFilter reconstructionFilter
  9. {
  10. get
  11. {
  12. if (this.m_ReconstructionFilter == null)
  13. {
  14. this.m_ReconstructionFilter = new MotionBlurComponent.ReconstructionFilter();
  15. }
  16. return this.m_ReconstructionFilter;
  17. }
  18. }
  19. public MotionBlurComponent.FrameBlendingFilter frameBlendingFilter
  20. {
  21. get
  22. {
  23. if (this.m_FrameBlendingFilter == null)
  24. {
  25. this.m_FrameBlendingFilter = new MotionBlurComponent.FrameBlendingFilter();
  26. }
  27. return this.m_FrameBlendingFilter;
  28. }
  29. }
  30. public override bool active
  31. {
  32. get
  33. {
  34. MotionBlurModel.Settings settings = base.model.settings;
  35. return base.model.enabled && ((settings.shutterAngle > 0f && this.reconstructionFilter.IsSupported()) || settings.frameBlending > 0f) && SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLES2 && !this.context.interrupted;
  36. }
  37. }
  38. public override string GetName()
  39. {
  40. return "Motion Blur";
  41. }
  42. public void ResetHistory()
  43. {
  44. if (this.m_FrameBlendingFilter != null)
  45. {
  46. this.m_FrameBlendingFilter.Dispose();
  47. }
  48. this.m_FrameBlendingFilter = null;
  49. }
  50. public override DepthTextureMode GetCameraFlags()
  51. {
  52. return DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
  53. }
  54. public override CameraEvent GetCameraEvent()
  55. {
  56. return CameraEvent.BeforeImageEffects;
  57. }
  58. public override void OnEnable()
  59. {
  60. this.m_FirstFrame = true;
  61. }
  62. public override void PopulateCommandBuffer(CommandBuffer cb)
  63. {
  64. if (this.m_FirstFrame)
  65. {
  66. this.m_FirstFrame = false;
  67. return;
  68. }
  69. Material material = this.context.materialFactory.Get("Hidden/Post FX/Motion Blur");
  70. Material mat = this.context.materialFactory.Get("Hidden/Post FX/Blit");
  71. MotionBlurModel.Settings settings = base.model.settings;
  72. RenderTextureFormat format = (!this.context.isHdr) ? RenderTextureFormat.Default : RenderTextureFormat.DefaultHDR;
  73. int tempRT = MotionBlurComponent.Uniforms._TempRT;
  74. cb.GetTemporaryRT(tempRT, this.context.width, this.context.height, 0, FilterMode.Point, format);
  75. if (settings.shutterAngle > 0f && settings.frameBlending > 0f)
  76. {
  77. this.reconstructionFilter.ProcessImage(this.context, cb, ref settings, BuiltinRenderTextureType.CameraTarget, tempRT, material);
  78. this.frameBlendingFilter.BlendFrames(cb, settings.frameBlending, tempRT, BuiltinRenderTextureType.CameraTarget, material);
  79. this.frameBlendingFilter.PushFrame(cb, tempRT, this.context.width, this.context.height, material);
  80. }
  81. else if (settings.shutterAngle > 0f)
  82. {
  83. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._MainTex, BuiltinRenderTextureType.CameraTarget);
  84. cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, mat, 0);
  85. this.reconstructionFilter.ProcessImage(this.context, cb, ref settings, tempRT, BuiltinRenderTextureType.CameraTarget, material);
  86. }
  87. else if (settings.frameBlending > 0f)
  88. {
  89. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._MainTex, BuiltinRenderTextureType.CameraTarget);
  90. cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, mat, 0);
  91. this.frameBlendingFilter.BlendFrames(cb, settings.frameBlending, tempRT, BuiltinRenderTextureType.CameraTarget, material);
  92. this.frameBlendingFilter.PushFrame(cb, tempRT, this.context.width, this.context.height, material);
  93. }
  94. cb.ReleaseTemporaryRT(tempRT);
  95. }
  96. public override void OnDisable()
  97. {
  98. if (this.m_FrameBlendingFilter != null)
  99. {
  100. this.m_FrameBlendingFilter.Dispose();
  101. }
  102. }
  103. private MotionBlurComponent.ReconstructionFilter m_ReconstructionFilter;
  104. private MotionBlurComponent.FrameBlendingFilter m_FrameBlendingFilter;
  105. private bool m_FirstFrame = true;
  106. private static class Uniforms
  107. {
  108. internal static readonly int _VelocityScale = Shader.PropertyToID("_VelocityScale");
  109. internal static readonly int _MaxBlurRadius = Shader.PropertyToID("_MaxBlurRadius");
  110. internal static readonly int _RcpMaxBlurRadius = Shader.PropertyToID("_RcpMaxBlurRadius");
  111. internal static readonly int _VelocityTex = Shader.PropertyToID("_VelocityTex");
  112. internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
  113. internal static readonly int _Tile2RT = Shader.PropertyToID("_Tile2RT");
  114. internal static readonly int _Tile4RT = Shader.PropertyToID("_Tile4RT");
  115. internal static readonly int _Tile8RT = Shader.PropertyToID("_Tile8RT");
  116. internal static readonly int _TileMaxOffs = Shader.PropertyToID("_TileMaxOffs");
  117. internal static readonly int _TileMaxLoop = Shader.PropertyToID("_TileMaxLoop");
  118. internal static readonly int _TileVRT = Shader.PropertyToID("_TileVRT");
  119. internal static readonly int _NeighborMaxTex = Shader.PropertyToID("_NeighborMaxTex");
  120. internal static readonly int _LoopCount = Shader.PropertyToID("_LoopCount");
  121. internal static readonly int _TempRT = Shader.PropertyToID("_TempRT");
  122. internal static readonly int _History1LumaTex = Shader.PropertyToID("_History1LumaTex");
  123. internal static readonly int _History2LumaTex = Shader.PropertyToID("_History2LumaTex");
  124. internal static readonly int _History3LumaTex = Shader.PropertyToID("_History3LumaTex");
  125. internal static readonly int _History4LumaTex = Shader.PropertyToID("_History4LumaTex");
  126. internal static readonly int _History1ChromaTex = Shader.PropertyToID("_History1ChromaTex");
  127. internal static readonly int _History2ChromaTex = Shader.PropertyToID("_History2ChromaTex");
  128. internal static readonly int _History3ChromaTex = Shader.PropertyToID("_History3ChromaTex");
  129. internal static readonly int _History4ChromaTex = Shader.PropertyToID("_History4ChromaTex");
  130. internal static readonly int _History1Weight = Shader.PropertyToID("_History1Weight");
  131. internal static readonly int _History2Weight = Shader.PropertyToID("_History2Weight");
  132. internal static readonly int _History3Weight = Shader.PropertyToID("_History3Weight");
  133. internal static readonly int _History4Weight = Shader.PropertyToID("_History4Weight");
  134. }
  135. private enum Pass
  136. {
  137. VelocitySetup,
  138. TileMax1,
  139. TileMax2,
  140. TileMaxV,
  141. NeighborMax,
  142. Reconstruction,
  143. FrameCompression,
  144. FrameBlendingChroma,
  145. FrameBlendingRaw
  146. }
  147. public class ReconstructionFilter
  148. {
  149. public ReconstructionFilter()
  150. {
  151. this.CheckTextureFormatSupport();
  152. }
  153. private void CheckTextureFormatSupport()
  154. {
  155. if (!SystemInfo.SupportsRenderTextureFormat(this.m_PackedRTFormat))
  156. {
  157. this.m_PackedRTFormat = RenderTextureFormat.ARGB32;
  158. }
  159. }
  160. public bool IsSupported()
  161. {
  162. return SystemInfo.supportsMotionVectors;
  163. }
  164. public void ProcessImage(PostProcessingContext context, CommandBuffer cb, ref MotionBlurModel.Settings settings, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material)
  165. {
  166. int num = (int)(5f * (float)context.height / 100f);
  167. int num2 = ((num - 1) / 8 + 1) * 8;
  168. float value = settings.shutterAngle / 360f;
  169. cb.SetGlobalFloat(MotionBlurComponent.Uniforms._VelocityScale, value);
  170. cb.SetGlobalFloat(MotionBlurComponent.Uniforms._MaxBlurRadius, (float)num);
  171. cb.SetGlobalFloat(MotionBlurComponent.Uniforms._RcpMaxBlurRadius, 1f / (float)num);
  172. int velocityTex = MotionBlurComponent.Uniforms._VelocityTex;
  173. cb.GetTemporaryRT(velocityTex, context.width, context.height, 0, FilterMode.Point, this.m_PackedRTFormat, RenderTextureReadWrite.Linear);
  174. cb.Blit(null, velocityTex, material, 0);
  175. int tile2RT = MotionBlurComponent.Uniforms._Tile2RT;
  176. cb.GetTemporaryRT(tile2RT, context.width / 2, context.height / 2, 0, FilterMode.Point, this.m_VectorRTFormat, RenderTextureReadWrite.Linear);
  177. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._MainTex, velocityTex);
  178. cb.Blit(velocityTex, tile2RT, material, 1);
  179. int tile4RT = MotionBlurComponent.Uniforms._Tile4RT;
  180. cb.GetTemporaryRT(tile4RT, context.width / 4, context.height / 4, 0, FilterMode.Point, this.m_VectorRTFormat, RenderTextureReadWrite.Linear);
  181. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._MainTex, tile2RT);
  182. cb.Blit(tile2RT, tile4RT, material, 2);
  183. cb.ReleaseTemporaryRT(tile2RT);
  184. int tile8RT = MotionBlurComponent.Uniforms._Tile8RT;
  185. cb.GetTemporaryRT(tile8RT, context.width / 8, context.height / 8, 0, FilterMode.Point, this.m_VectorRTFormat, RenderTextureReadWrite.Linear);
  186. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._MainTex, tile4RT);
  187. cb.Blit(tile4RT, tile8RT, material, 2);
  188. cb.ReleaseTemporaryRT(tile4RT);
  189. Vector2 v = Vector2.one * ((float)num2 / 8f - 1f) * -0.5f;
  190. cb.SetGlobalVector(MotionBlurComponent.Uniforms._TileMaxOffs, v);
  191. cb.SetGlobalFloat(MotionBlurComponent.Uniforms._TileMaxLoop, (float)((int)((float)num2 / 8f)));
  192. int tileVRT = MotionBlurComponent.Uniforms._TileVRT;
  193. cb.GetTemporaryRT(tileVRT, context.width / num2, context.height / num2, 0, FilterMode.Point, this.m_VectorRTFormat, RenderTextureReadWrite.Linear);
  194. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._MainTex, tile8RT);
  195. cb.Blit(tile8RT, tileVRT, material, 3);
  196. cb.ReleaseTemporaryRT(tile8RT);
  197. int neighborMaxTex = MotionBlurComponent.Uniforms._NeighborMaxTex;
  198. int width = context.width / num2;
  199. int height = context.height / num2;
  200. cb.GetTemporaryRT(neighborMaxTex, width, height, 0, FilterMode.Point, this.m_VectorRTFormat, RenderTextureReadWrite.Linear);
  201. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._MainTex, tileVRT);
  202. cb.Blit(tileVRT, neighborMaxTex, material, 4);
  203. cb.ReleaseTemporaryRT(tileVRT);
  204. cb.SetGlobalFloat(MotionBlurComponent.Uniforms._LoopCount, (float)Mathf.Clamp(settings.sampleCount / 2, 1, 64));
  205. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._MainTex, source);
  206. cb.Blit(source, destination, material, 5);
  207. cb.ReleaseTemporaryRT(velocityTex);
  208. cb.ReleaseTemporaryRT(neighborMaxTex);
  209. }
  210. private RenderTextureFormat m_VectorRTFormat = RenderTextureFormat.RGHalf;
  211. private RenderTextureFormat m_PackedRTFormat = RenderTextureFormat.ARGB2101010;
  212. }
  213. public class FrameBlendingFilter
  214. {
  215. public FrameBlendingFilter()
  216. {
  217. this.m_UseCompression = MotionBlurComponent.FrameBlendingFilter.CheckSupportCompression();
  218. this.m_RawTextureFormat = MotionBlurComponent.FrameBlendingFilter.GetPreferredRenderTextureFormat();
  219. this.m_FrameList = new MotionBlurComponent.FrameBlendingFilter.Frame[4];
  220. }
  221. public void Dispose()
  222. {
  223. foreach (MotionBlurComponent.FrameBlendingFilter.Frame frame in this.m_FrameList)
  224. {
  225. frame.Release();
  226. }
  227. }
  228. public void PushFrame(CommandBuffer cb, RenderTargetIdentifier source, int width, int height, Material material)
  229. {
  230. int frameCount = Time.frameCount;
  231. if (frameCount == this.m_LastFrameCount)
  232. {
  233. return;
  234. }
  235. int num = frameCount % this.m_FrameList.Length;
  236. if (this.m_UseCompression)
  237. {
  238. this.m_FrameList[num].MakeRecord(cb, source, width, height, material);
  239. }
  240. else
  241. {
  242. this.m_FrameList[num].MakeRecordRaw(cb, source, width, height, this.m_RawTextureFormat);
  243. }
  244. this.m_LastFrameCount = frameCount;
  245. }
  246. public void BlendFrames(CommandBuffer cb, float strength, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material)
  247. {
  248. float time = Time.time;
  249. MotionBlurComponent.FrameBlendingFilter.Frame frameRelative = this.GetFrameRelative(-1);
  250. MotionBlurComponent.FrameBlendingFilter.Frame frameRelative2 = this.GetFrameRelative(-2);
  251. MotionBlurComponent.FrameBlendingFilter.Frame frameRelative3 = this.GetFrameRelative(-3);
  252. MotionBlurComponent.FrameBlendingFilter.Frame frameRelative4 = this.GetFrameRelative(-4);
  253. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._History1LumaTex, frameRelative.lumaTexture);
  254. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._History2LumaTex, frameRelative2.lumaTexture);
  255. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._History3LumaTex, frameRelative3.lumaTexture);
  256. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._History4LumaTex, frameRelative4.lumaTexture);
  257. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._History1ChromaTex, frameRelative.chromaTexture);
  258. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._History2ChromaTex, frameRelative2.chromaTexture);
  259. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._History3ChromaTex, frameRelative3.chromaTexture);
  260. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._History4ChromaTex, frameRelative4.chromaTexture);
  261. cb.SetGlobalFloat(MotionBlurComponent.Uniforms._History1Weight, frameRelative.CalculateWeight(strength, time));
  262. cb.SetGlobalFloat(MotionBlurComponent.Uniforms._History2Weight, frameRelative2.CalculateWeight(strength, time));
  263. cb.SetGlobalFloat(MotionBlurComponent.Uniforms._History3Weight, frameRelative3.CalculateWeight(strength, time));
  264. cb.SetGlobalFloat(MotionBlurComponent.Uniforms._History4Weight, frameRelative4.CalculateWeight(strength, time));
  265. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._MainTex, source);
  266. cb.Blit(source, destination, material, (!this.m_UseCompression) ? 8 : 7);
  267. }
  268. private static bool CheckSupportCompression()
  269. {
  270. return SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.R8) && SystemInfo.supportedRenderTargetCount > 1;
  271. }
  272. private static RenderTextureFormat GetPreferredRenderTextureFormat()
  273. {
  274. RenderTextureFormat[] array = new RenderTextureFormat[3];
  275. RuntimeHelpers.InitializeArray(array, fieldof(<PrivateImplementationDetails>.$field-51A7A390CD6DE245186881400B18C9D822EFE240).FieldHandle);
  276. RenderTextureFormat[] array2 = array;
  277. foreach (RenderTextureFormat renderTextureFormat in array2)
  278. {
  279. if (SystemInfo.SupportsRenderTextureFormat(renderTextureFormat))
  280. {
  281. return renderTextureFormat;
  282. }
  283. }
  284. return RenderTextureFormat.Default;
  285. }
  286. private MotionBlurComponent.FrameBlendingFilter.Frame GetFrameRelative(int offset)
  287. {
  288. int num = (Time.frameCount + this.m_FrameList.Length + offset) % this.m_FrameList.Length;
  289. return this.m_FrameList[num];
  290. }
  291. private bool m_UseCompression;
  292. private RenderTextureFormat m_RawTextureFormat;
  293. private MotionBlurComponent.FrameBlendingFilter.Frame[] m_FrameList;
  294. private int m_LastFrameCount;
  295. private struct Frame
  296. {
  297. public float CalculateWeight(float strength, float currentTime)
  298. {
  299. if (Mathf.Approximately(this.m_Time, 0f))
  300. {
  301. return 0f;
  302. }
  303. float num = Mathf.Lerp(80f, 16f, strength);
  304. return Mathf.Exp((this.m_Time - currentTime) * num);
  305. }
  306. public void Release()
  307. {
  308. if (this.lumaTexture != null)
  309. {
  310. RenderTexture.ReleaseTemporary(this.lumaTexture);
  311. }
  312. if (this.chromaTexture != null)
  313. {
  314. RenderTexture.ReleaseTemporary(this.chromaTexture);
  315. }
  316. this.lumaTexture = null;
  317. this.chromaTexture = null;
  318. }
  319. public void MakeRecord(CommandBuffer cb, RenderTargetIdentifier source, int width, int height, Material material)
  320. {
  321. this.Release();
  322. this.lumaTexture = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.R8, RenderTextureReadWrite.Linear);
  323. this.chromaTexture = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.R8, RenderTextureReadWrite.Linear);
  324. this.lumaTexture.filterMode = FilterMode.Point;
  325. this.chromaTexture.filterMode = FilterMode.Point;
  326. if (this.m_MRT == null)
  327. {
  328. this.m_MRT = new RenderTargetIdentifier[2];
  329. }
  330. this.m_MRT[0] = this.lumaTexture;
  331. this.m_MRT[1] = this.chromaTexture;
  332. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._MainTex, source);
  333. cb.SetRenderTarget(this.m_MRT, this.lumaTexture);
  334. cb.DrawMesh(GraphicsUtils.quad, Matrix4x4.identity, material, 0, 6);
  335. this.m_Time = Time.time;
  336. }
  337. public void MakeRecordRaw(CommandBuffer cb, RenderTargetIdentifier source, int width, int height, RenderTextureFormat format)
  338. {
  339. this.Release();
  340. this.lumaTexture = RenderTexture.GetTemporary(width, height, 0, format);
  341. this.lumaTexture.filterMode = FilterMode.Point;
  342. cb.SetGlobalTexture(MotionBlurComponent.Uniforms._MainTex, source);
  343. cb.Blit(source, this.lumaTexture);
  344. this.m_Time = Time.time;
  345. }
  346. public RenderTexture lumaTexture;
  347. public RenderTexture chromaTexture;
  348. private float m_Time;
  349. private RenderTargetIdentifier[] m_MRT;
  350. }
  351. }
  352. }
  353. }