Files
Fishing2/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPass.cs
2025-05-10 12:49:47 +08:00

141 lines
4.6 KiB
C#

// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
namespace WaveHarmonic.Crest
{
sealed class UnderwaterMaskPass
{
readonly UnderwaterRenderer _Renderer;
#if d_CrestPortals
readonly Portals.PortalRenderer _Portals;
#endif
RTHandle _MaskTexture;
RTHandle _DepthTexture;
RenderTargetIdentifier _MaskTarget;
RenderTargetIdentifier _DepthTarget;
public UnderwaterMaskPass(UnderwaterRenderer renderer)
{
_Renderer = renderer;
#if d_CrestPortals
_Portals = renderer._Portals;
#endif
}
public void Allocate()
{
_MaskTexture = RTHandles.Alloc
(
scaleFactor: Vector2.one,
slices: TextureXR.slices,
dimension: TextureXR.dimension,
depthBufferBits: DepthBits.None,
colorFormat: GraphicsFormat.R16_SFloat,
enableRandomWrite: true,
useDynamicScale: true,
name: "_Crest_WaterMask"
);
_MaskTarget = new(_MaskTexture, mipLevel: 0, CubemapFace.Unknown, depthSlice: -1);
_DepthTexture = RTHandles.Alloc
(
scaleFactor: Vector2.one,
slices: TextureXR.slices,
dimension: TextureXR.dimension,
depthBufferBits: UnderwaterRenderer.k_DepthBits,
colorFormat: GraphicsFormat.None,
enableRandomWrite: false,
useDynamicScale: true,
name: "_Crest_WaterMaskDepth"
);
#if d_CrestPortals
// For HDRP we cannot allocate in OnEnable as RTHandle will complain.
if (_Portals.Active)
{
_Portals.Allocate();
}
#endif
_DepthTarget = new(_DepthTexture, mipLevel: 0, CubemapFace.Unknown, depthSlice: -1);
_Renderer.SetUpArtifactsShader();
}
// We should not have to reallocate, but URP will raise errors when an option like HDR is changed if we do not.
public void ReAllocate(RenderTextureDescriptor descriptor)
{
// Shared settings. Enabling MSAA might be a good idea except cannot enable random writes. Having a raster
// shader to remove artifacts is a workaround.
descriptor.bindMS = false;
descriptor.msaaSamples = 1;
descriptor.graphicsFormat = GraphicsFormat.None;
if (RenderPipelineCompatibilityHelper.ReAllocateIfNeeded(ref _DepthTexture, descriptor, name: "_Crest_WaterMaskDepth"))
{
_DepthTarget = new(_DepthTexture, mipLevel: 0, CubemapFace.Unknown, depthSlice: -1);
}
#if d_CrestPortals
if (_Portals.Active)
{
_Portals.ReAllocate(descriptor);
}
#endif
descriptor.graphicsFormat = GraphicsFormat.R16_SFloat;
descriptor.enableRandomWrite = true;
descriptor.depthBufferBits = 0;
if (RenderPipelineCompatibilityHelper.ReAllocateIfNeeded(ref _MaskTexture, descriptor, name: "_Crest_WaterMask"))
{
_MaskTarget = new(_MaskTexture, mipLevel: 0, CubemapFace.Unknown, depthSlice: -1);
}
}
public void Release()
{
_MaskTexture?.Release();
_DepthTexture?.Release();
#if d_CrestPortals
if (_Portals.Active)
{
_Portals.Release();
}
#endif
}
public void Execute(Camera camera, CommandBuffer buffer)
{
#if d_CrestPortals
// Populate water volume before mask so we can use the stencil.
if (_Portals.Active)
{
_Portals.RenderMask(camera, buffer, _Renderer._MaskMaterial);
_Portals.RenderStencil(buffer, _DepthTexture);
}
#endif
// For HDRP software dynamic scaling to work.
CoreUtils.SetRenderTarget(buffer, _MaskTexture, _DepthTexture);
Helpers.ScaleViewport(camera, buffer, _MaskTexture);
_Renderer.SetUpMask(buffer, _MaskTarget, _DepthTarget);
_Renderer.PopulateMask(buffer, camera);
var size = _MaskTexture.GetScaledSize(_MaskTexture.rtHandleProperties.currentViewportSize);
var descriptor = _MaskTexture.rt.descriptor;
descriptor.width = size.x; descriptor.height = size.y;
_Renderer.FixMaskArtefacts(buffer, descriptor, _MaskTarget);
}
}
}