using System; namespace UnityEngine.Rendering.Universal.Internal { /// /// Copy the given color buffer to the given destination color buffer. /// /// You can use this pass to copy a color buffer to the destination, /// so you can use it later in rendering. For example, you can copy /// the opaque texture to use it for distortion effects. /// public class CopyColorPass : ScriptableRenderPass { int m_SampleOffsetShaderHandle; Material m_SamplingMaterial; Downsampling m_DownsamplingMethod; Material m_CopyColorMaterial; private RenderTargetIdentifier source { get; set; } private RenderTargetHandle destination { get; set; } /// /// Create the CopyColorPass /// public CopyColorPass(RenderPassEvent evt, Material samplingMaterial, Material copyColorMaterial = null) { base.profilingSampler = new ProfilingSampler(nameof(CopyColorPass)); m_SamplingMaterial = samplingMaterial; m_CopyColorMaterial = copyColorMaterial; m_SampleOffsetShaderHandle = Shader.PropertyToID("_SampleOffset"); renderPassEvent = evt; m_DownsamplingMethod = Downsampling.None; base.useNativeRenderPass = false; } /// /// Configure the pass with the source and destination to execute on. /// /// Source Render Target /// Destination Render Target public void Setup(RenderTargetIdentifier source, RenderTargetHandle destination, Downsampling downsampling) { this.source = source; this.destination = destination; m_DownsamplingMethod = downsampling; } public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor; descriptor.msaaSamples = 1; descriptor.depthBufferBits = 0; if (m_DownsamplingMethod == Downsampling._2xBilinear) { descriptor.width /= 2; descriptor.height /= 2; } else if (m_DownsamplingMethod == Downsampling._4xBox || m_DownsamplingMethod == Downsampling._4xBilinear) { descriptor.width /= 4; descriptor.height /= 4; } cmd.GetTemporaryRT(destination.id, descriptor, m_DownsamplingMethod == Downsampling.None ? FilterMode.Point : FilterMode.Bilinear); } /// public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { if (m_SamplingMaterial == null) { Debug.LogErrorFormat("Missing {0}. {1} render pass will not execute. Check for missing reference in the renderer resources.", m_SamplingMaterial, GetType().Name); return; } CommandBuffer cmd = CommandBufferPool.Get(); //It is possible that the given color target is now the frontbuffer if (source == renderingData.cameraData.renderer.GetCameraColorFrontBuffer(cmd)) { source = renderingData.cameraData.renderer.cameraColorTarget; } using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.CopyColor))) { RenderTargetIdentifier opaqueColorRT = destination.Identifier(); ScriptableRenderer.SetRenderTarget(cmd, opaqueColorRT, BuiltinRenderTextureType.CameraTarget, clearFlag, clearColor); bool useDrawProceduleBlit = renderingData.cameraData.xr.enabled; switch (m_DownsamplingMethod) { case Downsampling.None: RenderingUtils.Blit(cmd, source, opaqueColorRT, m_CopyColorMaterial, 0, useDrawProceduleBlit); break; case Downsampling._2xBilinear: RenderingUtils.Blit(cmd, source, opaqueColorRT, m_CopyColorMaterial, 0, useDrawProceduleBlit); break; case Downsampling._4xBox: m_SamplingMaterial.SetFloat(m_SampleOffsetShaderHandle, 2); RenderingUtils.Blit(cmd, source, opaqueColorRT, m_SamplingMaterial, 0, useDrawProceduleBlit); break; case Downsampling._4xBilinear: RenderingUtils.Blit(cmd, source, opaqueColorRT, m_CopyColorMaterial, 0, useDrawProceduleBlit); break; } } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } /// public override void OnCameraCleanup(CommandBuffer cmd) { if (cmd == null) throw new ArgumentNullException("cmd"); if (destination != RenderTargetHandle.CameraTarget) { cmd.ReleaseTemporaryRT(destination.id); destination = RenderTargetHandle.CameraTarget; } } } }