Hello all,
I’m currently trying to get a Outline shader working with a own ScriptableRenderPass “DepthNormals Prepass”. However the outlines are showing even though they should be obscured by the terrain:

Looking at the custom “DepthNormals Prepass” RenderPass for the Outlines I get this Preview for this Frame:

When looking at Unitys own DepthNormalsPrepass it looks something like this:
which renders this: 
Now I would like to include that also in the Rendering Pass for my Outlines so they stop showing trough the Terrain, the Code for the Rendering Pass looks like this currently:
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class DepthNormals : ScriptableRendererFeature
{
class DepthNormalsPass : ScriptableRenderPass
{
int kDepthBufferBits = 32;
private RenderTargetHandle depthAttachmentHandle { get; set; }
internal RenderTextureDescriptor descriptor { get; private set; }
private Material depthNormalsMaterial = null;
private FilteringSettings m_FilteringSettings;
string m_ProfilerTag = "DepthNormals Prepass";
ShaderTagId m_ShaderTagId = new ShaderTagId("DepthOnly");
public DepthNormalsPass(RenderQueueRange renderQueueRange, LayerMask layerMask, Material material)
{
m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
depthNormalsMaterial = material;
}
public void Setup(RenderTextureDescriptor baseDescriptor, RenderTargetHandle depthAttachmentHandle)
{
this.depthAttachmentHandle = depthAttachmentHandle;
baseDescriptor.colorFormat = RenderTextureFormat.ARGB32;
baseDescriptor.depthBufferBits = kDepthBufferBits;
descriptor = baseDescriptor;
}
// This method is called before executing the render pass.
// It can be used to configure render targets and their clear state. Also to create temporary render target textures.
// When empty this render pass will render to the active camera render target.
// You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
// The render pipeline will ensure target setup and clearing happens in an performance manner.
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
cmd.GetTemporaryRT(depthAttachmentHandle.id, descriptor, FilterMode.Point);
ConfigureTarget(depthAttachmentHandle.Identifier());
ConfigureClear(ClearFlag.All, Color.black);
}
// Here you can implement the rendering logic.
// Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
// https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
// You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
using (new ProfilingSample(cmd, m_ProfilerTag))
{
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
var sortFlags = renderingData.cameraData.defaultOpaqueSortFlags;
var drawSettings = CreateDrawingSettings(m_ShaderTagId, ref renderingData, sortFlags);
drawSettings.perObjectData = PerObjectData.None;
ref CameraData cameraData = ref renderingData.cameraData;
Camera camera = cameraData.camera;
if (cameraData.isStereoEnabled)
context.StartMultiEye(camera);
drawSettings.overrideMaterial = depthNormalsMaterial;
context.DrawRenderers(renderingData.cullResults, ref drawSettings,
ref m_FilteringSettings);
cmd.SetGlobalTexture("_CameraDepthNormalsTexture", depthAttachmentHandle.id);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
/// Cleanup any allocated resources that were created during the execution of this render pass.
public override void FrameCleanup(CommandBuffer cmd)
{
if (depthAttachmentHandle != RenderTargetHandle.CameraTarget)
{
cmd.ReleaseTemporaryRT(depthAttachmentHandle.id);
depthAttachmentHandle = RenderTargetHandle.CameraTarget;
}
}
}
DepthNormalsPass depthNormalsPass;
RenderTargetHandle depthNormalsTexture;
Material depthNormalsMaterial;
public override void Create()
{
depthNormalsMaterial = CoreUtils.CreateEngineMaterial("Hidden/Internal-DepthNormalsTexture");
depthNormalsPass = new DepthNormalsPass(RenderQueueRange.opaque, -1, depthNormalsMaterial);
depthNormalsPass.renderPassEvent = RenderPassEvent.AfterRenderingPrePasses;
depthNormalsTexture.Init("_CameraDepthNormalsTexture");
}
// Here you can inject one or multiple render passes in the renderer.
// This method is called when setting up the renderer once per-camera.
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
depthNormalsPass.Setup(renderingData.cameraData.cameraTargetDescriptor, depthNormalsTexture);
renderer.EnqueuePass(depthNormalsPass);
}
}
The Outline feature looks like this, changing renderingPass.renderPassEvent around either makes the Outlines disappear entirely or makes no change and they still show in front of Terrain:
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class OutlineFeature : ScriptableRendererFeature
{
class OutlinePass : ScriptableRenderPass
{
private RenderTargetIdentifier source { get; set; }
private RenderTargetHandle destination { get; set; }
public Material outlineMaterial = null;
RenderTargetHandle temporaryColorTexture;
public void Setup(RenderTargetIdentifier source, RenderTargetHandle destination)
{
this.source = source;
this.destination = destination;
}
public OutlinePass(Material outlineMaterial)
{
this.outlineMaterial = outlineMaterial;
}
// This method is called before executing the render pass.
// It can be used to configure render targets and their clear state. Also to create temporary render target textures.
// When empty this render pass will render to the active camera render target.
// You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
// The render pipeline will ensure target setup and clearing happens in an performance manner.
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
}
// Here you can implement the rendering logic.
// Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
// https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
// You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get("_OutlinePass");
RenderTextureDescriptor opaqueDescriptor = renderingData.cameraData.cameraTargetDescriptor;
opaqueDescriptor.depthBufferBits = 0;
if (destination == RenderTargetHandle.CameraTarget)
{
cmd.GetTemporaryRT(temporaryColorTexture.id, opaqueDescriptor, FilterMode.Point);
Blit(cmd, source, temporaryColorTexture.Identifier(), outlineMaterial, 0);
Blit(cmd, temporaryColorTexture.Identifier(), source);
}
else Blit(cmd, source, destination.Identifier(), outlineMaterial, 0);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
/// Cleanup any allocated resources that were created during the execution of this render pass.
public override void FrameCleanup(CommandBuffer cmd)
{
if (destination == RenderTargetHandle.CameraTarget)
cmd.ReleaseTemporaryRT(temporaryColorTexture.id);
}
}
[System.Serializable]
public class OutlineSettings
{
public Material outlineMaterial = null;
}
public OutlineSettings settings = new OutlineSettings();
OutlinePass outlinePass;
RenderTargetHandle outlineTexture;
public override void Create()
{
outlinePass = new OutlinePass(settings.outlineMaterial);
outlinePass.renderPassEvent = RenderPassEvent.AfterRenderingTransparents;
outlineTexture.Init("_OutlineTexture");
}
// Here you can inject one or multiple render passes in the renderer.
// This method is called when setting up the renderer once per-camera.
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
if (settings.outlineMaterial == null)
{
Debug.LogWarningFormat("Missing Outline Material");
return;
}
outlinePass.Setup(renderer.cameraColorTarget, RenderTargetHandle.CameraTarget);
renderer.EnqueuePass(outlinePass);
}
}
I couldn’t find any Resources online on how to include the terrain rendering in this custom Pass so any help would be greatly appreciated!
Cheers!