using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.RendererUtils; using UnityEngine.Rendering.Universal; public class OutLine : ScriptableRendererFeature { //public Color OutLineColor; //public float OutLineStrength; //public List render=new List(); public List outLinePam=new List(); class CustomRenderPass : ScriptableRenderPass { private readonly int OutLineTemp = Shader.PropertyToID("OutLineTemp"); private readonly int OutLineTemp1 = Shader.PropertyToID("OutLineTemp1"); private readonly int OutLineTemp2 = Shader.PropertyToID("OutLineTemp2"); private readonly int OutLineTemp3 = Shader.PropertyToID("OutLineTemp3"); private readonly int OutLineTemp4 = Shader.PropertyToID("OutLineTemp4"); private readonly int OutLineTemp5 = Shader.PropertyToID("OutLineTemp5"); private readonly int OutLineTemp6 = Shader.PropertyToID("OutLineTemp6"); private Material OutMat; private Material OutMatAll; //public Color OutLineColor; //public float OutLineStrength; //public List render=new List(); public List outLinePam=new List(); public void SetUp() { //ConfigureInput(ScriptableRenderPassInput.Depth); } // This method is called before executing the render pass. // It can be used to configure render targets and their clear state. Also to create temporary render target textures. // When empty this render pass will render to the active camera render target. // You should never call CommandBuffer.SetRenderTarget. Instead call ConfigureTarget and ConfigureClear. // The render pipeline will ensure target setup and clearing happens in a performant manner. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { if (OutMat == null) { OutMat = CoreUtils.CreateEngineMaterial("Unlit URP Shader/OutLine"); OutMatAll = CoreUtils.CreateEngineMaterial("Unlit URP Shader/OutLine2"); } } public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { base.Configure(cmd, cameraTextureDescriptor); RenderTextureDescriptor rtd = cameraTextureDescriptor; rtd.msaaSamples = 1; rtd.colorFormat = RenderTextureFormat.ARGB64; cmd.GetTemporaryRT(OutLineTemp1,rtd); rtd.colorFormat = RenderTextureFormat.ARGB4444; cmd.GetTemporaryRT(OutLineTemp,rtd); rtd.width /= 2; rtd.height /= 2; cmd.GetTemporaryRT(OutLineTemp2,rtd); rtd.width /= 2; rtd.height /= 2; cmd.GetTemporaryRT(OutLineTemp3,rtd); rtd.width /= 2; rtd.height /= 2; cmd.GetTemporaryRT(OutLineTemp4,rtd); rtd.width *= 2; rtd.height *= 2; cmd.GetTemporaryRT(OutLineTemp5,rtd); rtd.width *= 2; rtd.height *= 2; cmd.GetTemporaryRT(OutLineTemp6,rtd); ConfigureTarget(OutLineTemp); ConfigureClear(ClearFlag.All,Vector4.zero); } public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { CommandBuffer cmd = CommandBufferPool.Get("OutLine"); if(outLinePam.Count==0) return; for (int i = 0; i < outLinePam.Count; i++) { if (outLinePam[i] == null || outLinePam[i].renders==null) continue; cmd.SetGlobalFloat("_OutLineWide",outLinePam[i].strength); cmd.SetGlobalColor("_OutLineColor",outLinePam[i].color); for (int j = 0; j < outLinePam[i].renders.Length; j++) { if(outLinePam[i].renders[j]==null) continue; cmd.DrawRenderer(outLinePam[i].renders[j],OutMat,0); } } //2、对RenderTexture模糊处理 cmd.SetGlobalFloat("_BurStength",5); cmd.Blit(OutLineTemp,OutLineTemp2,OutMatAll,1); cmd.SetGlobalFloat("_BurStength",2); cmd.Blit(OutLineTemp2,OutLineTemp3,OutMatAll,1); cmd.SetGlobalFloat("_BurStength",0.3f); cmd.Blit(OutLineTemp3,OutLineTemp4,OutMatAll,1); cmd.SetGlobalTexture("_Temp",OutLineTemp3); cmd.SetGlobalFloat("_BurStength",0.3f); cmd.Blit(OutLineTemp4,OutLineTemp5,OutMatAll,7); cmd.SetGlobalTexture("_Temp",OutLineTemp2); cmd.SetGlobalFloat("_BurStength",2); cmd.Blit(OutLineTemp5,OutLineTemp6,OutMatAll,7); cmd.Blit(OutLineTemp6,OutLineTemp2,OutMatAll,5); cmd.Blit(OutLineTemp2,OutLineTemp6,OutMatAll,6); cmd.SetGlobalFloat("_BurStength",5); cmd.Blit(OutLineTemp6,OutLineTemp1,OutMatAll,1); cmd.Blit(OutLineTemp1,OutLineTemp,OutMatAll,1); //cmd.Blit(OutLineTemp1,OutLineTemp); //3、通过模板测试裁剪描边内部像素 //cmd.DrawRenderer(render); cmd.Blit(OutLineTemp1,OutLineTemp,OutMatAll,2); //4、根据alpha值把RenderTexture和屏幕混合 cmd.SetGlobalTexture("_OutLineTex",OutLineTemp); cmd.Blit(renderingData.cameraData.renderer.cameraColorTarget,OutLineTemp1,OutMatAll,3); cmd.Blit(OutLineTemp1,renderingData.cameraData.renderer.cameraColorTarget); cmd.ReleaseTemporaryRT(OutLineTemp); cmd.ReleaseTemporaryRT(OutLineTemp1); cmd.ReleaseTemporaryRT(OutLineTemp2); cmd.ReleaseTemporaryRT(OutLineTemp3); cmd.ReleaseTemporaryRT(OutLineTemp4); cmd.ReleaseTemporaryRT(OutLineTemp5); cmd.ReleaseTemporaryRT(OutLineTemp6); context.ExecuteCommandBuffer(cmd); cmd.Release(); } // Cleanup any allocated resources that were created during the execution of this render pass. public override void OnCameraCleanup(CommandBuffer cmd) { } public void Distory() { CoreUtils.Destroy(OutMat); CoreUtils.Destroy(OutMatAll); } } CustomRenderPass m_ScriptablePass; /// public override void Create() { m_ScriptablePass = new CustomRenderPass(); // Configures where the render pass should be injected. m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing; } // Here you can inject one or multiple render passes in the renderer. // This method is called when setting up the renderer once per-camera. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if(outLinePam==null) return; //m_ScriptablePass.render = render; //m_ScriptablePass.OutLineColor = OutLineColor; //m_ScriptablePass.OutLineStrength = OutLineStrength; m_ScriptablePass.outLinePam = outLinePam; m_ScriptablePass.SetUp(); renderer.EnqueuePass(m_ScriptablePass); } protected override void Dispose(bool disposing) { base.Dispose(disposing); m_ScriptablePass.Distory(); } }