Skip to content

Instantly share code, notes, and snippets.

@EricHu33
Last active April 16, 2022 21:48
Show Gist options
  • Save EricHu33/d3dfb936b5001fac79a407c7aca0885e to your computer and use it in GitHub Desktop.
Save EricHu33/d3dfb936b5001fac79a407c7aca0885e 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);
}
}
}
@EricHu33
Copy link
Author

image

  1. choose which render pass event to grab the full screen image.
  2. name the grabbed texture (Grab Tex Name).
  3. To use the texture in shader just called

material.SetTexture("_YourTexNameInShader", Shader.GetGlobalTexture("_GrabTexTexture"));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment