184 lines
7.3 KiB
C#
184 lines
7.3 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>();
|
|
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 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.BGRA32;
|
|
cmd.GetTemporaryRT(OutLineTemp1,rtd);
|
|
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");
|
|
//RenderTextureDescriptor rtd = renderingData.cameraData.cameraTargetDescriptor;
|
|
//rtd.msaaSamples = 1;
|
|
|
|
OutMat.SetColor("_OutLineColor",OutLineColor);
|
|
OutMat.SetFloat("_OutLineWide",OutLineStrength);
|
|
OutMatAll.SetColor("_OutLineColor",OutLineColor);
|
|
OutMatAll.SetFloat("_OutLineWide",OutLineStrength);
|
|
//1、将需要描边的物体绘制到一张RenderTexture
|
|
if(render.Count==0 || render==null) return;
|
|
for (int i = 0; i < render.Count; i++)
|
|
{
|
|
if(render[i]==null) return;
|
|
cmd.DrawRenderer(render[i],OutMat,0);
|
|
}
|
|
|
|
|
|
|
|
//2、对RenderTexture模糊处理
|
|
|
|
cmd.SetGlobalFloat("_BurStength",3);
|
|
cmd.Blit(OutLineTemp,OutLineTemp2,OutMatAll,1);
|
|
cmd.SetGlobalFloat("_BurStength",5);
|
|
cmd.Blit(OutLineTemp2,OutLineTemp3,OutMatAll,1);
|
|
cmd.SetGlobalFloat("_BurStength",7);
|
|
cmd.Blit(OutLineTemp3,OutLineTemp4,OutMatAll,1);
|
|
cmd.SetGlobalTexture("_Temp",OutLineTemp3);
|
|
cmd.SetGlobalFloat("_BurStength",5);
|
|
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.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(render==null) return;
|
|
m_ScriptablePass.render = render;
|
|
m_ScriptablePass.OutLineColor = OutLineColor;
|
|
m_ScriptablePass.OutLineStrength = OutLineStrength;
|
|
m_ScriptablePass.SetUp();
|
|
renderer.EnqueuePass(m_ScriptablePass);
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
base.Dispose(disposing);
|
|
m_ScriptablePass.Distory();
|
|
}
|
|
}
|
|
|
|
|