Hi @antoinel_unity , sorry for the necro bump on this thread. I’ve been trying to achieve the same results as the one above in Unity 2021.3, where the RendererList and DrawRendererList have gone through some refactors, so we can use Rendering Layers to filter out objects when applying a custom pass effect.
I’m attaching below a sample script which has 3 different tests:
1- CoreUtils.DrawRendererList with a UnityEngine.Rendering.RendererUtils RendererList.
- In 2022.2 and above I believe this method works, since Rendering Layers are now exposed into RendererListDesc and you also have RendererListParams as another option. Unfortunately, 2021.3 does not have this functionality yet, so we can only filter out elements by regular Layers.
2- ScriptableRenderContext.DrawRenderers
- As I believe you’ve mentioned in this thread (and this other thread here ), this seems to be the ideal approach where you have more control over how you’re drawing and filtering objects. Unfortunately, the test below does not render anything, and I couldn’t find a sample online that could get some insights on what I’m missing.
3- CoreUtils.DrawRendererList with a deprecated UnityEngine.Experimental.Rendering RendererList.
- This method is the only one I’ve managed to get semi-working, and is based on the sample above by punk. The deprecated RendererList contains a FilteringSettings field which you can assign rendering layers and seems to be working fine in the Scene View. Unfortunately, the effect does not show in the Game View.
Is there anything in the second or third approach that we’re doing wrong and we could fix to make the effect work in game? Any insights on this subject would help a ton :).
using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering.RendererUtils; // uncomment this if you're using Test 1 or 2
//using UnityEngine.Experimental.Rendering; // uncomment this if you're using Test 3
public class RenderingLayerExampleCustomPass : CustomPass
{
// A duplicate of the rendering layer mask enum.
// I couldn't find a way to access it, so I created a copy. Sorry.
[Flags]
public enum RenderingLayerMaskCopy
{
None = 0,
Everything = -1,
LightLayerDefault = 1 << 0,
LightLayer1 = 1 << 1,
LightLayer2 = 1 << 2,
LightLayer3 = 1 << 3,
LightLayer4 = 1 << 4,
LightLayer5 = 1 << 5,
LightLayer6 = 1 << 6,
LightLayer7 = 1 << 7,
DecalLayerDefault = 1 << 8,
DecalLayer1 = 1 << 9,
DecalLayer2 = 1 << 10,
DecalLayer3 = 1 << 11,
DecalLayer4 = 1 << 12,
DecalLayer5 = 1 << 13,
DecalLayer6 = 1 << 14,
DecalLayer7 = 1 << 15,
RenderingLayer16 = 1 << 16,
RenderingLayer17 = 1 << 17,
RenderingLayer18 = 1 << 18,
RenderingLayer19 = 1 << 19,
RenderingLayer20 = 1 << 20,
RenderingLayer21 = 1 << 21,
RenderingLayer22 = 1 << 22,
RenderingLayer23 = 1 << 23,
RenderingLayer24 = 1 << 24,
RenderingLayer25 = 1 << 25,
RenderingLayer26 = 1 << 26,
RenderingLayer27 = 1 << 27,
RenderingLayer28 = 1 << 28,
RenderingLayer29 = 1 << 29,
RenderingLayer30 = 1 << 30,
RenderingLayer31 = 1 << 31,
}
public bool DrawInSceneView = true;
public LayerMask LayerMaskFilter;
public RenderingLayerMaskCopy RenderingLayerMaskFilter;
[SerializeField]
private Material _replacementMaterial;
private ShaderTagId[] _shaderTags;
private RendererList _rendererList;
protected override bool executeInSceneView
{
get { return DrawInSceneView; }
}
protected override void Setup (ScriptableRenderContext renderContext, CommandBuffer cmd)
{
// Warning: You can use all tags in Test 1 and 3, but Test 2 only allows 1 ShaderTag per DrawRenderers command.
_shaderTags = new ShaderTagId[5]
{
new ShaderTagId("Forward"),
new ShaderTagId("ForwardOnly"), // Unlit Shaders
new ShaderTagId("GBuffer"), // Lit Shaders
new ShaderTagId("SRPDefaultUnlit"),
new ShaderTagId("FirstPass")
};
}
protected override void Execute (CustomPassContext ctx)
{
// TEST 1: Regular DrawRendererList from Core Utils.
// This is successful in creating a custom pass, but there's no place in the current pipeline that allows you to set a Rendering Layer mask in Unity 2021. this is fixed in Unity 2022 though.
//
// ----------------------------------------------------------------------------------------------------
//
// var result = new RendererListDesc(_shaderTags, ctx.cullingResults, ctx.hdCamera.camera)
// {
// rendererConfiguration = PerObjectData.None,
// sortingCriteria = SortingCriteria.BackToFront,
// overrideMaterial = _replacementMaterial,
// overrideMaterialPassIndex = 0,
// renderQueueRange = RenderQueueRange.all,
// excludeObjectMotionVectors = false,
// layerMask = LayerMaskFilter,
// stateBlock = new RenderStateBlock(RenderStateMask.Depth){ depthState = new DepthState(true, CompareFunction.LessEqual)},
// };
//
// _rendererList = ctx.renderContext.CreateRendererList(result);
// CoreUtils.DrawRendererList(ctx.renderContext,ctx.cmd, _rendererList);
// TEST 2: Lower level call using ScriptableRenderContext.DrawRenderers.
// This is actually the recommended suggestion by a Unity Engineer in these threads:
// https://discussions.unity.com/t/761329
// https://discussions.unity.com/t/783910
//
// This requires you to manually setup the drawing settings, filtering settings and render state.
// The Filtering settings is the most important part of this call, because you can set a Rendering Layer mask in it.
//
// ----------------------------------------------------------------------------------------------------
FilteringSettings filteringSettings = FilteringSettings.defaultValue;
var drawSettings = new DrawingSettings(_shaderTags[1], new SortingSettings(ctx.hdCamera.camera));
drawSettings.perObjectData = PerObjectData.None;
drawSettings.overrideMaterial = _replacementMaterial;
drawSettings.overrideMaterialPassIndex = 0;
filteringSettings.renderQueueRange = RenderQueueRange.all;
filteringSettings.excludeMotionVectorObjects = false;
filteringSettings.layerMask = LayerMaskFilter;
filteringSettings.renderingLayerMask = (uint)RenderingLayerMaskFilter;
RenderStateBlock stateBlock = new RenderStateBlock(RenderStateMask.Depth)
{
depthState = new DepthState(true, CompareFunction.LessEqual)
};
ctx.renderContext.DrawRenderers(ctx.cullingResults, ref drawSettings, ref filteringSettings, ref stateBlock);
// TEST 3: Using a deprecated Renderer List struct that contains a Filtering Settings field.
// Warning: Uncomment UnityEngine.Experimental.Rendering and comment out UnityEngine.Rendering.RendererUtils as they have conflicting definitions.
//
// In recent versions, Unity has moved the RendererList struct away from the RenderPipeline package, and into the internal UnityEngine.Rendering namespace.
// The previous version is still semi-functional in which you can actually get it to work in scene view, but for some reason I can't get it to show in game view.
//
// ----------------------------------------------------------------------------------------------------
//
// var result = new RendererListDesc(_shaderTags, ctx.cullingResults, ctx.hdCamera.camera)
// {
// rendererConfiguration = PerObjectData.None,
// sortingCriteria = SortingCriteria.BackToFront,
// overrideMaterial = _replacementMaterial,
// overrideMaterialPassIndex = 0,
// renderQueueRange = RenderQueueRange.all,
// excludeObjectMotionVectors = false,
// stateBlock = new RenderStateBlock(RenderStateMask.Depth){ depthState = new DepthState(true, CompareFunction.LessEqual)},
// };
//
// _rendererList = RendererList.Create(result);
//
// FilteringSettings filteringSettings = FilteringSettings.defaultValue;
//
// filteringSettings.renderQueueRange = RenderQueueRange.all;
// filteringSettings.excludeMotionVectorObjects = false;
// filteringSettings.renderingLayerMask = (uint)RenderingLayerMaskFilter;
// filteringSettings.layerMask = LayerMaskFilter;
// RenderStateBlock stateBlock = new RenderStateBlock(RenderStateMask.Depth)
// {
// depthState = new DepthState(true, CompareFunction.LessEqual)
// };
//
// _rendererList.filteringSettings = filteringSettings;
// _rendererList.stateBlock = stateBlock;
//
// CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, _rendererList);
}
}