今天看源码无意间发现了renderingLayerMask属性,真是解决了一个大问题啊。 比如我有多个角色,希望其中某几个拥有描边效果,此时又不希望写多个Layer层。就可以添加一个RenderMaskLayer。如下图所示。 可以自己扩展一个RenderObjects类。
RenderObjectsPass.cs
1 2 3 4 5 6 7 8 9 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
[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 修改面板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
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层级
1 2 3 |
GetComponent<Renderer>().renderingLayerMask = (uint)renderLayer; |
大功告成,两个Cube在同一个层, 但是设置了不同的RenderMask,所以效果不同。
今天美术又给我来了个灵魂拷问,他们的材质使用的是多维子材质。如下图所示,一个Render上有多个材质,美术同学系统其中某一个才需要描边这种特殊效果,而其他的不需要。开始我想使用CommandBuffer.DrawRender,但是这样就无法使用SrpBatcher里, 由于每个人的Mesh也都不相同,这样就没办法用GPU Instancing了,效率恐怕不会更好,随后想到了这个办法。
它需要占用一个RenderQueue了,如上图中将需要特殊效果的材质的RenderQueue设置成2001,如果透明就设置成3001,具体数值设置成其他也行就是做一个区分,让管线知道它和其他的不同。(2001和3001也可以根据情况改成其他数值)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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,但是深度贴图又有问题,崩溃了。
能分享下完整的代码吗,最近刚在接触在新项目尝试使用的