مرحبًا.
سأخبرك بكيفية إنشاء تأثير مخطط تفصيلي بسيط على خط أنابيب العرض الخفيف الجديد (LWRP) في Unity. للقيام بذلك ، تحتاج إلى إصدار Unity 2018.3 وأعلى ، وكذلك LWRP الإصدار 4.0.0 وأعلى.
يتكون المخطط الكلاسيكي من تظليل ثنائي التمرير ، لكن LWRP يدعم فقط تظليل التمرير الواحد. لإصلاح هذا العيب في LWRP ، أصبح من الممكن إضافة تمرير مخصص إلى مراحل معينة من العرض باستخدام الواجهات:
IAfterDepthPrePass IAfterOpaquePass IAfterOpaquePostProcess IAfterSkyboxPass IAfterTransparentPass IAfterRender
التحضير
سنحتاج إلى اثنين من تظليل.
أولاً سأستخدم Unlit Color. بدلاً من ذلك ، يمكنك استخدام أخرى ، الشيء الرئيسي هو إضافة بنية 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() {
في المُنشئ ، نقوم بتسجيل اسم المقطع ، وإنشاء مواد وإعدادات لتصفية الأشياء المرئية بعد التبريد. في المرشح ، سنقوم بتعيين الكائنات المعتمة فقط ، حيث سنضيف التمرير بعد التمرير المعتم.
وظيفة التنفيذ هي وظيفة تقديم لتمرير. في ذلك ، نقوم بإنشاء إعدادات للعرض ، وتعيين المادة التي تم إنشاؤها في المُنشئ ، وتقديم كل الكائنات المرئية التي تلبي عامل التصفية الذي تم إنشاؤه.
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 Shader
- اصنع مكعبًا وعلق المواد عليه.
- قم بإضافة برنامج نصي OutlinePass إلى الكاميرا وقم بتعيين اللون.
- وانقر فوق تشغيل
سيكون المخطط التفصيلي مرئيًا فقط في عرض اللعبة.
هنا يجب الحصول على النتيجة.

المكافأة: الإضاءة الخلفية لصديق العدو
باستخدام الإعداد لتصفية الكائنات المرئية ، يمكنك تحديد طبقة أو طبقة تجسيد لتطبيق هذا المقطع على كائن معين أو مجموعة من الكائنات وربطها بمنطق اللعبة.
قم بتغيير تصريحنا بحيث يكون لكل الكائنات ذات طبقة "Friend" مخطط أخضر ، وطبقة "Enemy" باللون الأحمر.
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]); } } }
في المشهد ، أضف طبقات "الصديق" و "العدو" ، وقم بتكرار المكعب عدة مرات ، وقم بتعيين الطبقات إلى "الصديق" أو "العدو" ، واضبط بطاقة المخطط التفصيلي وقم بتشغيلها.

وهذا ما نحصل عليه.

الخلاصة
يتوسع العرض الجديد في Unity بشكل جيد للغاية ، مما يجعل إنشاء تأثيرات مثيرة للاهتمام أمرًا سهلاً للغاية.
آمل أن تكون المقالة مفيدة للقراءة. إذا كان لدى أي شخص أسئلة ، أراك في التعليقات.