I adapted render blit feature example from this package GitHub - Unity-Technologies/UniversalRenderingExamples: This project contains a collection of Custom Renderer examples. This will be updated as we refine the feature and add more options.. So now it’s 2 component more universal stuff.
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using System.Collections.Generic;
public enum BufferType { CameraColor, Custom }
public class ScreenFeature : ScriptableRendererFeature
{
class RenderPass : ScriptableRenderPass
{
public FilterMode filterMode { get; set; }
private Settings settings;
private RenderTargetIdentifier source;
private RenderTargetIdentifier destination;
private int tempTextureId = Shader.PropertyToID("_TempTexture");
private int sourceId;
private int destinationId;
private bool isSameTarget;
private string profilingName;
public void SetStencilState(int reference, CompareFunction compareFunction, StencilOp passOp, StencilOp failOp, StencilOp zFailOp)
{
StencilState stencilState = StencilState.defaultValue;
stencilState.enabled = true;
stencilState.SetCompareFunction(compareFunction);
stencilState.SetPassOperation(passOp);
stencilState.SetFailOperation(failOp);
stencilState.SetZFailOperation(zFailOp);
renderStateBlock.mask |= RenderStateMask.Stencil;
renderStateBlock.stencilReference = reference;
renderStateBlock.stencilState = stencilState;
}
RenderStateBlock renderStateBlock;
public RenderPass(string profilingName, Settings settings)
{
this.profilingName = profilingName;
renderPassEvent = settings.renderPassEvent;
this.settings = settings;
renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
}
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
RenderTextureDescriptor blitTargetDescriptor = renderingData.cameraData.cameraTargetDescriptor;
blitTargetDescriptor.depthBufferBits = 0;
isSameTarget = 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 (isSameTarget)
{
destinationId = tempTextureId;
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);
}
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get(profilingName);
// Can't read and write to same color target, create a temp render target to blit.
if (settings.blitMaterial == null)
{
Blit(cmd, source, destination);
}
else if (isSameTarget)
{
Blit(cmd, source, destination, settings.blitMaterial, settings.blitMaterialPassIndex);
Blit(cmd, destination, source);
}
else
{
Blit(cmd, source, destination, settings.blitMaterial, settings.blitMaterialPassIndex);
}
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
CommandBufferPool.Release(cmd);
}
public override void FrameCleanup(CommandBuffer cmd)
{
if (destinationId != -1)
cmd.ReleaseTemporaryRT(destinationId);
if (source == destination && sourceId != -1)
cmd.ReleaseTemporaryRT(sourceId);
}
}
[System.Serializable]
public class Settings
{
public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
public Material blitMaterial = null;
public int blitMaterialPassIndex = -1;
public BufferType sourceType = BufferType.CameraColor;
public BufferType destinationType = BufferType.CameraColor;
public string sourceTextureId = "_SourceTexture";
public string destinationTextureId = "_DestinationTexture";
public StencilStateData stencilSettings = new StencilStateData();
}
public Settings settings = new Settings();
RenderPass renderPass;
public override void Create()
{
renderPass = new RenderPass(name, settings);
if (settings.stencilSettings.overrideStencilState)
{
renderPass.SetStencilState(settings.stencilSettings.stencilReference,
settings.stencilSettings.stencilCompareFunction, settings.stencilSettings.passOperation,
settings.stencilSettings.failOperation, settings.stencilSettings.zFailOperation);
}
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(renderPass);
}
}
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using System.Collections.Generic;
public class LayerFeature : ScriptableRendererFeature
{
class RenderPass : ScriptableRenderPass
{
private string profilingName;
private RenderTargetIdentifier destination;
private List<ShaderTagId> shaderTagIdList = new List<ShaderTagId>();
private FilteringSettings filter;
private Settings settings;
private int destinationId;
public void SetStencilState(int reference, CompareFunction compareFunction, StencilOp passOp, StencilOp failOp, StencilOp zFailOp)
{
StencilState stencilState = StencilState.defaultValue;
stencilState.enabled = true;
stencilState.SetCompareFunction(compareFunction);
stencilState.SetPassOperation(passOp);
stencilState.SetFailOperation(failOp);
stencilState.SetZFailOperation(zFailOp);
renderStateBlock.mask |= RenderStateMask.Stencil;
renderStateBlock.stencilReference = reference;
renderStateBlock.stencilState = stencilState;
}
RenderStateBlock renderStateBlock;
public RenderPass(string profilingName, Settings settings) : base()
{
this.profilingName = profilingName;
renderPassEvent = settings.renderEvent;
this.settings = settings;
shaderTagIdList.Add(new ShaderTagId("SRPDefaultUnlit"));
shaderTagIdList.Add(new ShaderTagId("UniversalForward"));
shaderTagIdList.Add(new ShaderTagId("UniversalForwardOnly"));
filter = new FilteringSettings(RenderQueueRange.transparent, settings.layer);
renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
}
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
RenderTextureDescriptor cameraTextureDescriptor = renderingData.cameraData.cameraTargetDescriptor;
cameraTextureDescriptor.depthBufferBits = 0;
ScriptableRenderer renderer = renderingData.cameraData.renderer;
destinationId = Shader.PropertyToID(settings.destinationTextureId);
cmd.GetTemporaryRT(destinationId, cameraTextureDescriptor, settings.filter);
destination = new RenderTargetIdentifier(destinationId);
ConfigureTarget(destination);
ConfigureClear(ClearFlag.Color, Color.clear);
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
DrawingSettings drawingSettings = CreateDrawingSettings(shaderTagIdList, ref renderingData, SortingCriteria.CommonTransparent);
drawingSettings.overrideMaterial = settings.overrideMaterial;
CommandBuffer cmd = CommandBufferPool.Get(profilingName);
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filter, ref renderStateBlock);
CommandBufferPool.Release(cmd);
}
}
[System.Serializable]
public class Settings
{
public RenderPassEvent renderEvent = RenderPassEvent.AfterRenderingTransparents;
public LayerMask layer;
public FilterMode filter;
public string destinationTextureId = "_DestinationTexture";
public Material overrideMaterial;
public StencilStateData stencilSettings = new StencilStateData();
}
[SerializeField]
private Settings settings = new Settings();
private RenderPass renderPass;
public override void Create()
{
renderPass = new RenderPass(name, settings);
if (settings.stencilSettings.overrideStencilState)
{
renderPass.SetStencilState(settings.stencilSettings.stencilReference,
settings.stencilSettings.stencilCompareFunction, settings.stencilSettings.passOperation,
settings.stencilSettings.failOperation, settings.stencilSettings.zFailOperation);
}
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(renderPass);
}
}
Here’s the example of how to setup the same as in previous comment.
