Files
Fishing2/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassHDRP.cs
2026-01-08 22:30:55 +08:00

158 lines
5.8 KiB
C#

// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#if d_UnityHDRP
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
namespace WaveHarmonic.Crest
{
sealed class UnderwaterEffectPassHDRP : CustomPass
{
const string k_Name = "Underwater Effect";
static UnderwaterRenderer s_Renderer;
static UnderwaterEffectPass s_UnderwaterEffectPass;
internal static UnderwaterEffectPassHDRP s_Instance;
static CopyDepthBufferPassHDRP s_CopyDepthBufferPassHDRP;
static ShaderTagId[] s_ForwardShaderTags;
public static void Enable(UnderwaterRenderer renderer)
{
var gameObject = CustomPassHelpers.CreateOrUpdate
(
parent: renderer._Water.Container.transform,
k_Name,
hide: !renderer._Water._Debug._ShowHiddenObjects
);
CustomPassHelpers.CreateOrUpdate
(
gameObject,
ref s_CopyDepthBufferPassHDRP,
UnderwaterRenderer.k_DrawVolume,
CustomPassInjectionPoint.AfterOpaqueDepthAndNormal
);
var isBeforeTransparentPass = renderer.RenderBeforeTransparency;
CustomPassHelpers.CreateOrUpdate
(
gameObject,
ref s_Instance,
UnderwaterRenderer.k_DrawVolume,
GetInjectionPoint(isBeforeTransparentPass),
// Higher number (priority) means execute earlier. Volume executes first.
priority: 1
);
s_Renderer = renderer;
s_UnderwaterEffectPass = new(renderer);
}
public static void Disable()
{
// It should be safe to rely on this reference for this reference to fail.
if (s_Instance != null && s_Instance._GameObject != null)
{
// Will also trigger Cleanup below.
s_Instance._GameObject.SetActive(false);
}
}
static CustomPassInjectionPoint GetInjectionPoint(bool isBeforeTransparentPass)
{
return isBeforeTransparentPass
? CustomPassInjectionPoint.BeforeTransparent
: CustomPassInjectionPoint.BeforePostProcess;
}
internal void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
{
s_CopyDepthBufferPassHDRP.enabled = s_Renderer.UseStencilBuffer;
s_Instance._Volume.injectionPoint = GetInjectionPoint(s_Renderer.RenderBeforeTransparency);
}
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
{
var asset = GraphicsSettings.currentRenderPipeline as HDRenderPipelineAsset;
// Developers have a choice with the color buffer format. There is also a custom buffer buffer format but
// that is not relevant here. This will not cover the format change when scene filtering as Setup/Cleanup is
// not executed for this change.
s_UnderwaterEffectPass.Allocate((GraphicsFormat)asset.currentPlatformRenderPipelineSettings.colorBufferFormat);
// Taken from:
// https://github.com/Unity-Technologies/Graphics/blob/778ddac6207ade1689999b95380cd835b0669f2d/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/DrawRenderersCustomPass.cs#L136-L142
s_ForwardShaderTags ??= new[]
{
HDShaderPassNames.s_ForwardName, // HD Lit shader
HDShaderPassNames.s_ForwardOnlyName, // HD Unlit shader
HDShaderPassNames.s_SRPDefaultUnlitName, // Cross SRP Unlit shader
};
}
protected override void Cleanup()
{
s_UnderwaterEffectPass?.Release();
}
protected override void Execute(CustomPassContext context)
{
var camera = context.hdCamera.camera;
if (!s_Renderer.ShouldRender(camera, UnderwaterRenderer.Pass.Effect))
{
return;
}
// Allocate here in case user changes options and we skipped allocation in Setup.
s_UnderwaterEffectPass.Allocate(context.cameraColorBuffer.rt.graphicsFormat);
// Create a separate stencil buffer context by using a depth buffer copy if needed.
var depthBuffer = s_Renderer.UseStencilBuffer
? s_CopyDepthBufferPassHDRP._DepthBufferCopy
: context.cameraDepthBuffer;
s_UnderwaterEffectPass.Execute(camera, context.cmd, context.cameraColorBuffer, depthBuffer, context.propertyBlock);
}
}
sealed class CopyDepthBufferPassHDRP : CustomPass
{
public RTHandle _DepthBufferCopy;
protected override void Execute(CustomPassContext context)
{
// Multiple cameras could have different settings.
RenderPipelineCompatibilityHelper.ReAllocateIfNeeded
(
ref _DepthBufferCopy,
context.cameraDepthBuffer.rt.descriptor,
FilterMode.Point,
name: "_Crest_UnderwaterCopiedDepthBuffer"
);
var buffer = context.cmd;
// NOTE: previously we cleared the target depth first due to artifacts.
buffer.CopyTexture(context.cameraDepthBuffer.rt, _DepthBufferCopy.rt);
// Clear the stencil component just in case.
CoreUtils.SetRenderTarget(buffer, BuiltinRenderTextureType.None, _DepthBufferCopy, ClearFlag.Stencil);
}
protected override void Cleanup()
{
_DepthBufferCopy?.Release();
_DepthBufferCopy = null;
}
}
}
#endif // d_UnityHDRP