Files
Studio/Assets/Scripts/UVC/ScriptableRenderFeature/EdgeDetection.cs
2025-06-12 16:15:53 +09:00

98 lines
3.9 KiB
C#

using System;
using System.Drawing.Drawing2D;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.Universal;
namespace UVC.Rendering
{
public class EdgeDetection : ScriptableRendererFeature
{
private class EdgeDetectionPass : ScriptableRenderPass
{
private Material material;
private static readonly int OutlineThicknessProperty = Shader.PropertyToID("_OutlineThickness");
private static readonly int OutlineColorProperty = Shader.PropertyToID("_OutlineColor");
public EdgeDetectionPass()
{
profilingSampler = new ProfilingSampler(nameof(EdgeDetectionPass));
}
public void Setup(ref EdgeDetectionSettings settings, ref Material edgeDetectionMaterial)
{
material = edgeDetectionMaterial;
renderPassEvent = settings.renderPassEvent;
material.SetFloat(OutlineThicknessProperty, settings.outlineThickness);
material.SetColor(OutlineColorProperty, settings.outlineColor);
}
private class PassData
{
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
var resourceData = frameData.Get<UniversalResourceData>();
using var builder = renderGraph.AddRasterRenderPass<PassData>("Edge Detection", out var passData);
builder.SetRenderAttachment(resourceData.activeColorTexture, 0);
builder.UseAllGlobalTextures(true);
builder.AllowPassCulling(false);
builder.SetRenderFunc((PassData pd, RasterGraphContext context) =>
{
Blitter.BlitTexture(context.cmd, Vector2.one, material, 0);
});
}
}
[Serializable]
public class EdgeDetectionSettings
{
public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingTransparents;
[Range(0, 15)] public float outlineThickness = 3;
public Color outlineColor = Color.black;
public LayerMask layerMask = ~0;
}
[SerializeField] EdgeDetectionSettings settings;
public Material edgeDetectionMaterial;
EdgeDetectionPass edgeDetectionPass;
public override void Create()
{
edgeDetectionPass ??= new EdgeDetectionPass();
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
if (renderingData.cameraData.cameraType == CameraType.Preview
|| renderingData.cameraData.cameraType == CameraType.Reflection
|| UniversalRenderer.IsOffscreenDepthTexture(ref renderingData.cameraData))
{
return;
}
if (edgeDetectionMaterial == null)
{
edgeDetectionMaterial= CoreUtils.CreateEngineMaterial(Shader.Find("Custom/EdgeDetectionOutline"));
if(edgeDetectionMaterial == null)
{
Debug.LogWarning("Not all required materials could be created. Edge Detection will not render.");
return;
}
}
edgeDetectionPass.ConfigureInput(ScriptableRenderPassInput.Depth | ScriptableRenderPassInput.Normal | ScriptableRenderPassInput.Color);
edgeDetectionPass.requiresIntermediateTexture = true;
edgeDetectionPass.Setup(ref settings, ref edgeDetectionMaterial);
renderer.EnqueuePass(edgeDetectionPass);
}
protected override void Dispose(bool disposing)
{
edgeDetectionPass = null;
if (edgeDetectionMaterial != null)
GameObject.DestroyImmediate(edgeDetectionMaterial);
}
}
}