193 lines
7.6 KiB
C#
Raw Normal View History

2025-01-02 12:15:45 +08:00
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<Renderer> render=new List<Renderer>();
public List<OutLinePam> outLinePam=new List<OutLinePam>();
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<Renderer> render=new List<Renderer>();
public List<OutLinePam> outLinePam=new List<OutLinePam>();
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 <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
// 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;
/// <inheritdoc/>
public override void Create()
{
m_ScriptablePass = new CustomRenderPass();
// Configures where the render pass should be injected.
m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingTransparents;
}
// 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();
}
}