193 lines
7.6 KiB
C#
193 lines
7.6 KiB
C#
|
|
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();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|