Skip to content

Instantly share code, notes, and snippets.

@kkhomyakov3d
Forked from EricHu33/DrawFullScreenFeature.cs
Created November 25, 2021 14:10
Show Gist options
  • Save kkhomyakov3d/059b88d62086f4d3cd48c16055b071af to your computer and use it in GitHub Desktop.
Save kkhomyakov3d/059b88d62086f4d3cd48c16055b071af to your computer and use it in GitHub Desktop.
An example of how to write custom grab pass renderer feature in Unity URP
namespace UnityEngine.Rendering.Universal
{
public enum BufferType
{
CameraColor,
Custom
}
public class DrawFullScreenFeature : ScriptableRendererFeature
{
[System.Serializable]
public class Settings
{
public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingTransparents;
public BufferType sourceType = BufferType.CameraColor;
public BufferType destinationType = BufferType.CameraColor;
public string sourceTextureId = "_SourceTexture";
public string destinationTextureId = "_DestinationTexture";
public string tempTextureId = "_Temp";
public string grabTexName = "_GrabTexTexture";
}
public Settings settings = new Settings();
DrawFullScreenPass blitPass;
public override void Create()
{
blitPass = new DrawFullScreenPass(name, settings.tempTextureId, settings.grabTexName);
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
blitPass.renderPassEvent = settings.renderPassEvent;
blitPass.settings = settings;
renderer.EnqueuePass(blitPass);
}
}
}
namespace UnityEngine.Rendering.Universal
{
/// <summary>
/// Draws full screen mesh using given material and pass and reading from source target.
/// </summary>
internal class DrawFullScreenPass : ScriptableRenderPass
{
public FilterMode filterMode { get; set; }
public DrawFullScreenFeature.Settings settings;
RenderTargetIdentifier source;
RenderTargetIdentifier destination;
int temporaryRTId;
int grabTexId;
int sourceId;
int destinationId;
bool isSourceAndDestinationSameTarget;
string m_ProfilerTag;
public DrawFullScreenPass(string tag, string tempTextureId, string grabTexName)
{
m_ProfilerTag = tag;
temporaryRTId = Shader.PropertyToID(tempTextureId);
grabTexId = Shader.PropertyToID(grabTexName);
}
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
RenderTextureDescriptor blitTargetDescriptor = renderingData.cameraData.cameraTargetDescriptor;
blitTargetDescriptor.depthBufferBits = 0;
isSourceAndDestinationSameTarget = settings.sourceType == settings.destinationType &&
(settings.sourceType == BufferType.CameraColor || settings.sourceTextureId == settings.destinationTextureId);
var renderer = renderingData.cameraData.renderer;
if (settings.sourceType == BufferType.CameraColor)
{
sourceId = -1;
source = renderer.cameraColorTarget;
}
else
{
sourceId = Shader.PropertyToID(settings.sourceTextureId);
cmd.GetTemporaryRT(sourceId, blitTargetDescriptor, filterMode);
source = new RenderTargetIdentifier(sourceId);
}
if (isSourceAndDestinationSameTarget)
{
destinationId = temporaryRTId;
cmd.GetTemporaryRT(destinationId, blitTargetDescriptor, filterMode);
destination = new RenderTargetIdentifier(destinationId);
}
else if (settings.destinationType == BufferType.CameraColor)
{
destinationId = -1;
destination = renderer.cameraColorTarget;
}
else
{
destinationId = Shader.PropertyToID(settings.destinationTextureId);
cmd.GetTemporaryRT(destinationId, blitTargetDescriptor, filterMode);
destination = new RenderTargetIdentifier(destinationId);
}
}
/// <inheritdoc/>
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
// Can't read and write to same color target, create a temp render target to blit.
if (isSourceAndDestinationSameTarget)
{
Blit(cmd, source, destination);
Blit(cmd, destination, source);
}
else
{
Blit(cmd, source, destination);
}
cmd.SetGlobalTexture(grabTexId, destination);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
/// <inheritdoc/>
public override void FrameCleanup(CommandBuffer cmd)
{
if (destinationId != -1)
cmd.ReleaseTemporaryRT(destinationId);
if (source == destination && sourceId != -1)
cmd.ReleaseTemporaryRT(sourceId);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment