diff options
Diffstat (limited to 'UnityEngine.PostProcessing/MotionBlurComponent.cs')
-rw-r--r-- | UnityEngine.PostProcessing/MotionBlurComponent.cs | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/UnityEngine.PostProcessing/MotionBlurComponent.cs b/UnityEngine.PostProcessing/MotionBlurComponent.cs new file mode 100644 index 0000000..59199e1 --- /dev/null +++ b/UnityEngine.PostProcessing/MotionBlurComponent.cs @@ -0,0 +1,421 @@ +using UnityEngine.Rendering; + +namespace UnityEngine.PostProcessing; + +public sealed class MotionBlurComponent : PostProcessingComponentCommandBuffer<MotionBlurModel> +{ + private static class Uniforms + { + internal static readonly int _VelocityScale = Shader.PropertyToID("_VelocityScale"); + + internal static readonly int _MaxBlurRadius = Shader.PropertyToID("_MaxBlurRadius"); + + internal static readonly int _RcpMaxBlurRadius = Shader.PropertyToID("_RcpMaxBlurRadius"); + + internal static readonly int _VelocityTex = Shader.PropertyToID("_VelocityTex"); + + internal static readonly int _MainTex = Shader.PropertyToID("_MainTex"); + + internal static readonly int _Tile2RT = Shader.PropertyToID("_Tile2RT"); + + internal static readonly int _Tile4RT = Shader.PropertyToID("_Tile4RT"); + + 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"); + } + + private enum Pass + { + VelocitySetup, + TileMax1, + TileMax2, + TileMaxV, + NeighborMax, + Reconstruction, + FrameCompression, + FrameBlendingChroma, + FrameBlendingRaw + } + + public class ReconstructionFilter + { + private RenderTextureFormat m_VectorRTFormat = RenderTextureFormat.RGHalf; + + private RenderTextureFormat m_PackedRTFormat = RenderTextureFormat.ARGB2101010; + + public ReconstructionFilter() + { + CheckTextureFormatSupport(); + } + + private void CheckTextureFormatSupport() + { + if (!SystemInfo.SupportsRenderTextureFormat(m_PackedRTFormat)) + { + m_PackedRTFormat = RenderTextureFormat.ARGB32; + } + } + + public bool IsSupported() + { + return SystemInfo.supportsMotionVectors; + } + + public void ProcessImage(PostProcessingContext context, CommandBuffer cb, ref MotionBlurModel.Settings settings, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material) + { + int num = (int)(5f * (float)context.height / 100f); + int num2 = ((num - 1) / 8 + 1) * 8; + float value = settings.shutterAngle / 360f; + cb.SetGlobalFloat(Uniforms._VelocityScale, value); + cb.SetGlobalFloat(Uniforms._MaxBlurRadius, num); + cb.SetGlobalFloat(Uniforms._RcpMaxBlurRadius, 1f / (float)num); + int velocityTex = Uniforms._VelocityTex; + cb.GetTemporaryRT(velocityTex, context.width, context.height, 0, FilterMode.Point, m_PackedRTFormat, RenderTextureReadWrite.Linear); + cb.Blit(null, velocityTex, material, 0); + int tile2RT = Uniforms._Tile2RT; + cb.GetTemporaryRT(tile2RT, context.width / 2, context.height / 2, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear); + cb.SetGlobalTexture(Uniforms._MainTex, velocityTex); + cb.Blit(velocityTex, tile2RT, material, 1); + int tile4RT = Uniforms._Tile4RT; + cb.GetTemporaryRT(tile4RT, context.width / 4, context.height / 4, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear); + cb.SetGlobalTexture(Uniforms._MainTex, tile2RT); + cb.Blit(tile2RT, tile4RT, material, 2); + cb.ReleaseTemporaryRT(tile2RT); + int tile8RT = Uniforms._Tile8RT; + cb.GetTemporaryRT(tile8RT, context.width / 8, context.height / 8, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear); + cb.SetGlobalTexture(Uniforms._MainTex, tile4RT); + cb.Blit(tile4RT, tile8RT, material, 2); + cb.ReleaseTemporaryRT(tile4RT); + Vector2 vector = Vector2.one * ((float)num2 / 8f - 1f) * -0.5f; + cb.SetGlobalVector(Uniforms._TileMaxOffs, vector); + cb.SetGlobalFloat(Uniforms._TileMaxLoop, (int)((float)num2 / 8f)); + int tileVRT = Uniforms._TileVRT; + cb.GetTemporaryRT(tileVRT, context.width / num2, context.height / num2, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear); + cb.SetGlobalTexture(Uniforms._MainTex, tile8RT); + cb.Blit(tile8RT, tileVRT, material, 3); + cb.ReleaseTemporaryRT(tile8RT); + int neighborMaxTex = Uniforms._NeighborMaxTex; + int width = context.width / num2; + int height = context.height / num2; + cb.GetTemporaryRT(neighborMaxTex, width, height, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear); + cb.SetGlobalTexture(Uniforms._MainTex, tileVRT); + cb.Blit(tileVRT, neighborMaxTex, material, 4); + cb.ReleaseTemporaryRT(tileVRT); + cb.SetGlobalFloat(Uniforms._LoopCount, Mathf.Clamp(settings.sampleCount / 2, 1, 64)); + cb.SetGlobalTexture(Uniforms._MainTex, source); + cb.Blit(source, destination, material, 5); + cb.ReleaseTemporaryRT(velocityTex); + cb.ReleaseTemporaryRT(neighborMaxTex); + } + } + + public class FrameBlendingFilter + { + private struct Frame + { + public RenderTexture lumaTexture; + + public RenderTexture chromaTexture; + + private float m_Time; + + private RenderTargetIdentifier[] m_MRT; + + public float CalculateWeight(float strength, float currentTime) + { + if (Mathf.Approximately(m_Time, 0f)) + { + return 0f; + } + float num = Mathf.Lerp(80f, 16f, strength); + return Mathf.Exp((m_Time - currentTime) * num); + } + + 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]; + } + ref RenderTargetIdentifier reference = ref m_MRT[0]; + reference = lumaTexture; + ref RenderTargetIdentifier reference2 = ref m_MRT[1]; + reference2 = chromaTexture; + cb.SetGlobalTexture(Uniforms._MainTex, source); + cb.SetRenderTarget(m_MRT, lumaTexture); + cb.DrawMesh(GraphicsUtils.quad, Matrix4x4.identity, material, 0, 6); + 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; + } + } + + private bool m_UseCompression; + + private RenderTextureFormat m_RawTextureFormat; + + private Frame[] m_FrameList; + + private int m_LastFrameCount; + + public FrameBlendingFilter() + { + m_UseCompression = CheckSupportCompression(); + m_RawTextureFormat = GetPreferredRenderTextureFormat(); + m_FrameList = new Frame[4]; + } + + public void Dispose() + { + Frame[] frameList = m_FrameList; + foreach (Frame frame in frameList) + { + frame.Release(); + } + } + + public void PushFrame(CommandBuffer cb, RenderTargetIdentifier source, int width, int height, Material material) + { + int frameCount = Time.frameCount; + if (frameCount != m_LastFrameCount) + { + int num = frameCount % m_FrameList.Length; + if (m_UseCompression) + { + m_FrameList[num].MakeRecord(cb, source, width, height, material); + } + else + { + m_FrameList[num].MakeRecordRaw(cb, source, width, height, m_RawTextureFormat); + } + m_LastFrameCount = frameCount; + } + } + + public void BlendFrames(CommandBuffer cb, float strength, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material) + { + float time = Time.time; + Frame frameRelative = GetFrameRelative(-1); + Frame frameRelative2 = GetFrameRelative(-2); + Frame frameRelative3 = GetFrameRelative(-3); + Frame frameRelative4 = GetFrameRelative(-4); + cb.SetGlobalTexture(Uniforms._History1LumaTex, frameRelative.lumaTexture); + cb.SetGlobalTexture(Uniforms._History2LumaTex, frameRelative2.lumaTexture); + cb.SetGlobalTexture(Uniforms._History3LumaTex, frameRelative3.lumaTexture); + cb.SetGlobalTexture(Uniforms._History4LumaTex, frameRelative4.lumaTexture); + cb.SetGlobalTexture(Uniforms._History1ChromaTex, frameRelative.chromaTexture); + cb.SetGlobalTexture(Uniforms._History2ChromaTex, frameRelative2.chromaTexture); + cb.SetGlobalTexture(Uniforms._History3ChromaTex, frameRelative3.chromaTexture); + cb.SetGlobalTexture(Uniforms._History4ChromaTex, frameRelative4.chromaTexture); + cb.SetGlobalFloat(Uniforms._History1Weight, frameRelative.CalculateWeight(strength, time)); + cb.SetGlobalFloat(Uniforms._History2Weight, frameRelative2.CalculateWeight(strength, time)); + cb.SetGlobalFloat(Uniforms._History3Weight, frameRelative3.CalculateWeight(strength, time)); + cb.SetGlobalFloat(Uniforms._History4Weight, frameRelative4.CalculateWeight(strength, time)); + cb.SetGlobalTexture(Uniforms._MainTex, source); + cb.Blit(source, destination, material, (!m_UseCompression) ? 8 : 7); + } + + private static bool CheckSupportCompression() + { + return SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.R8) && SystemInfo.supportedRenderTargetCount > 1; + } + + private static RenderTextureFormat GetPreferredRenderTextureFormat() + { + RenderTextureFormat[] array = new RenderTextureFormat[3] + { + RenderTextureFormat.RGB565, + RenderTextureFormat.ARGB1555, + RenderTextureFormat.ARGB4444 + }; + RenderTextureFormat[] array2 = array; + foreach (RenderTextureFormat renderTextureFormat in array2) + { + if (SystemInfo.SupportsRenderTextureFormat(renderTextureFormat)) + { + return renderTextureFormat; + } + } + return RenderTextureFormat.Default; + } + + private Frame GetFrameRelative(int offset) + { + int num = (Time.frameCount + m_FrameList.Length + offset) % m_FrameList.Length; + return m_FrameList[num]; + } + } + + private ReconstructionFilter m_ReconstructionFilter; + + private FrameBlendingFilter m_FrameBlendingFilter; + + private bool m_FirstFrame = true; + + public ReconstructionFilter reconstructionFilter + { + get + { + if (m_ReconstructionFilter == null) + { + m_ReconstructionFilter = new ReconstructionFilter(); + } + return m_ReconstructionFilter; + } + } + + public FrameBlendingFilter frameBlendingFilter + { + get + { + if (m_FrameBlendingFilter == null) + { + m_FrameBlendingFilter = new FrameBlendingFilter(); + } + return m_FrameBlendingFilter; + } + } + + public override bool active + { + get + { + MotionBlurModel.Settings settings = base.model.settings; + return base.model.enabled && ((settings.shutterAngle > 0f && reconstructionFilter.IsSupported()) || settings.frameBlending > 0f) && SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLES2 && !context.interrupted; + } + } + + public override string GetName() + { + return "Motion Blur"; + } + + public void ResetHistory() + { + if (m_FrameBlendingFilter != null) + { + m_FrameBlendingFilter.Dispose(); + } + m_FrameBlendingFilter = null; + } + + public override DepthTextureMode GetCameraFlags() + { + return DepthTextureMode.Depth | DepthTextureMode.MotionVectors; + } + + public override CameraEvent GetCameraEvent() + { + return CameraEvent.BeforeImageEffects; + } + + public override void OnEnable() + { + m_FirstFrame = true; + } + + public override void PopulateCommandBuffer(CommandBuffer cb) + { + if (m_FirstFrame) + { + m_FirstFrame = false; + return; + } + Material material = context.materialFactory.Get("Hidden/Post FX/Motion Blur"); + Material mat = context.materialFactory.Get("Hidden/Post FX/Blit"); + MotionBlurModel.Settings settings = base.model.settings; + RenderTextureFormat format = ((!context.isHdr) ? RenderTextureFormat.Default : RenderTextureFormat.DefaultHDR); + int tempRT = Uniforms._TempRT; + cb.GetTemporaryRT(tempRT, context.width, context.height, 0, FilterMode.Point, format); + if (settings.shutterAngle > 0f && settings.frameBlending > 0f) + { + reconstructionFilter.ProcessImage(context, cb, ref settings, BuiltinRenderTextureType.CameraTarget, tempRT, material); + frameBlendingFilter.BlendFrames(cb, settings.frameBlending, tempRT, BuiltinRenderTextureType.CameraTarget, material); + frameBlendingFilter.PushFrame(cb, tempRT, context.width, context.height, material); + } + else if (settings.shutterAngle > 0f) + { + cb.SetGlobalTexture(Uniforms._MainTex, BuiltinRenderTextureType.CameraTarget); + cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, mat, 0); + reconstructionFilter.ProcessImage(context, cb, ref settings, tempRT, BuiltinRenderTextureType.CameraTarget, material); + } + else if (settings.frameBlending > 0f) + { + cb.SetGlobalTexture(Uniforms._MainTex, BuiltinRenderTextureType.CameraTarget); + cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, mat, 0); + frameBlendingFilter.BlendFrames(cb, settings.frameBlending, tempRT, BuiltinRenderTextureType.CameraTarget, material); + frameBlendingFilter.PushFrame(cb, tempRT, context.width, context.height, material); + } + cb.ReleaseTemporaryRT(tempRT); + } + + public override void OnDisable() + { + if (m_FrameBlendingFilter != null) + { + m_FrameBlendingFilter.Dispose(); + } + } +} |