今天看源码无意间发现了renderingLayerMask属性,真是解决了一个大问题啊。 比如我有多个角色,希望其中某几个拥有描边效果,此时又不希望写多个Layer层。就可以添加一个RenderMaskLayer。如下图所示。 可以自己扩展一个RenderObjects类。
RenderObjectsPass.cs
public RenderObjectsPass(string profilerTag, RenderPassEvent renderPassEvent, string[] shaderTags, RenderQueueType renderQueueType, int layerMask, uint renderMask,RenderObjects.CustomCameraSettings cameraSettings)
{
//..略
m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
m_FilteringSettings.renderingLayerMask = renderMask; //在这里设置renderMask
}
RenderObjects.cs
[System.Flags]
public enum RenderLayer
{
Outline = (1 << 0),
A2 = (1 << 1),
A3 = (1 << 2),
A4 = (1 << 3),
}
[System.Serializable]
public class FilterSettings
{
public RenderQueueType RenderQueueType;
public LayerMask LayerMask;
public string[] PassNames;
public RenderLayer RenderMask; //添加RenderMask
public FilterSettings()
{
RenderQueueType = RenderQueueType.Opaque;
LayerMask = 0;
}
}
public override void Create()
{
FilterSettings filter = settings.filterSettings;
//...略
//传入RenderMask
renderObjectsPass = new RenderObjectsPass(settings.passTag, settings.Event, filter.PassNames,
filter.RenderQueueType, filter.LayerMask, (uint)filter.RenderMask, settings.cameraSettings);
}
RenderObjectsPassFeatureEditor.cs 修改面板
void DoFilters(ref Rect rect)
{
m_FiltersFoldout.value = EditorGUI.Foldout(rect, m_FiltersFoldout.value, Styles.filtersHeader, true);
SaveHeaderBool(m_FiltersFoldout);
rect.y += Styles.defaultLineSpace;
if (m_FiltersFoldout.value)
{
EditorGUI.indentLevel++;
//Render queue filter
EditorGUI.PropertyField(rect, m_RenderQueue, Styles.renderQueueFilter);
rect.y += Styles.defaultLineSpace;
//Layer mask
EditorGUI.PropertyField(rect, m_LayerMask, Styles.layerMask);
rect.y += Styles.defaultLineSpace;
EditorGUI.PropertyField(rect, m_RenderMask, Styles.renderMask);//在这里添加面板
rect.y += Styles.defaultLineSpace;
//Shader pass list
EditorGUI.PropertyField(rect, m_ShaderPasses, Styles.shaderPassFilter, true);
rect.y += EditorGUI.GetPropertyHeight(m_ShaderPasses);
EditorGUI.indentLevel--;
}
}
然后在需要描边的Render上挂脚本,设置它的RenderMask层级
GetComponent<Renderer>().renderingLayerMask = (uint)renderLayer;
大功告成,两个Cube在同一个层, 但是设置了不同的RenderMask,所以效果不同。
今天美术又给我来了个灵魂拷问,他们的材质使用的是多维子材质。如下图所示,一个Render上有多个材质,美术同学系统其中某一个才需要描边这种特殊效果,而其他的不需要。开始我想使用CommandBuffer.DrawRender,但是这样就无法使用SrpBatcher里, 由于每个人的Mesh也都不相同,这样就没办法用GPU Instancing了,效率恐怕不会更好,随后想到了这个办法。
它需要占用一个RenderQueue了,如上图中将需要特殊效果的材质的RenderQueue设置成2001,如果透明就设置成3001,具体数值设置成其他也行就是做一个区分,让管线知道它和其他的不同。(2001和3001也可以根据情况改成其他数值)
public RenderObjectsPass(string profilerTag, RenderPassEvent renderPassEvent, string[] shaderTags, RenderQueueType renderQueueType, int layerMask, RenderObjects.CustomCameraSettings cameraSettings)
{
//..略
RenderQueueRange renderQueueRange = (renderQueueType == RenderQueueType.Transparent)
? RenderQueueRange.transparent
: RenderQueueRange.opaque;
m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
//设置需要特殊效果的RenderQueue
if(renderQueueRange == RenderQueueRange.opaque)
m_FilteringSettings.renderQueueRange = new RenderQueueRange(2001, 2001);
else if (renderQueueRange == RenderQueueRange.transparent)
m_FilteringSettings.renderQueueRange = new RenderQueueRange(3001, 3001);
}
通过这段代码可以强制设置不透明只有2001才会有描边特效效果, 透明只有3001层级才有描边特殊效果。这种方法暂时可以解决问题,但是毕竟还需要修改RenderQueue实际应用中还需要美术同学配合,如下图所示,都是多维子材质,可以选择性开启或关闭覆盖的特殊效果了。
- 本文固定链接: https://www.xuanyusong.com/archives/4956
- 转载请注明: 雨松MOMO于 雨松MOMO程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!






感觉还是不好用,如果我想按照确切的几个物体而不是layer就很麻烦,所以我自己写了个基于list列表来渲染对象的renderfeature,但是深度贴图又有问题,崩溃了。
能分享下完整的代码吗,最近刚在接触在新项目尝试使用的