using AOT.Common; using UnityEngine; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; using UnityEngine.Rendering.RendererUtils; using UnityEngine.Rendering.Universal; public class PostOutlineRPF : ScriptableRendererFeature { [System.Serializable] public class Settings { //渲染发生的阶段,具体信息可以在枚举类RenderPassEvent中查看 public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingSkybox; public LayerMask teamSelfLayer; public LayerMask teamEnemyLayer; public LayerMask teamNeutralLayer; } class CustomRenderPass : ScriptableRenderPass { private Settings _settings; private Material _matSelf; private Material _matEnemy; private Material _matNeutral; private Material _mat2; private Material _mat3; private int _SSOutlineTexureID; private int _EdgeTexureID; private bool _canEnable = false; private readonly ShaderTagId _shaderTagId = new ShaderTagId("UniversalForward"); public CustomRenderPass(Settings setting) { _settings = setting; } public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { base.OnCameraSetup(cmd, ref renderingData); _canEnable = false; if (OutlineManager.instance == null || !OutlineManager.instance.m_EnableOutline) { if (AOTCodeDefine.ENABLE_OUTLINE_DEBUG) { Debug.Log("OutlineManager.instance == null || !OutlineManager.instance.m_EnableOutline"); } return; } if (renderingData.cameraData.camera != OutlineManager.instance.targetCamera) { if (AOTCodeDefine.ENABLE_OUTLINE_DEBUG) { Debug.Log("不是主相机, 当前相机名字: " + renderingData.cameraData.camera.name + " 主相机名字:" + OutlineManager.instance.targetCamera.name); } return; } if (_matSelf == null) { _matSelf = OutlineManager.instance.mat1; _matSelf.SetColor(PureColor, OutlineManager.instance.m_OutlineColor); _matEnemy = OutlineManager.instance.mat1_1; _matEnemy.SetColor(PureColor, OutlineManager.instance.m_OutlineColorEnemy); _matNeutral = OutlineManager.instance.mat1_2; _matNeutral.SetColor(PureColor, OutlineManager.instance.m_OutlineColorNeutral); _mat2 = OutlineManager.instance.mat2; _mat3 = OutlineManager.instance.mat3; _SSOutlineTexureID = Shader.PropertyToID("_SSOutlineTexure"); _EdgeTexureID = Shader.PropertyToID("_EdgeTex"); } var isSupported = _matSelf.shader.isSupported && _mat2.shader.isSupported && _mat3.shader.isSupported; if (!isSupported) { Debug.LogError("Shader not supported on platform"); return; } _canEnable = true; if (AOTCodeDefine.ENABLE_OUTLINE_DEBUG) { Debug.Log("可以进行描边渲染"); } } public override void OnCameraCleanup(CommandBuffer cmd) { base.OnCameraCleanup(cmd); if (!_canEnable) return; } public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { if (!_canEnable) return; var cmd = CommandBufferPool.Get("Draw Outline"); _DrawPureColor(cmd, context, ref renderingData); _DoEdgeDetect(cmd, context, ref renderingData); _DoMerge(cmd, context, ref renderingData); context.ExecuteCommandBuffer(cmd); cmd.ReleaseTemporaryRT(_EdgeTexureID); cmd.ReleaseTemporaryRT(_SSOutlineTexureID); CommandBufferPool.Release(cmd); } private void _DrawPureColor(CommandBuffer cmd, ScriptableRenderContext context, ref RenderingData renderingData) { var desc = renderingData.cameraData.cameraTargetDescriptor; //using (new ProfilingScope(cmd, new ProfilingSampler("Draw PureColor"))) { // 绘制己方 cmd.GetTemporaryRT(_SSOutlineTexureID, desc.width, desc.height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32); cmd.SetRenderTarget(_SSOutlineTexureID); cmd.ClearRenderTarget(true, true, new Color(0, 0, 0, 0)); var renderListDesc = new RendererListDesc(_shaderTagId, renderingData.cullResults, renderingData.cameraData.camera); renderListDesc.renderQueueRange = RenderQueueRange.all; renderListDesc.layerMask = _settings.teamSelfLayer; renderListDesc.overrideMaterial = _matSelf; var renderList = context.CreateRendererList(renderListDesc); cmd.DrawRendererList(renderList); } // using (new ProfilingScope(cmd, new ProfilingSampler("Draw PureColor"))) { // 绘制敌方 var renderListDesc = new RendererListDesc(_shaderTagId, renderingData.cullResults, renderingData.cameraData.camera); renderListDesc.renderQueueRange = RenderQueueRange.all; renderListDesc.layerMask = _settings.teamEnemyLayer; renderListDesc.overrideMaterial = _matEnemy; var renderList = context.CreateRendererList(renderListDesc); cmd.DrawRendererList(renderList); } { // 绘制中立 var renderListDesc = new RendererListDesc(_shaderTagId, renderingData.cullResults, renderingData.cameraData.camera); renderListDesc.renderQueueRange = RenderQueueRange.all; renderListDesc.layerMask = _settings.teamNeutralLayer; renderListDesc.overrideMaterial = _matNeutral; var renderList = context.CreateRendererList(renderListDesc); cmd.DrawRendererList(renderList); } // context.ExecuteCommandBuffer(cmd); // CommandBufferPool.Release(cmd); } private void _DoEdgeDetect(CommandBuffer cmd, ScriptableRenderContext context, ref RenderingData renderingData) { // var cmd = CommandBufferPool.Get("Draw Outline"); // using (new ProfilingScope(cmd, new ProfilingSampler("Final SSOutline"))) { var desc = renderingData.cameraData.cameraTargetDescriptor; cmd.GetTemporaryRT(_EdgeTexureID, desc.width, desc.height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32); var sampleDistance = OutlineManager.instance.m_SampleDistance; var scaleProgress = OutlineManager.instance.scaleProgress; _mat2.SetFloat(SampleDistance, scaleProgress * sampleDistance); _mat2.SetColor(OutlineColor, OutlineManager.instance.m_OutlineColor); cmd.Blit(_SSOutlineTexureID, _EdgeTexureID, _mat2); } // context.ExecuteCommandBuffer(cmd); // CommandBufferPool.Release(cmd); } private void _DoMerge(CommandBuffer cmd, ScriptableRenderContext context, ref RenderingData renderingData) { // using (new ProfilingScope(cmd, new ProfilingSampler("SSOutline Merge"))) { var source = renderingData.cameraData.renderer.cameraColorTargetHandle.nameID; cmd.SetGlobalTexture("_EdgeTex", _EdgeTexureID); cmd.Blit(source, _SSOutlineTexureID, _mat3, 0); cmd.Blit(_SSOutlineTexureID, source, _mat3, 0); } // context.ExecuteCommandBuffer(cmd); } } public Settings settings; private CustomRenderPass _pass; private static readonly int SampleDistance = Shader.PropertyToID("_SampleDistance"); private static readonly int OutlineColor = Shader.PropertyToID("_OutlineColor"); private static readonly int PureColor = Shader.PropertyToID("_PureColor"); public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { renderer.EnqueuePass(_pass); } public override void Create() { _pass = new CustomRenderPass(settings); _pass.renderPassEvent = settings.renderPassEvent; } }