OldBlueWater/BlueWater/Assets/Quibli/Post Process/Effects/Scripts/StylizedDetail.cs
2023-08-02 18:12:26 +09:00

114 lines
5.7 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.Universal.PostProcessing;
namespace CompoundRendererFeature.PostProcess {
[Serializable, VolumeComponentMenu("Quibli/Stylized Detail")]
public class StylizedDetail : VolumeComponent {
[Tooltip("Controls the amount of contrast added to the image details.")]
public ClampedFloatParameter intensity = new ClampedFloatParameter(0f, 0f, 3f, true);
[Tooltip("Controls smoothing amount.")]
public ClampedFloatParameter blur = new ClampedFloatParameter(1f, 0, 2, true);
[Tooltip("Controls structure within the image.")]
public ClampedFloatParameter edgePreserve = new ClampedFloatParameter(1.25f, 0, 2, true);
[Tooltip("The distance from the camera at which the effect starts."), Space]
public MinFloatParameter rangeStart = new MinFloatParameter(10f, 0f);
[Tooltip("The distance from the camera at which the effect reaches its maximum radius.")]
public MinFloatParameter rangeEnd = new MinFloatParameter(30f, 0f);
}
[CompoundRendererFeature("Stylized Detail", InjectionPoint.BeforePostProcess)]
public class StylizedDetailRenderer : CompoundRenderer {
private StylizedDetail _volumeComponent;
private Material _effectMaterial;
static class PropertyIDs {
internal static readonly int Input = Shader.PropertyToID("_MainTex");
internal static readonly int PingTexture = Shader.PropertyToID("_PingTexture");
internal static readonly int BlurStrength = Shader.PropertyToID("_BlurStrength");
internal static readonly int Blur1 = Shader.PropertyToID("_BlurTex1");
internal static readonly int Blur2 = Shader.PropertyToID("_BlurTex2");
internal static readonly int Intensity = Shader.PropertyToID("_Intensity");
internal static readonly int DownSampleScaleFactor = Shader.PropertyToID("_DownSampleScaleFactor");
public static readonly int CoCParams = Shader.PropertyToID("_CoCParams");
}
public override ScriptableRenderPassInput input =>
ScriptableRenderPassInput.Color | ScriptableRenderPassInput.Depth;
// Called only once before the first render call.
public override void Initialize() {
base.Initialize();
_effectMaterial = CoreUtils.CreateEngineMaterial("Hidden/CompoundRendererFeature/StylizedDetail");
}
// Called for each camera/injection point pair on each frame.
// Return true if the effect should be rendered for this camera.
public override bool Setup(in RenderingData renderingData, InjectionPoint injectionPoint) {
base.Setup(in renderingData, injectionPoint);
var stack = VolumeManager.instance.stack;
_volumeComponent = stack.GetComponent<StylizedDetail>();
bool shouldRenderEffect = _volumeComponent.intensity.value > 0;
return shouldRenderEffect;
}
public override void Render(CommandBuffer cmd, RTHandle source, RTHandle destination,
ref RenderingData renderingData, InjectionPoint injectionPoint) {
const int downSample = 1;
RenderTextureDescriptor descriptor = GetTempRTDescriptor(renderingData);
int wh = descriptor.width / downSample;
int hh = descriptor.height / downSample;
// Assumes a radius of 1 is 1 at 1080p. Past a certain radius our gaussian kernel will look very bad so we'll
// clamp it for very high resolutions (4K+).
float blurRadius = _volumeComponent.blur.value * (wh / 1080f);
blurRadius = Mathf.Min(blurRadius, 2f);
float edgePreserve = _volumeComponent.edgePreserve.value * (wh / 1080f);
edgePreserve = Mathf.Min(edgePreserve, 2f);
var rangeStart = _volumeComponent.rangeStart.overrideState ? _volumeComponent.rangeStart.value : 0;
var rangeEnd = _volumeComponent.rangeEnd.overrideState ? _volumeComponent.rangeEnd.value : -1;
_effectMaterial.SetVector(PropertyIDs.CoCParams, new Vector2(rangeStart, rangeEnd));
_effectMaterial.SetFloat(PropertyIDs.Intensity, _volumeComponent.intensity.value);
SetSourceSize(cmd, descriptor);
var tempRtDescriptor = GetTempRTDescriptor(renderingData, wh, hh, _defaultHDRFormat);
cmd.GetTemporaryRT(PropertyIDs.PingTexture, tempRtDescriptor, FilterMode.Bilinear);
cmd.GetTemporaryRT(PropertyIDs.Blur1, tempRtDescriptor, FilterMode.Bilinear);
cmd.GetTemporaryRT(PropertyIDs.Blur2, tempRtDescriptor, FilterMode.Bilinear);
cmd.SetGlobalVector(PropertyIDs.DownSampleScaleFactor,
new Vector4(1.0f / downSample, 1.0f / downSample, downSample, downSample));
cmd.SetGlobalFloat(PropertyIDs.BlurStrength, edgePreserve);
cmd.SetGlobalTexture(PropertyIDs.Input, source);
CoreUtils.DrawFullScreen(cmd, _effectMaterial, PropertyIDs.PingTexture, null, 1);
cmd.SetGlobalTexture(PropertyIDs.Input, PropertyIDs.PingTexture);
CoreUtils.DrawFullScreen(cmd, _effectMaterial, PropertyIDs.Blur1, null, 2);
cmd.SetGlobalFloat(PropertyIDs.BlurStrength, blurRadius);
cmd.SetGlobalTexture(PropertyIDs.Input, PropertyIDs.Blur1);
CoreUtils.DrawFullScreen(cmd, _effectMaterial, PropertyIDs.PingTexture, null, 1);
cmd.SetGlobalTexture(PropertyIDs.Input, PropertyIDs.PingTexture);
CoreUtils.DrawFullScreen(cmd, _effectMaterial, PropertyIDs.Blur2, null, 2);
cmd.SetGlobalTexture(PropertyIDs.Input, source);
CoreUtils.DrawFullScreen(cmd, _effectMaterial, destination, null, 0);
cmd.ReleaseTemporaryRT(PropertyIDs.PingTexture);
cmd.ReleaseTemporaryRT(PropertyIDs.Blur1);
cmd.ReleaseTemporaryRT(PropertyIDs.Blur2);
}
public override void Dispose(bool disposing) { }
}
}