2026-03-18 허수아비 추가
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.RenderGraphModule;
|
||||
using UnityEngine.Rendering.RenderGraphModule.Util;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace Ilumisoft.Rendering
|
||||
{
|
||||
[SupportedOnRenderer(typeof(UniversalRendererData))]
|
||||
[DisallowMultipleRendererFeature("Outline")]
|
||||
public class OutlineRendererFeature : ScriptableRendererFeature
|
||||
{
|
||||
public enum InjectionPoint
|
||||
{
|
||||
BeforeRenderingTransparents = 450,
|
||||
BeforeRenderingPostProcessing = 550
|
||||
}
|
||||
|
||||
public enum OutlineMode
|
||||
{
|
||||
DepthOnly,
|
||||
[InspectorName("Depth + Normal")]
|
||||
DepthNormal
|
||||
}
|
||||
|
||||
public struct Settings
|
||||
{
|
||||
public OutlineMode Mode;
|
||||
public bool ScaleWithResolution;
|
||||
public int ReferenceHeight;
|
||||
}
|
||||
|
||||
class OutlineRenderPass : ScriptableRenderPass
|
||||
{
|
||||
private readonly int LUMINANCE_CONTRAST = Shader.PropertyToID("_LuminanceContrast");
|
||||
private readonly int LUMINANCE_POWER = Shader.PropertyToID("_LuminancePower");
|
||||
private readonly int BACKGROUND_COLOR = Shader.PropertyToID("_BackgroundColor");
|
||||
private readonly int BACKGROUND_COLOR_OPACITY = Shader.PropertyToID("_BackgroundColorOpacity");
|
||||
private readonly int DEPTH_EDGE = Shader.PropertyToID("_DepthEdge");
|
||||
private readonly int NORMAL_EDGE = Shader.PropertyToID("_NormalEdge");
|
||||
private readonly int IS_FADE_ENABLED = Shader.PropertyToID("_IsFadeEnabled");
|
||||
private readonly int FADE_START = Shader.PropertyToID("_FadeStart");
|
||||
private readonly int FADE_END = Shader.PropertyToID("_FadeEnd");
|
||||
private readonly int REFERENCE_HEIGHT = Shader.PropertyToID("_ReferenceHeight");
|
||||
private readonly int OUTLINE_THICKNESS_ID = Shader.PropertyToID("_OutlineThickness");
|
||||
private readonly int OUTLINE_COLOR_ID = Shader.PropertyToID("_OutlineColor");
|
||||
|
||||
Material material;
|
||||
|
||||
Settings settings;
|
||||
|
||||
public void Setup(Material material, Settings settings)
|
||||
{
|
||||
this.material = material;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
|
||||
{
|
||||
var volumeComponent = VolumeManager.instance.stack.GetComponent<OutlineVolumeComponent>();
|
||||
|
||||
// Get settings from volume component
|
||||
int thickness = volumeComponent.thickness.value;
|
||||
Color outlineColor = volumeComponent.outlineColor.value;
|
||||
Color backgroundColor = volumeComponent.backgroundColor.value;
|
||||
bool isDistanceFadeEnabled = volumeComponent.distanceFade.value;
|
||||
float distanceFadeStart = volumeComponent.fadeStart.value;
|
||||
float distanceFadeDistance = volumeComponent.fadeDistance.value;
|
||||
bool backgroundFill = volumeComponent.backgroundFill.value;
|
||||
Vector2 depthEdge = volumeComponent.depthSmoothstep.value;
|
||||
Vector2 normalEdge = volumeComponent.normalSmoothstep.value;
|
||||
float luminancePower = volumeComponent.luminanceDetail.value;
|
||||
float luminanceContrast = volumeComponent.luminanceContrast.value;
|
||||
|
||||
int referenceHeight = settings.ReferenceHeight;
|
||||
|
||||
// Cancel if outline are disabled
|
||||
if (thickness == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
|
||||
|
||||
var sourceHandle = resourceData.activeColorTexture;
|
||||
var descriptor = sourceHandle.GetDescriptor(renderGraph);
|
||||
descriptor.clearBuffer = false;
|
||||
descriptor.name = "_CameraColorOutline";
|
||||
|
||||
if (!sourceHandle.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current image height if outlines should not be scaled by a reference resolution
|
||||
if (!settings.ScaleWithResolution)
|
||||
{
|
||||
referenceHeight = descriptor.height;
|
||||
}
|
||||
|
||||
// Set material properties
|
||||
material.SetColor(OUTLINE_COLOR_ID, outlineColor);
|
||||
material.SetInt(OUTLINE_THICKNESS_ID, thickness);
|
||||
material.SetInt(REFERENCE_HEIGHT, referenceHeight);
|
||||
material.SetInt(IS_FADE_ENABLED, isDistanceFadeEnabled ? 1 : 0);
|
||||
material.SetFloat(FADE_START, distanceFadeStart);
|
||||
material.SetFloat(FADE_END, distanceFadeStart + distanceFadeDistance);
|
||||
material.SetColor(BACKGROUND_COLOR, backgroundColor);
|
||||
material.SetFloat(BACKGROUND_COLOR_OPACITY, backgroundFill ? 1 : 0);
|
||||
material.SetVector(DEPTH_EDGE, depthEdge);
|
||||
material.SetVector(NORMAL_EDGE, normalEdge);
|
||||
material.SetFloat(LUMINANCE_POWER, luminancePower);
|
||||
material.SetFloat(LUMINANCE_CONTRAST, luminanceContrast);
|
||||
|
||||
// Outline blit
|
||||
TextureHandle targetHandle = renderGraph.CreateTexture(descriptor);
|
||||
var parameters = new RenderGraphUtils.BlitMaterialParameters(sourceHandle, targetHandle, material, (int)settings.Mode);
|
||||
renderGraph.AddBlitPass(parameters, passName: "Draw Outlines");
|
||||
|
||||
resourceData.cameraColor = targetHandle;
|
||||
}
|
||||
}
|
||||
|
||||
[Tooltip("Specifies where in the frame this pass will be injected.")]
|
||||
public InjectionPoint injectionPoint = InjectionPoint.BeforeRenderingTransparents;
|
||||
|
||||
[Tooltip("Determines which scene data is used for edge detection. 'Depth Only' uses depth differences. 'Depth + Normal' uses surface angle changes as well.")]
|
||||
public OutlineMode mode = OutlineMode.DepthNormal;
|
||||
|
||||
[Tooltip("When enabled, outline thickness scales proportionally with screen resolution to maintain visual consistency across different screen resolutions.")]
|
||||
public bool scaleWithResolution = true;
|
||||
|
||||
[Tooltip("The vertical resolution used as a baseline for outline thickness scaling. A value of 1080 means the effect appears 1:1 at 1080p.")]
|
||||
[Min(720)]
|
||||
public int referenceHeight = 1080;
|
||||
|
||||
public bool showInSceneView = false;
|
||||
|
||||
Shader shader;
|
||||
Material material;
|
||||
OutlineRenderPass renderPass;
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
shader = Shader.Find("Hidden/Ilumisoft/PostProcessing/Outline");
|
||||
|
||||
if (shader == null)
|
||||
{
|
||||
Debug.LogWarning("Outline Renderer Feature: Could not find outline shader");
|
||||
return;
|
||||
}
|
||||
|
||||
material = CoreUtils.CreateEngineMaterial(shader);
|
||||
renderPass = new OutlineRenderPass();
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
||||
{
|
||||
if (renderPass == null || material == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (renderingData.cameraData.cameraType == CameraType.Preview || renderingData.cameraData.cameraType == CameraType.Reflection || UniversalRenderer.IsOffscreenDepthTexture(ref renderingData.cameraData))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (renderingData.cameraData.cameraType != CameraType.Game && !(showInSceneView && renderingData.cameraData.cameraType == CameraType.SceneView))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var inputRequirements = ScriptableRenderPassInput.Depth;
|
||||
|
||||
if (mode == OutlineMode.DepthNormal)
|
||||
{
|
||||
inputRequirements |= ScriptableRenderPassInput.Normal;
|
||||
}
|
||||
|
||||
renderPass.ConfigureInput(inputRequirements);
|
||||
renderPass.requiresIntermediateTexture = true;
|
||||
renderPass.renderPassEvent = injectionPoint switch
|
||||
{
|
||||
InjectionPoint.BeforeRenderingTransparents => RenderPassEvent.BeforeRenderingTransparents,
|
||||
InjectionPoint.BeforeRenderingPostProcessing => RenderPassEvent.BeforeRenderingPostProcessing,
|
||||
_ => RenderPassEvent.BeforeRenderingTransparents,
|
||||
};
|
||||
|
||||
renderPass.Setup(material, new Settings()
|
||||
{
|
||||
Mode = mode,
|
||||
ReferenceHeight = referenceHeight,
|
||||
ScaleWithResolution = scaleWithResolution
|
||||
});
|
||||
|
||||
renderer.EnqueuePass(renderPass);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
CoreUtils.Destroy(material);
|
||||
renderPass = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user