I am doing a very simple test in URP in a simple project. I have a cube, as well as some quads to create a ground surface and a “backdrop” wall.
I have a scriptable render feature that simply draws the same exact scene with an override material on the objects, and blits this to a global texture called “_GeometryUpdateTexture”. The override material is a basic unlit shader with a texture for color.
The cube’s material in the regular pass is a custom shader that outputs “_customPassTex” mapped to screen position in the fragment shader.
So, my expectation was that the cube should appear the same in both passes. However, when I move the camera, there is an annoying lag in the “_GeometryUpdateTexture.”
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
[Serializable]
public class GeometryUpdateSettings
{
public Material _AnisoMaterial;
}
public class GeometryUpdate : ScriptableRendererFeature
{
private GeometryUpdatePass m_ScriptablePass;
public GeometryUpdateSettings Settings = new GeometryUpdateSettings();
class GeometryUpdatePass : ScriptableRenderPass
{
private GeometryUpdateSettings m_Settings;
FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.all, 128);
FilteringSettings filteringSettings2 = new FilteringSettings(RenderQueueRange.all, 256);
private RenderTargetIdentifier cameraColorTargetIdent2;
private readonly List<ShaderTagId> shaderTagIdList = new List<ShaderTagId>();
RTHandle blur;
RTHandle m_CameraDepthTarget;
RTHandle tempTex;
private readonly Material blurMaterial;
private readonly Material blurPass;
public GeometryUpdatePass(GeometryUpdateSettings variables)
{
m_Settings = variables;
shaderTagIdList.Add(new ShaderTagId("UniversalForward"));
shaderTagIdList.Add(new ShaderTagId("UniversalForwardOnly"));
shaderTagIdList.Add(new ShaderTagId("LightweightForward"));
shaderTagIdList.Add(new ShaderTagId("SRPDefaultUnlit"));
}
public void SetTarget(RTHandle cameraColorTargetHandle, RTHandle cameraDepthTargetHandle)
{
blur = cameraColorTargetHandle;
// m_CameraDepthTarget = cameraDepthTargetHandle;
}
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
RenderTextureDescriptor cameraTextureDescriptor = renderingData.cameraData.cameraTargetDescriptor;
RenderTextureDescriptor cameraTextureDescriptor2 = new RenderTextureDescriptor(cameraTextureDescriptor.width, cameraTextureDescriptor.height,
RenderTextureFormat.RGB111110Float);
cameraTextureDescriptor2.depthBufferBits = 0;
RenderingUtils.ReAllocateIfNeeded(ref tempTex, Vector2.one, cameraTextureDescriptor2, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_TestMap");
RenderingUtils.ReAllocateIfNeeded(ref m_CameraDepthTarget, Vector2.one, cameraTextureDescriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_CameraDepthTexture");
blur = renderingData.cameraData.renderer.cameraColorTargetHandle;
ConfigureTarget(tempTex, m_CameraDepthTarget);
ConfigureClear(ClearFlag.Depth, Color.black);
}
public void ReleaseTargets()
{
tempTex?.Release();
m_CameraDepthTarget?.Release();
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get();
using (new ProfilingScope(cmd, new ProfilingSampler(" GeometryUpdate")))
{
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
SortingCriteria sortingCriteria = renderingData.cameraData.defaultOpaqueSortFlags;
Camera camera = renderingData.cameraData.camera;
context.DrawSkybox(camera);
DrawingSettings drawSettings = CreateDrawingSettings(shaderTagIdList, ref renderingData, sortingCriteria);
context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filteringSettings);
context.ExecuteCommandBuffer(cmd);
drawSettings.overrideMaterial = m_Settings._AnisoMaterial;
drawSettings.overrideMaterialPassIndex = 0;
context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filteringSettings2);
cmd.SetGlobalTexture("_GeometryUpdateTexture", tempTex);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
public override void OnCameraCleanup(CommandBuffer cmd)
{
cmd.ReleaseTemporaryRT(Shader.PropertyToID(tempTex.name));
cmd.ReleaseTemporaryRT(Shader.PropertyToID(m_CameraDepthTarget.name));
}
}
/// <inheritdoc/>
public override void Create()
{
m_ScriptablePass = new GeometryUpdatePass(Settings);
// m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingTransparents + 10;
m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(m_ScriptablePass);
}
public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
{
if (renderingData.cameraData.cameraType == CameraType.Game)
{
m_ScriptablePass.ConfigureInput(ScriptableRenderPassInput.Depth | ScriptableRenderPassInput.Color);
m_ScriptablePass.SetTarget(renderer.cameraColorTargetHandle, renderer.cameraDepthTargetHandle);
}
}
protected override void Dispose(bool disposing)
{
m_ScriptablePass.ReleaseTargets();
}
}
I’ll be very surprised if URP is incapable of blitting a custom pass to a texture that can be used in normal pass without lag. Any pointers?