Files
2026-06-05 22:12:05 +08:00

178 lines
6.5 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
#if HDRP_OUTLINE
using UnityEngine.Rendering.HighDefinition;
namespace EPOOutline
{
[VolumeComponentMenu("EPO/Outline")]
public class OutlineCustomPass : CustomPass
{
private List<Outlinable> tempOutlinables = new List<Outlinable>();
private static Queue<OutlineParameters> pool = new Queue<OutlineParameters>();
private static Queue<OutlineParameters> parametersInUse = new Queue<OutlineParameters>();
private List<Outliner> outliners = new List<Outliner>();
[SerializeField]
[HideInInspector]
private Camera lastSelectedCamera = null;
protected override void Execute(CustomPassContext ctx)
{
var camera = ctx.hdCamera.camera;
outliners ??= new List<Outliner>();
outliners.Clear();
#if UNITY_EDITOR
if (camera.cameraType == CameraType.SceneView)
{
if (lastSelectedCamera == null)
{
foreach (var obj in UnityEditor.Selection.gameObjects)
{
lastSelectedCamera = obj.GetComponent<Camera>();
if (lastSelectedCamera != null)
lastSelectedCamera.GetComponents(outliners);
if (outliners.Count != 0)
break;
lastSelectedCamera = null;
}
}
outliners.Clear();
if (lastSelectedCamera != null)
lastSelectedCamera.GetComponents(outliners);
}
else
#endif
camera.GetComponents(outliners);
var hdCameraData = ctx.hdCamera;
var commandBuffer = ctx.cmd;
var context = ctx.renderContext;
RTHandle colorTarget;
RTHandle depthTarget;
colorTarget = ctx.cameraColorBuffer;
depthTarget = ctx.cameraDepthBuffer;
foreach (var outliner in outliners)
UpdateOutliner(context, commandBuffer, camera, outliner, hdCameraData, colorTarget, depthTarget);
if (parametersInUse != null)
{
foreach (var param in parametersInUse)
pool.Enqueue(param);
parametersInUse.Clear();
}
}
private void UpdateOutliner(ScriptableRenderContext renderContext, CommandBuffer cmd, Camera camera, Outliner outlineEffect, HDCamera hdCamera, RTHandle colorTarget, RTHandle depthTarget)
{
if (outlineEffect == null || !outlineEffect.enabled)
return;
pool ??= new Queue<OutlineParameters>();
parametersInUse ??= new Queue<OutlineParameters>();
if (pool.Count == 0)
pool.Enqueue(new OutlineParameters(new BasicCommandBufferWrapper(cmd)));
var parameters = pool.Dequeue();
parametersInUse.Enqueue(parameters);
(parameters.Buffer as BasicCommandBufferWrapper).SetCommandBuffer(cmd);
outlineEffect.UpdateSharedParameters(parameters, camera, camera.cameraType == CameraType.SceneView, true, true);
Outlinable.GetAllActiveOutlinables(parameters.OutlinablesToRender);
RendererFilteringUtility.Filter(parameters.Camera, parameters);
parameters.Buffer.EnableShaderKeyword("EPO_HDRP");
parameters.Target = colorTarget;
parameters.DepthTarget = depthTarget;
parameters.TargetWidth = colorTarget.rt.width;
parameters.TargetHeight = colorTarget.rt.height;
parameters.Antialiasing = colorTarget.rt.antiAliasing;
parameters.Scale = new Vector2(colorTarget.rtHandleProperties.rtHandleScale.x, colorTarget.rtHandleProperties.rtHandleScale.y);
var viewportSize = colorTarget.useScaling
? colorTarget.GetScaledSize(colorTarget.rtHandleProperties.currentViewportSize)
: colorTarget.rtHandleProperties.currentViewportSize;
parameters.Viewport = new Rect(Vector2.zero, viewportSize);
parameters.ScaledBufferWidth = viewportSize.x;
parameters.ScaledBufferHeight = viewportSize.y;
if (outlineEffect.RenderingStrategy == OutlineRenderingStrategy.Default)
{
outlineEffect.UpdateSharedParameters(parameters, camera, camera.cameraType == CameraType.SceneView, true, true);
outlineEffect.ReplaceHandles(parameters);
parameters.Prepare();
OutlineEffect.SetupOutline(parameters);
renderContext.ExecuteCommandBuffer((parameters.Buffer as BasicCommandBufferWrapper).UnderlyingBuffer);
parameters.Buffer.Clear();
}
else
{
tempOutlinables ??= new List<Outlinable>();
tempOutlinables.Clear();
tempOutlinables.AddRange(parameters.OutlinablesToRender);
outlineEffect.UpdateSharedParameters(parameters, camera, camera.cameraType == CameraType.SceneView, true, true);
outlineEffect.ReplaceHandles(parameters);
foreach (var outlinable in tempOutlinables)
{
parameters.OutlinablesToRender.Clear();
parameters.OutlinablesToRender.Add(outlinable);
parameters.BlitMesh = null;
parameters.Prepare();
OutlineEffect.SetupOutline(parameters);
renderContext.ExecuteCommandBuffer((parameters.Buffer as BasicCommandBufferWrapper).UnderlyingBuffer);
parameters.Buffer.Clear();
}
if (tempOutlinables.Count == 0)
{
parameters.OutlinablesToRender.Clear();
parameters.Prepare();
parameters.BlitMesh = null;
OutlineEffect.SetupOutline(parameters);
renderContext.ExecuteCommandBuffer((parameters.Buffer as BasicCommandBufferWrapper).UnderlyingBuffer);
parameters.Buffer.Clear();
}
parameters.MeshPool.ReleaseAllMeshes();
}
parameters.Buffer.Clear();
}
}
}
#endif