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.
121 lines
4.9 KiB
121 lines
4.9 KiB
using System; |
|
using UnityEngine; |
|
using UnityEngine.Rendering; |
|
using UnityEngine.Rendering.Universal; |
|
|
|
//This renderer feature will replicate a "don't clear" behaviour by injecting two passes into the pipeline: |
|
//One pass that copies color at the end of a frame |
|
//Another pass that draws the content of the copied texture at the beginning of a new frame |
|
public class KeepFrameFeature : ScriptableRendererFeature |
|
{ |
|
//This pass is responsible for copying color to a specified destination |
|
class CopyFramePass : ScriptableRenderPass |
|
{ |
|
private RenderTargetIdentifier source { get; set; } |
|
private RenderTargetHandle destination { get; set; } |
|
|
|
public void Setup(RenderTargetIdentifier source, RenderTargetHandle destination) |
|
{ |
|
this.source = source; |
|
this.destination = destination; |
|
} |
|
|
|
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) |
|
{ |
|
if (renderingData.cameraData.camera.cameraType != CameraType.Game) |
|
return; |
|
|
|
CommandBuffer cmd = CommandBufferPool.Get("CopyFramePass"); |
|
RenderTargetIdentifier opaqueColorRT = destination.Identifier(); |
|
Blit(cmd, source, opaqueColorRT); |
|
context.ExecuteCommandBuffer(cmd); |
|
CommandBufferPool.Release(cmd); |
|
} |
|
|
|
public override void OnCameraCleanup(CommandBuffer cmd) |
|
{ |
|
cmd.ReleaseTemporaryRT(destination.id); |
|
|
|
if (destination != RenderTargetHandle.CameraTarget) |
|
{ |
|
cmd.ReleaseTemporaryRT(destination.id); |
|
destination = RenderTargetHandle.CameraTarget; |
|
} |
|
} |
|
} |
|
|
|
//This pass is responsible for drawing the old color to a full screen quad |
|
class DrawOldFramePass : ScriptableRenderPass |
|
{ |
|
private Material m_DrawOldFrameMaterial; |
|
private RenderTargetHandle m_handle; |
|
private string m_textureName; |
|
|
|
public void Setup(Material drawOldFrameMaterial, RenderTargetHandle handle, string textureName) |
|
{ |
|
m_DrawOldFrameMaterial = drawOldFrameMaterial; |
|
m_handle = handle; |
|
m_textureName = textureName; |
|
} |
|
|
|
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescripor) |
|
{ |
|
RenderTextureDescriptor descriptor = cameraTextureDescripor; |
|
descriptor.msaaSamples = 1; |
|
descriptor.depthBufferBits = 0; |
|
cmd.GetTemporaryRT(m_handle.id, descriptor, FilterMode.Bilinear); |
|
} |
|
|
|
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) |
|
{ |
|
if (m_DrawOldFrameMaterial != null) |
|
{ |
|
CommandBuffer cmd = CommandBufferPool.Get("DrawOldFramePass"); |
|
cmd.SetGlobalTexture(m_textureName, m_handle.id); |
|
cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity); |
|
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, m_DrawOldFrameMaterial, 0, 0); |
|
cmd.SetViewProjectionMatrices(renderingData.cameraData.camera.worldToCameraMatrix, renderingData.cameraData.camera.projectionMatrix); |
|
context.ExecuteCommandBuffer(cmd); |
|
CommandBufferPool.Release(cmd); |
|
} |
|
} |
|
} |
|
|
|
[Serializable] |
|
public class Settings |
|
{ |
|
[Tooltip("The material that is used when the old frame is redrawn at the start of the new frame (before opaques).")] |
|
public Material displayMaterial; |
|
[Tooltip("The name of the texture used for referencing the copied frame. (Defaults to _FrameCopyTex if empty)")] |
|
public string textureName; |
|
} |
|
|
|
private CopyFramePass m_CopyFrame; |
|
private DrawOldFramePass m_DrawOldFame; |
|
|
|
private RenderTargetHandle m_OldFrameHandle; |
|
|
|
public Settings settings = new Settings(); |
|
|
|
//In this function the passes are created and their point of injection is set |
|
public override void Create() |
|
{ |
|
m_CopyFrame = new CopyFramePass(); |
|
m_CopyFrame.renderPassEvent = RenderPassEvent.AfterRenderingTransparents; //Frame color is copied late in the frame |
|
|
|
m_DrawOldFame = new DrawOldFramePass(); |
|
m_DrawOldFame.renderPassEvent = RenderPassEvent.BeforeRenderingOpaques; //Old frame is drawn early in the frame |
|
} |
|
|
|
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) |
|
{ |
|
m_OldFrameHandle.Init("_OldFrameRenderTarget"); |
|
m_DrawOldFame.ConfigureClear(ClearFlag.None, Color.red); |
|
|
|
m_CopyFrame.Setup(renderer.cameraColorTarget, m_OldFrameHandle); |
|
renderer.EnqueuePass(m_CopyFrame); |
|
|
|
m_DrawOldFame.Setup(settings.displayMaterial, m_OldFrameHandle, String.IsNullOrEmpty(settings.textureName) ? "_FrameCopyTex" : settings.textureName); |
|
renderer.EnqueuePass(m_DrawOldFame); |
|
} |
|
}
|
|
|