using Code.Scripts.Gameplay.Utils; using Gameplay.Performance; using PhxhSDK; using UnityEngine; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using Constants = Framework.Constants; public class PostOutlineRPF : ScriptableRendererFeature { [System.Serializable] public class Settings { //渲染发生的阶段,具体信息可以在枚举类RenderPassEvent中查看 public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingSkybox; } class CustomRenderPass : ScriptableRenderPass { private Material _mat1; private Material _mat1_1; private Material _mat2; private Material _mat3; private int _SSOutlineTexureID; private int _EdgeTexureID; private bool _canEnable = false; public CustomRenderPass(Settings setting) { } public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { base.OnCameraSetup(cmd, ref renderingData); _canEnable = false; if (renderingData.cameraData.renderType != CameraRenderType.Base) { return; } if (OutlineManager.instance == null || !OutlineManager.instance.m_EnableOutline) return; if (OutlineManager.instance.m_RenderList.Count == 0 && OutlineManager.instance.m_RenderListEnemy.Count == 0) return; if (!PerformanceManager.instance.data.enablePostOutline) return; if (_mat1 == null) { _mat1 = Instantiate(AssetManager.Instance.GetPreLoadResult(Constants.SHADER_OUTLINE_PATH1)); _mat1_1 = Instantiate(AssetManager.Instance.GetPreLoadResult(Constants.SHADER_OUTLINE_PATH1_1)); _mat2 = Instantiate(AssetManager.Instance.GetPreLoadResult(Constants.SHADER_OUTLINE_PATH2)); _mat3 = Instantiate(AssetManager.Instance.GetPreLoadResult(Constants.SHADER_OUTLINE_PATH3)); // DebugUtil.LogError("shader name: " + _mat1.shader.name + " " + _mat2.shader.name + " " + _mat3.shader.name); // DebugUtil.LogError("shader pass count:" + _mat1.shader.passCount + " " + _mat2.shader.passCount + " " + _mat3.shader.passCount); // DebugUtil.LogError("shader support:" + _mat1.shader.isSupported + " " + _mat2.shader.isSupported + " " + _mat3.shader.isSupported); _SSOutlineTexureID = Shader.PropertyToID("_SSOutlineTexure"); _EdgeTexureID = Shader.PropertyToID("_EdgeTex"); } _canEnable = _mat1.shader.isSupported && _mat2.shader.isSupported && _mat3.shader.isSupported; } 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 camera = renderingData.cameraData.camera; if (camera != Camera.main) { 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); } Plane[] frustumPlanes = new Plane[6]; private void _DrawPureColor(CommandBuffer cmd, ScriptableRenderContext context, ref RenderingData renderingData) { GeometryUtility.CalculateFrustumPlanes(renderingData.cameraData.camera, frustumPlanes); var desc = renderingData.cameraData.cameraTargetDescriptor; //using (new ProfilingScope(cmd, new ProfilingSampler("Draw PureColor"))) { // 绘制己方 _mat1.SetColor(PureColor, OutlineManager.instance.m_OutlineColor); 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 renders = OutlineManager.instance.m_RenderList; for (var i = 0; i < renders.Count; ++i) { var render = renders[i]; if (render == null) { renders.RemoveAt(i--); continue; } if (!render.gameObject.activeInHierarchy) { continue; } // 判断是否在屏幕内 if (!GeometryUtility.TestPlanesAABB(frustumPlanes, render.bounds)) { continue; } cmd.DrawRenderer(render, _mat1); } } // using (new ProfilingScope(cmd, new ProfilingSampler("Draw PureColor"))) { // 绘制敌方 _mat1_1.SetColor(PureColor, OutlineManager.instance.m_OutlineColorEnemy); var renders = OutlineManager.instance.m_RenderListEnemy; for (var i = 0; i < renders.Count; ++i) { var render = renders[i]; if (render == null) { renders.RemoveAt(i--); continue; } if (!render.gameObject.activeInHierarchy) { continue; } // 判断是否在屏幕内 if (!GeometryUtility.TestPlanesAABB(frustumPlanes, render.bounds)) { continue; } cmd.DrawRenderer(render, _mat1_1); } } // 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 screenWidth = desc.width; var sampleDistance = OutlineManager.instance.m_SampleDistance; var wrapDistance = sampleDistance / 1080 * screenWidth; var scaleProgress = CameraManager.Instance.GetOutlineScale(wrapDistance); _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"))) { // TODO: 使用新方法会报错 #pragma warning disable CS0618 // 类型或成员已过时 var source = renderingData.cameraData.renderer.cameraColorTarget; #pragma warning restore CS0618 // 类型或成员已过时 cmd.SetGlobalTexture("_EdgeTex", _EdgeTexureID); cmd.Blit(source, _SSOutlineTexureID, _mat3); cmd.Blit(_SSOutlineTexureID, source, _mat3); } // 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; } }