context: using UnityEngine.Rendering;
  
  namespace UnityEngine.PostProcessing
  {
      using Settings = MotionBlurModel.Settings;
  
      public sealed class MotionBlurComponent : PostProcessingComponentCommandBuffer<MotionBlurModel>
      {
          static class Uniforms
          {
              internal static readonly int _VelocityScale     = Shader.PropertyToID("_VelocityScale");
              internal static readonly int _MaxBlurRadius     = Shader.PropertyToID("_MaxBlurRadius");
              internal static readonly int _VelocityTex       = Shader.PropertyToID("_VelocityTex");
              internal static readonly int _Tile4RT           = Shader.PropertyToID("_Tile4RT");
              internal static readonly int _MainTex           = Shader.PropertyToID("_MainTex");
              internal static readonly int _Tile8RT           = Shader.PropertyToID("_Tile8RT");
              internal static readonly int _TileMaxOffs       = Shader.PropertyToID("_TileMaxOffs");
              internal static readonly int _TileMaxLoop       = Shader.PropertyToID("_TileMaxLoop");
              internal static readonly int _TileVRT           = Shader.PropertyToID("_TileVRT");
              internal static readonly int _NeighborMaxTex    = Shader.PropertyToID("_NeighborMaxTex");
              internal static readonly int _LoopCount         = Shader.PropertyToID("_LoopCount");
              internal static readonly int _TempRT            = Shader.PropertyToID("_TempRT");
  
              internal static readonly int _History1LumaTex   = Shader.PropertyToID("_History1LumaTex");
              internal static readonly int _History2LumaTex   = Shader.PropertyToID("_History2LumaTex");
              internal static readonly int _History3LumaTex   = Shader.PropertyToID("_History3LumaTex");
              internal static readonly int _History4LumaTex   = Shader.PropertyToID("_History4LumaTex");
  
              internal static readonly int _History1ChromaTex = Shader.PropertyToID("_History1ChromaTex");
              internal static readonly int _History2ChromaTex = Shader.PropertyToID("_History2ChromaTex");
              internal static readonly int _History3ChromaTex = Shader.PropertyToID("_History3ChromaTex");
              internal static readonly int _History4ChromaTex = Shader.PropertyToID("_History4ChromaTex");
  
              internal static readonly int _History1Weight    = Shader.PropertyToID("_History1Weight");
              internal static readonly int _History2Weight    = Shader.PropertyToID("_History2Weight");
              internal static readonly int _History3Weight    = Shader.PropertyToID("_History3Weight");
              internal static readonly int _History4Weight    = Shader.PropertyToID("_History4Weight");
          }
  
          enum Pass
          {
              VelocitySetup,
              TileMax4,
              TileMax2,
              TileMaxV,
              NeighborMax,
              Reconstruction,
              ReconstructionUnroll,
              FrameCompression,
              FrameBlendingChroma,
              FrameBlendingRaw
          }
  
          public class ReconstructionFilter
          {
              // Texture format for storing 2D vectors.
              RenderTextureFormat m_VectorRTFormat = RenderTextureFormat.RGHalf;
  
              // Texture format for storing packed velocity/depth.
              RenderTextureFormat m_PackedRTFormat = RenderTextureFormat.ARGB2101010;
  
              bool m_UseUnrolledShader;
  
              public ReconstructionFilter()
              {
                  CheckTextureFormatSupport();
  
                  // Use loop unrolling on Adreno GPUs to avoid shader issues.
                  m_UseUnrolledShader = SystemInfo.graphicsDeviceName.Contains("Adreno");
              }
  
              void CheckTextureFormatSupport()
              {
                  // If 2:10:10:10 isn't supported, use ARGB32 instead.
                  if (!SystemInfo.SupportsRenderTextureFormat(m_PackedRTFormat))
                      m_PackedRTFormat = RenderTextureFormat.ARGB32;
              }
  
              public bool IsSupported()
              {
                  return SystemInfo.supportsMotionVectors;
              }
  
              public void ProcessImage(PostProcessingContext context, CommandBuffer cb, ref Settings settings, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material)
              {
                  const float kMaxBlurRadius = 5f;
  
                  // Calculate the maximum blur radius in pixels.
                  int maxBlurPixels = (int)(kMaxBlurRadius * context.height / 100);
  
                  // Calculate the TileMax size.
                  // It should be a multiple of 8 and larger than maxBlur.
                  int tileSize = ((maxBlurPixels - 1) / 8 + 1) * 8;
  
                  // Pass 1 - Velocity/depth packing
                  // Motion vectors are scaled by an empirical factor of 1.45.
                  var velocityScale = settings.shutterAngle / 360f * 1.45f;
                  cb.SetGlobalFloat(Uniforms._VelocityScale, velocityScale);
                  cb.SetGlobalFloat(Uniforms._MaxBlurRadius, maxBlurPixels);
  
                  int vbuffer = Uniforms._VelocityTex;
                  cb.GetTemporaryRT(vbuffer, context.width, context.height, 0, FilterMode.Point, m_PackedRTFormat, RenderTextureReadWrite.Linear);
                  cb.Blit((Texture)null, vbuffer, material, (int)Pass.VelocitySetup);
  
                  // Pass 2 - First TileMax filter (1/4 downsize)
                  int tile4 = Uniforms._Tile4RT;
                  cb.GetTemporaryRT(tile4, context.width / 4, context.height / 4, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear);
                  cb.SetGlobalTexture(Uniforms._MainTex, vbuffer);
                  cb.Blit(vbuffer, tile4, material, (int)Pass.TileMax4);
  
                  // Pass 3 - Second TileMax filter (1/2 downsize)
                  int tile8 = Uniforms._Tile8RT;
                  cb.GetTemporaryRT(tile8, context.width / 8, context.height / 8, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear);
                  cb.SetGlobalTexture(Uniforms._MainTex, tile4);
                  cb.Blit(tile4, tile8, material, (int)Pass.TileMax2);
                  cb.ReleaseTemporaryRT(tile4);
  
                  // Pass 4 - Third TileMax filter (reduce to tileSize)
                  var tileMaxOffs = Vector2.one * (tileSize / 8f - 1f) * -0.5f;
                  cb.SetGlobalVector(Uniforms._TileMaxOffs, tileMaxOffs);
                  cb.SetGlobalFloat(Uniforms._TileMaxLoop, (int)(tileSize / 8f));
  
                  int tile = Uniforms._TileVRT;
                  cb.GetTemporaryRT(tile, context.width / tileSize, context.height / tileSize, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear);
                  cb.SetGlobalTexture(Uniforms._MainTex, tile8);
                  cb.Blit(tile8, tile, material, (int)Pass.TileMaxV);
                  cb.ReleaseTemporaryRT(tile8);
  
                  // Pass 5 - NeighborMax filter
                  int neighborMax = Uniforms._NeighborMaxTex;
                  int neighborMaxWidth = context.width / tileSize;
                  int neighborMaxHeight = context.height / tileSize;
                  cb.GetTemporaryRT(neighborMax, neighborMaxWidth, neighborMaxHeight, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear);
                  cb.SetGlobalTexture(Uniforms._MainTex, tile);
                  cb.Blit(tile, neighborMax, material, (int)Pass.NeighborMax);
                  cb.ReleaseTemporaryRT(tile);
  
                  // Pass 6 - Reconstruction pass
                  cb.SetGlobalFloat(Uniforms._LoopCount, Mathf.Clamp(settings.sampleCount / 2, 1, 64));
                  cb.SetGlobalFloat(Uniforms._MaxBlurRadius, maxBlurPixels);
                  cb.SetGlobalTexture(Uniforms._MainTex, source);
  
                  cb.Blit(source, destination, material, m_UseUnrolledShader ? (int)Pass.ReconstructionUnroll : (int)Pass.Reconstruction);
  
                  cb.ReleaseTemporaryRT(vbuffer);
                  cb.ReleaseTemporaryRT(neighborMax);
              }
          }
  
          public class FrameBlendingFilter
          {
              struct Frame
              {
                  public RenderTexture lumaTexture;
                  public RenderTexture chromaTexture;
  
                  float m_Time;
                  RenderTargetIdentifier[] m_MRT;
  
                  public float CalculateWeight(float strength, float currentTime)
                  {
                      if (Mathf.Approximately(m_Time, 0f))
                          return 0f;
  
                      var coeff = Mathf.Lerp(80f, 16f, strength);
                      return Mathf.Exp((m_Time - currentTime) * coeff);
                  }
  
                  public void Release()
                  {
                      if (lumaTexture != null)
                          RenderTexture.ReleaseTemporary(lumaTexture);
  
                      if (chromaTexture != null)
                          RenderTexture.ReleaseTemporary(chromaTexture);
  
                      lumaTexture = null;
                      chromaTexture = null;
                  }
  
                  public void MakeRecord(CommandBuffer cb, RenderTargetIdentifier source, int width, int height, Material material)
                  {
                      Release();
  
                      lumaTexture = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.R8, RenderTextureReadWrite.Linear);
                      chromaTexture = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.R8, RenderTextureReadWrite.Linear);
  
                      lumaTexture.filterMode = FilterMode.Point;
                      chromaTexture.filterMode = FilterMode.Point;
  
                      if (m_MRT == null)
                          m_MRT = new RenderTargetIdentifier[2];
  
                      m_MRT[0] = lumaTexture;
                      m_MRT[1] = chromaTexture;
  
                      cb.SetGlobalTexture(Uniforms._MainTex, source);
                      cb.SetRenderTarget(m_MRT, lumaTexture);
                      cb.DrawMesh(GraphicsUtils.quad, Matrix4x4.identity, material, 0, (int)Pass.FrameCompression);
  
                      m_Time = Time.time;
                  }
  
                  public void MakeRecordRaw(CommandBuffer cb, RenderTargetIdentifier source, int width, int height, RenderTextureFormat format)
                  {
                      Release();
  
                      lumaTexture = RenderTexture.GetTemporary(width, height, 0, format);
                      lumaTexture.filterMode = FilterMode.Point;
  
                      cb.SetGlobalTexture(Uniforms._MainTex, source);
                      cb.Blit(source, lumaTexture);
  
                      m_Time = Time.time;
                  }
              }
  
              bool m_UseCompression;
              RenderTextureFormat m_RawTextureFormat;
  
              Frame[] m_FrameList;
              int m_LastFrameCount;
  
              public FrameBlendingFilter()
              {
                  m_UseCompression = CheckSupportCompression();
                  m_RawTextureFormat = GetPreferredRenderTextureFormat();
  
gt:                 m_FrameList = new Frame[4];