221 lines
7.5 KiB
C#
221 lines
7.5 KiB
C#
// Crest Water System
|
|
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
|
|
|
#if d_UnityURP
|
|
|
|
using UnityEngine;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Rendering.Universal;
|
|
|
|
namespace WaveHarmonic.Crest
|
|
{
|
|
sealed partial class UnderwaterEffectPassURP : ScriptableRenderPass
|
|
{
|
|
const string k_Name = "Crest.DrawWater/Volume";
|
|
|
|
UnderwaterRenderer _Renderer;
|
|
|
|
internal static UnderwaterEffectPassURP s_Instance;
|
|
UnderwaterEffectPass _UnderwaterEffectPass;
|
|
CopyDepthBufferPassURP _CopyDepthBufferPass;
|
|
|
|
RTHandle _ColorBuffer;
|
|
RTHandle _DepthBuffer;
|
|
|
|
public UnderwaterEffectPassURP()
|
|
{
|
|
ConfigureInput(ScriptableRenderPassInput.Color | ScriptableRenderPassInput.Depth);
|
|
}
|
|
|
|
public static void Enable(UnderwaterRenderer renderer)
|
|
{
|
|
if (s_Instance == null)
|
|
{
|
|
s_Instance = new();
|
|
s_Instance._Renderer = renderer;
|
|
s_Instance._CopyDepthBufferPass = new(RenderPassEvent.AfterRenderingOpaques);
|
|
}
|
|
|
|
RenderPipelineManager.activeRenderPipelineTypeChanged -= Disable;
|
|
RenderPipelineManager.activeRenderPipelineTypeChanged += Disable;
|
|
}
|
|
|
|
public static void Disable()
|
|
{
|
|
RenderPipelineManager.activeRenderPipelineTypeChanged -= Disable;
|
|
|
|
s_Instance?._UnderwaterEffectPass?.Release();
|
|
s_Instance?._CopyDepthBufferPass?.Release();
|
|
s_Instance = null;
|
|
}
|
|
|
|
internal void EnqueuePass(ScriptableRenderContext context, Camera camera)
|
|
{
|
|
if (!_Renderer.ShouldRender(camera, UnderwaterRenderer.Pass.Effect))
|
|
{
|
|
return;
|
|
}
|
|
|
|
s_Instance.renderPassEvent = _Renderer.RenderBeforeTransparency ? WaterRenderer.k_WaterRenderPassEvent : RenderPassEvent.AfterRenderingTransparents;
|
|
|
|
var renderer = camera.GetUniversalAdditionalCameraData().scriptableRenderer;
|
|
|
|
#if UNITY_EDITOR
|
|
if (renderer == null) return;
|
|
#endif
|
|
|
|
// Copy the depth buffer to create a new depth/stencil context.
|
|
if (_Renderer.UseStencilBuffer)
|
|
{
|
|
renderer.EnqueuePass(_CopyDepthBufferPass);
|
|
}
|
|
|
|
// Set up internal pass which houses shared code for SRPs.
|
|
_UnderwaterEffectPass ??= new(_Renderer);
|
|
|
|
renderer.EnqueuePass(s_Instance);
|
|
}
|
|
|
|
#if UNITY_6000_0_OR_NEWER
|
|
bool _ErrorMissingColorTarget;
|
|
|
|
void OnSetup(CommandBuffer buffer, RenderGraphHelper.PassData data)
|
|
{
|
|
_ColorBuffer = data.colorTargetHandle.Texture;
|
|
_DepthBuffer = data.depthTargetHandle.Texture;
|
|
|
|
// Unity bug
|
|
if (_ColorBuffer?.rt == null)
|
|
{
|
|
if (!_ErrorMissingColorTarget)
|
|
{
|
|
Debug.LogError($"Crest: Your current URP setup has a Unity bug which prevents underwater from rendering on this camera ({data.cameraData.camera.name}). It is too complicated for us to advise which combination of settings are the issue (sorry), but they will be on either the URP asset or renderer file.");
|
|
_ErrorMissingColorTarget = true;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// TODO: renderingData.cameraData.cameraTargetDescriptor?
|
|
_UnderwaterEffectPass.ReAllocate(_ColorBuffer.rt.descriptor);
|
|
}
|
|
|
|
void Execute(ScriptableRenderContext context, CommandBuffer buffer, RenderGraphHelper.PassData data)
|
|
{
|
|
// Unity bug
|
|
if (_ColorBuffer?.rt == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (_Renderer.UseStencilBuffer)
|
|
{
|
|
_DepthBuffer = _CopyDepthBufferPass._DepthBufferCopy;
|
|
}
|
|
|
|
_UnderwaterEffectPass.Execute(data.cameraData.camera, buffer, _ColorBuffer, _DepthBuffer);
|
|
}
|
|
#else
|
|
public override void OnCameraSetup(CommandBuffer buffer, ref RenderingData data)
|
|
{
|
|
_ColorBuffer = data.cameraData.renderer.cameraColorTargetHandle;
|
|
_DepthBuffer = data.cameraData.renderer.cameraDepthTargetHandle;
|
|
|
|
// TODO: renderingData.cameraData.cameraTargetDescriptor?
|
|
_UnderwaterEffectPass.ReAllocate(_ColorBuffer.rt.descriptor);
|
|
}
|
|
|
|
public override void Execute(ScriptableRenderContext context, ref RenderingData data)
|
|
{
|
|
var buffer = CommandBufferPool.Get(k_Name);
|
|
|
|
if (_Renderer.UseStencilBuffer)
|
|
{
|
|
_DepthBuffer = _CopyDepthBufferPass._DepthBufferCopy;
|
|
}
|
|
|
|
_UnderwaterEffectPass.Execute(data.cameraData.camera, buffer, _ColorBuffer, _DepthBuffer);
|
|
|
|
context.ExecuteCommandBuffer(buffer);
|
|
CommandBufferPool.Release(buffer);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// Copies the depth buffer to avoid conflicts when using the stencil buffer.
|
|
sealed partial class CopyDepthBufferPassURP : ScriptableRenderPass
|
|
{
|
|
const string k_Name = "Crest Copy Depth Buffer";
|
|
RTHandle _ColorBuffer;
|
|
RTHandle _DepthBuffer;
|
|
public RTHandle _DepthBufferCopy;
|
|
|
|
public CopyDepthBufferPassURP(RenderPassEvent @event)
|
|
{
|
|
renderPassEvent = @event;
|
|
}
|
|
|
|
#if UNITY_6000_0_OR_NEWER
|
|
void OnSetup(CommandBuffer buffer, PassData data)
|
|
#else
|
|
public override void OnCameraSetup(CommandBuffer buffer, ref RenderingData data)
|
|
#endif
|
|
{
|
|
var descriptor = data.cameraData.cameraTargetDescriptor;
|
|
descriptor.graphicsFormat = GraphicsFormat.None;
|
|
descriptor.bindMS = descriptor.msaaSamples > 1;
|
|
#if UNITY_6000_0_OR_NEWER
|
|
RenderingUtils.ReAllocateHandleIfNeeded(ref _DepthBufferCopy, descriptor, FilterMode.Point, name: "Crest Copied Depth Buffer");
|
|
_ColorBuffer = data.colorTargetHandle;
|
|
_DepthBuffer = data.depthTargetHandle;
|
|
#else
|
|
RenderingUtils.ReAllocateIfNeeded(ref _DepthBufferCopy, descriptor, FilterMode.Point, name: "Crest Copied Depth Buffer");
|
|
_ColorBuffer = data.cameraData.renderer.cameraColorTargetHandle;
|
|
_DepthBuffer = data.cameraData.renderer.cameraDepthTargetHandle;
|
|
#endif
|
|
}
|
|
|
|
#if UNITY_6000_0_OR_NEWER
|
|
void Execute(ScriptableRenderContext context, CommandBuffer buffer, PassData data)
|
|
#else
|
|
public override void Execute(ScriptableRenderContext context, ref RenderingData data)
|
|
#endif
|
|
{
|
|
// Just in case.
|
|
if (_ColorBuffer == null || _DepthBuffer == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#if !UNITY_6000_0_OR_NEWER
|
|
var buffer = CommandBufferPool.Get(k_Name);
|
|
#endif
|
|
|
|
// NOTE: previously we cleared the target depth first due to artifacts.
|
|
buffer.CopyTexture(_DepthBuffer.rt, _DepthBufferCopy.rt);
|
|
|
|
// Clear the stencil component just in case.
|
|
// Previously we passed BuiltinRenderTextureType.None for color but this made the
|
|
// scene disappear in the scene view on DX11 only.
|
|
CoreUtils.SetRenderTarget(buffer, _ColorBuffer, _DepthBufferCopy, ClearFlag.Stencil);
|
|
|
|
// Required for Unity 6+.
|
|
CoreUtils.SetRenderTarget(buffer, _ColorBuffer, _DepthBuffer);
|
|
|
|
#if !UNITY_6000_0_OR_NEWER
|
|
context.ExecuteCommandBuffer(buffer);
|
|
CommandBufferPool.Release(buffer);
|
|
#endif
|
|
}
|
|
|
|
public void Release()
|
|
{
|
|
_DepthBuffer = null;
|
|
_DepthBufferCopy?.Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // d_UnityURP
|