你好
我将告诉您如何在Unity中的新轻量级渲染管线(LWRP)上创建简单的轮廓效果。 为此,您需要Unity版本2018.3和更高版本,以及LWRP版本4.0.0和更高版本。
经典轮廓由两遍着色器组成,但是LWRP仅支持单遍着色器。 为了解决LWRP中的这一缺陷,可以使用界面将自定义传递添加到渲染的某些阶段:
IAfterDepthPrePass IAfterOpaquePass IAfterOpaquePostProcess IAfterSkyboxPass IAfterTransparentPass IAfterRender
准备工作
我们将需要两个着色器。
首先,我将使用“不亮颜色”。 相反,您可以使用另一个,主要是将Stencil构造添加到着色器。
颜色不亮 Shader "Unlit/SimpleColor" { SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { Tags { "LightMode" = "LightweightForward" } Stencil { Ref 2 Comp always Pass replace } HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Core.hlsl" struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.vertex = TransformObjectToHClip(v.vertex.xyz); return o; } half4 frag (v2f i) : SV_Target { return half4(0.5h, 0.0h, 0.0h, 1.0h); } ENDHLSL } } }
第二个是最简单的轮廓着色器本身。
简单的轮廓 Shader "Unlit/SimpleOutline" { SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { Stencil { Ref 2 Comp notequal Pass keep } HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Core.hlsl" struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; }; half4 _OutlineColor; v2f vert (appdata v) { v2f o; v.vertex.xyz += 0.2 * normalize(v.vertex.xyz); o.vertex = TransformObjectToHClip(v.vertex.xyz); return o; } half4 frag (v2f i) : SV_Target { return _OutlineColor; } ENDHLSL } } }
自定义通行证
编写自定义通行证始于创建通常的MonoBehaviour并实现上述接口之一。 我们使用IAfterOpaquePass,因为大纲将仅应用于不透明的对象。
public class OutlinePass : MonoBehaviour, IAfterOpaquePass { public ScriptableRenderPass GetPassToEnqueue(RenderTextureDescriptor baseDescriptor, RenderTargetHandle colorAttachmentHandle, RenderTargetHandle depthAttachmentHandle) {
该脚本必须添加到摄像机。 通过它,我们将组织段落与游戏逻辑的交互,但以后会更多。
现在让我们开始写这段文字本身。 为此,请创建一个从ScriptableRenderPass继承的类
public class OutlinePassImpl : ScriptableRenderPass { public OutlinePassImpl() {
在构造函数中,我们注册通道的名称,创建材质和设置以在冷却后过滤可见对象。 在过滤器中,我们将仅设置不透明对象,因为我们将在不透明通行证之后添加通行证。
Execute函数是用于传递的渲染函数。 在其中,我们创建渲染设置,设置在构造函数中创建的材质,并渲染所有满足创建的滤镜的可见对象。
原来是我的OutlinePassImpl public class OutlinePassImpl : ScriptableRenderPass { private Material outlineMaterial; private FilterRenderersSettings m_OutlineFilterSettings; private int OutlineColorId; public OutlinePassImpl(Color outlineColor) {
现在让我们添加OutlinePass类。 在这里,创建OutlinePassImpl类的实例非常简单,通过链接,您可以在运行时模式下与用户传递交互。 例如,更改轮廓颜色。
原来是我的OutlinePass public class OutlinePass : MonoBehaviour, IAfterOpaquePass { public Color OutlineColor; private OutlinePassImpl outlinePass; public ScriptableRenderPass GetPassToEnqueue(RenderTextureDescriptor baseDescriptor, RenderTargetHandle colorAttachmentHandle, RenderTargetHandle depthAttachmentHandle) { return outlinePass ?? (outlinePass = new OutlinePassImpl(OutlineColor)); } }
现在设置测试场景。
- 从SimpleColor着色器创建材质
- 创建一个多维数据集并将材料挂在其上。
- 将OutlinePass脚本添加到相机并设置颜色。
- 然后点击播放
轮廓仅在游戏视图中可见。
这是应该获得的结果。

奖励:友敌背光
使用用于过滤可见对象的设置,您可以指定一个图层或渲染层,以便将此段落应用于特定对象或对象组并将其与游戏逻辑关联。
更改通行证,以使所有带有“朋友”层的对象都具有绿色轮廓,而带有“敌人”层的所有对象均具有红色轮廓。
OutlinePass和OutlinePassImpl public class OutlinePass : MonoBehaviour, IAfterOpaquePass { [System.Serializable] public class OutlineData { public Color Color; public LayerMask Layer; } public List<OutlineData> outlineDatas = new List<OutlineData>(); private OutlinePassImpl outlinePass; public ScriptableRenderPass GetPassToEnqueue(RenderTextureDescriptor baseDescriptor, RenderTargetHandle colorAttachmentHandle, RenderTargetHandle depthAttachmentHandle) { return outlinePass ?? (outlinePass = new OutlinePassImpl(outlineDatas)); } } public class OutlinePassImpl : ScriptableRenderPass { private Material[] outlineMaterial; private FilterRenderersSettings[] m_OutlineFilterSettings; public OutlinePassImpl(List<OutlinePass.OutlineData> outlineDatas) { RegisterShaderPassName("LightweightForward"); outlineMaterial = new Material[outlineDatas.Count]; m_OutlineFilterSettings = new FilterRenderersSettings[outlineDatas.Count]; Shader outlineShader = Shader.Find("Unlit/SimpleOutline"); int OutlineColorId = Shader.PropertyToID("_OutlineColor"); for (int i = 0; i < outlineDatas.Count; i++) { OutlinePass.OutlineData outline = outlineDatas[i]; Material material = CoreUtils.CreateEngineMaterial(outlineShader); material.SetColor(OutlineColorId, outline.Color); outlineMaterial[i] = material; m_OutlineFilterSettings[i] = new FilterRenderersSettings(true) { renderQueueRange = RenderQueueRange.opaque, layerMask = outline.Layer }; } } public override void Execute(ScriptableRenderer renderer, ScriptableRenderContext context, ref RenderingData renderingData) { Camera camera = renderingData.cameraData.camera; SortFlags sortFlags = renderingData.cameraData.defaultOpaqueSortFlags; DrawRendererSettings drawSettings = CreateDrawRendererSettings(camera, sortFlags, RendererConfiguration.None, renderingData.supportsDynamicBatching); for (int i = 0; i < outlineMaterial.Length; i++) { drawSettings.SetOverrideMaterial(outlineMaterial[i], 0); context.DrawRenderers(renderingData.cullResults.visibleRenderers, ref drawSettings, m_OutlineFilterSettings[i]); } } }
在场景中,添加“朋友”和“敌人”图层,多次复制多维数据集,将它们的图层分配给“朋友”或“敌人”,设置并运行Outline Pass。

这就是我们得到的。

结论
Unity中的新渲染效果很好,可以轻松创建有趣的效果。
我希望这篇文章对阅读很有帮助。 如有任何疑问,请在评论中与您联系。