Skip to content

Instantly share code, notes, and snippets.

@wonkee-kim
Last active July 6, 2022 16:56
Show Gist options
  • Save wonkee-kim/1792cd4fced96f98ae4a09ec500a3177 to your computer and use it in GitHub Desktop.
Save wonkee-kim/1792cd4fced96f98ae4a09ec500a3177 to your computer and use it in GitHub Desktop.
Unity URP BlitPass with comments
// https://github.com/Unity-Technologies/UniversalRenderingExamples/blob/master/Assets/Scripts/Runtime/RenderPasses/BlitPass.cs
// https://samdriver.xyz/articles/scriptableRender.htm
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace UnityEngine.Experimental.Rendering.Universal {
/// <summary>
/// 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.
/// https://github.com/Unity-Technologies/UniversalRenderingExamples/blob/master/Assets/Scripts/Runtime/RenderPasses/BlitPass.cs
/// </summary>
///
//The "pass" is what does the actual rendering work while the "feature" is how it interfaces with the rest of the scriptable pipeline.
public class BlitPass :ScriptableRenderPass {
// used to label this pass in Unity's Frame Debug utility
string m_ProfilerTag;
public Material blitMaterial = null;
public int blitShaderPassIndex = 0;
// https://docs.unity3d.com/ScriptReference/Rendering.RenderTargetIdentifier.html
// https://docs.unity3d.com/ScriptReference/Rendering.RenderTargetIdentifier-ctor.html
private RenderTargetIdentifier source { get; set; }
private RenderTargetHandle destination { get; set; }
RenderTargetHandle m_TemporaryColorTexture;
//public FilterMode filterMode { get; set; }
public FilterMode filterMode = FilterMode.Trilinear;
/// <summary>
/// Create the CopyColorPass
/// </summary>
public BlitPass(RenderPassEvent renderPassEvent, Material blitMaterial, int blitShaderPassIndex, string tag) {
this.renderPassEvent = renderPassEvent;
this.blitMaterial = blitMaterial;
this.blitShaderPassIndex = blitShaderPassIndex;
m_ProfilerTag = tag;
m_TemporaryColorTexture.Init("_TemporaryColorTexture");
}
// This isn't part of the ScriptableRenderPass class and is our own addition.
// For this custom pass we need the camera's color target, so that gets passed in.
/// <summary>
/// Configure the pass with the source and destination to execute on.
/// </summary>
/// <param name="source">Source Render Target</param>
/// <param name="destination">Destination Render Target</param>
public void Setup(RenderTargetIdentifier source, RenderTargetHandle destination) {
this.source = source;
this.destination = destination;
}
// called each frame before Execute, use it to set up things the pass will need
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) {
// Can't read and write to same color target, create a temp render target to blit.
if(destination == RenderTargetHandle.CameraTarget) {
// Create a temporary render texture that maches the camera
//cmd.GetTemporaryRT(m_TemporaryColorTexture.id, cameraTextureDescriptor, filterMode);
cmd.GetTemporaryRT(m_TemporaryColorTexture.id, cameraTextureDescriptor);
}
}
// Execute is called for every eligible camera every frame. It's not called at the moment that
// rendering is actually taking place, so don't directly execute rendering commands here.
// Instead use the methods on ScriptableRenderContext to set up instructions.
// RenderingData provides a bunch of (not very well documented) information about the scene
// and what's being rendered.
/// <inheritdoc/>
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) {
// fetch a command buffer to use
CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
cmd.Clear();
RenderTextureDescriptor opaqueDesc = renderingData.cameraData.cameraTargetDescriptor;
opaqueDesc.depthBufferBits = 0;
// Can't read and write to same color target, create a temp render target to blit.
if(destination == RenderTargetHandle.CameraTarget) {
// Create a temporary render texture that maches the camera
//cmd.GetTemporaryRT(m_TemporaryColorTexture.id, opaqueDesc, filterMode);
// the actual content of our custom render pass
// we apply our material while blitting to a temporary texture
Blit(cmd, source, m_TemporaryColorTexture.Identifier(), blitMaterial, blitShaderPassIndex);
// ..then blit it back again
Blit(cmd, m_TemporaryColorTexture.Identifier(), source);
//cmd.Blit(source, m_TemporaryColorTexture.Identifier(), blitMaterial, blitShaderPassIndex);
} else {
Blit(cmd, source, destination.Identifier(), blitMaterial, blitShaderPassIndex);
}
// don't forget to tell ScriptableRenderContext to actually execute the commands
context.ExecuteCommandBuffer(cmd);
// tidy up after ourselves
CommandBufferPool.Release(cmd);
}
// called after Execute, use it to clean up anything allocated in Configure and Execute
/// <inheritdoc/>
public override void FrameCleanup(CommandBuffer cmd) {
if(destination == RenderTargetHandle.CameraTarget)
cmd.ReleaseTemporaryRT(m_TemporaryColorTexture.id);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment