升级水插件

This commit is contained in:
2026-01-08 22:30:55 +08:00
parent febff82d24
commit ca68084264
415 changed files with 18138 additions and 7134 deletions

View File

@@ -1,161 +1,94 @@
// Crest Water System
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
namespace WaveHarmonic.Crest
{
// Built-in Render Pipeline
partial class WaterRenderer
{
internal const string k_DrawWater = "Crest.DrawWater";
internal const string k_DrawCopyColor = "CopyColor";
internal const string k_DrawCopyDepth = "CopyDepth";
partial class ShaderIDs
{
public static readonly int s_CameraOpaqueTexture = Shader.PropertyToID("_CameraOpaqueTexture");
public static readonly int s_ShadowMapTexture = Shader.PropertyToID("_ShadowMapTexture");
public static readonly int s_ScreenSpaceShadowTexture = Shader.PropertyToID("_Crest_ScreenSpaceShadowTexture");
public static readonly int s_TemporaryDepthTexture = Shader.PropertyToID("_Crest_TemporaryDepthTexture");
public static readonly int s_PrimaryLightHasCookie = Shader.PropertyToID("g_Crest_PrimaryLightHasCookie");
public static class Unity
{
public static readonly int s_CameraOpaqueTexture = Shader.PropertyToID("_CameraOpaqueTexture");
}
}
CommandBuffer _CopyColorTextureBuffer;
RenderTexture _CameraColorTexture;
bool _DoneMatrices;
CommandBuffer _ScreenSpaceShadowMapBuffer;
CommandBuffer _DeferredShadowMapBuffer;
CommandBuffer _UpdateColorDepthTexturesBuffer;
internal DefaultFormat LikelyFrameBufferFormat
internal Rendering.BIRP.FrameBufferFormatOverride FrameBufferFormatOverride =>
!_OverrideRenderHDR
? Rendering.BIRP.FrameBufferFormatOverride.None
: _RenderHDR
? Rendering.BIRP.FrameBufferFormatOverride.HDR
: Rendering.BIRP.FrameBufferFormatOverride.LDR;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void InitializeOnLoad()
{
get
{
if (_OverrideRenderHDR)
{
return _RenderHDR ? DefaultFormat.HDR : DefaultFormat.LDR;
}
#if UNITY_EDITOR
var target = UnityEditor.EditorUserBuildSettings.activeBuildTarget;
if (target is UnityEditor.BuildTarget.Android or UnityEditor.BuildTarget.iOS or UnityEditor.BuildTarget.tvOS)
{
return DefaultFormat.LDR;
}
#endif
#if UNITY_ANDROID || UNITY_IOS || UNITY_TVOS
return DefaultFormat.LDR;
#else
return DefaultFormat.HDR;
#endif
}
// Fixes error on first frame.
Shader.SetGlobalTexture(Crest.ShaderIDs.Unity.s_ShadowMapTexture, Texture2D.whiteTexture);
}
void OnPreRenderCamera(Camera camera)
internal void UpdateMatrices(Camera camera)
{
#if UNITY_EDITOR
UpdateLastActiveSceneCamera(camera);
if (!Application.isPlaying)
{
OnPreRenderWaterLevelDepthTexture(camera);
}
#endif
OnBeginCameraRendering(camera);
if (!Helpers.MaskIncludesLayer(camera.cullingMask, Layer))
if (_DoneMatrices)
{
return;
}
XRHelpers.Update(camera);
XRHelpers.SetInverseViewProjectionMatrix(camera);
Rendering.BIRP.SetMatrices(camera);
_CopyColorTextureBuffer ??= new() { name = "Crest Copy Color Texture" };
_DeferredShadowMapBuffer ??= new() { name = "Crest Deferred Shadow Data" };
_ScreenSpaceShadowMapBuffer ??= new() { name = "Crest Screen-Space Shadow Data" };
_CopyColorTextureBuffer.Clear();
_DeferredShadowMapBuffer.Clear();
_ScreenSpaceShadowMapBuffer.Clear();
_DoneMatrices = true;
}
// Create or update RT.
void OnBeginCameraRenderingLegacy(Camera camera)
{
if (PrimaryLight == null)
{
var descriptor = XRHelpers.GetRenderTextureDescriptor(camera);
// Format must be correct for CopyTexture to work. Hopefully this is good enough.
if (camera.allowHDR && QualitySettings.activeColorSpace == ColorSpace.Linear)
{
descriptor.graphicsFormat = SystemInfo.GetGraphicsFormat(LikelyFrameBufferFormat);
}
// Occurred in a build and caused a black screen.
if (descriptor.width <= 0)
{
return;
}
if (_CameraColorTexture == null)
{
_CameraColorTexture = new(descriptor);
}
else
{
_CameraColorTexture.Release();
_CameraColorTexture.descriptor = descriptor;
}
_CameraColorTexture.Create();
return;
}
var target = new RenderTargetIdentifier(_CameraColorTexture, 0, CubemapFace.Unknown, -1);
// Use blit instead of CopyTexture as it will smooth out issues with format
// differences which is very hard to get right for BIRP.
_CopyColorTextureBuffer.Blit(BuiltinRenderTextureType.CameraTarget, target);
_CopyColorTextureBuffer.SetGlobalTexture(ShaderIDs.s_CameraOpaqueTexture, _CameraColorTexture);
camera.AddCommandBuffer(CameraEvent.BeforeForwardAlpha, _CopyColorTextureBuffer);
if (QualitySettings.shadows != ShadowQuality.Disable && PrimaryLight != null)
// Force shadow map to remain for transparent pass and beyond.
{
_ScreenSpaceShadowMapBuffer ??= new() { name = "Crest.CausticsOcclusion" };
_ScreenSpaceShadowMapBuffer.Clear();
// Make the screen-space shadow texture available for the water shader for caustic occlusion.
_ScreenSpaceShadowMapBuffer.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, BuiltinRenderTextureType.CurrentActive);
PrimaryLight.AddCommandBuffer(LightEvent.AfterScreenspaceMask, _ScreenSpaceShadowMapBuffer);
// Call this regardless of rendering path as it has no negative consequences for forward.
_DeferredShadowMapBuffer.SetGlobalTexture(ShaderIDs.s_ShadowMapTexture, BuiltinRenderTextureType.CurrentActive);
PrimaryLight.AddCommandBuffer(LightEvent.AfterShadowMap, _DeferredShadowMapBuffer);
}
{
// Always set these in case shadow maps are disabled in the graphics settings which
// we cannot check at runtime.
// Black for shadowed. White for unshadowed.
if (camera.stereoEnabled && XRHelpers.IsSinglePass)
{
Shader.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, XRHelpers.WhiteTexture);
}
else
{
Shader.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, Texture2D.whiteTexture);
}
Shader.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, Rendering.BIRP.GetWhiteTexture(camera));
}
Helpers.SetGlobalBoolean(ShaderIDs.s_PrimaryLightHasCookie, PrimaryLight.cookie != null);
}
void OnPostRenderCamera(Camera camera)
void OnEndCameraRenderingLegacy(Camera camera)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
OnPostRenderWaterLevelDepthTexture(camera);
}
#endif
_DoneMatrices = false;
_DoneCameraOpaqueTexture = false;
if (!Helpers.MaskIncludesLayer(camera.cullingMask, Layer))
if (_UpdateColorDepthTexturesBuffer != null)
{
return;
}
if (_CopyColorTextureBuffer != null)
{
camera.RemoveCommandBuffer(CameraEvent.BeforeForwardAlpha, _CopyColorTextureBuffer);
camera.RemoveCommandBuffer(RenderBeforeTransparency ? CameraEvent.BeforeForwardAlpha : CameraEvent.AfterForwardAlpha, _UpdateColorDepthTexturesBuffer);
}
if (QualitySettings.shadows != ShadowQuality.Disable && PrimaryLight != null)
@@ -164,11 +97,153 @@ namespace WaveHarmonic.Crest
{
PrimaryLight.RemoveCommandBuffer(LightEvent.AfterScreenspaceMask, _ScreenSpaceShadowMapBuffer);
}
}
if (_DeferredShadowMapBuffer != null)
Shader.SetGlobalTexture(ShaderIDs.Unity.s_CameraOpaqueTexture, Texture2D.grayTexture);
}
// Needs to be separate, as it needs to run after the water volume pass.
void OnLegacyCopyPass(Camera camera)
{
if (!ShouldRender(camera, Surface.Layer))
{
return;
}
if (Surface.Material == null)
{
return;
}
if (!SurfaceRenderer.IsTransparent(Surface.Material))
{
return;
}
// Our reflections do not need them.
if (camera == WaterReflections.CurrentCamera)
{
return;
}
_UpdateColorDepthTexturesBuffer ??= new() { name = k_DrawWater };
_UpdateColorDepthTexturesBuffer.Clear();
var buffer = _UpdateColorDepthTexturesBuffer;
if (WriteToColorTexture)
{
UpdateCameraOpaqueTexture(camera, buffer);
}
if (WriteToDepthTexture && Shader.GetGlobalTexture(Crest.ShaderIDs.Unity.s_CameraDepthTexture) is RenderTexture depthRT)
{
buffer.BeginSample(k_DrawCopyDepth);
// There is no way to update the depth texture with the depth buffer, as we cannot
// get a reference to it. We have to render water depth separately and then merge
// the results.
var target = new RenderTargetIdentifier(depthRT, 0, CubemapFace.Unknown, -1);
var id = ShaderIDs.s_TemporaryDepthTexture;
buffer.GetTemporaryRT(id, depthRT.descriptor);
CoreUtils.SetRenderTarget(buffer, id, ClearFlag.Depth);
Surface.Render(camera, buffer, pass: Surface.Material.FindPass("DepthOnly"), culled: true);
buffer.SetGlobalTexture(Helpers.ShaderIDs.s_MainTexture, id);
Helpers.Blit(buffer, target, Rendering.BIRP.UtilityMaterial, (int)Rendering.BIRP.UtilityPass.MergeDepth);
// TODO: add debug toggle
// buffer.Blit(target, BuiltinRenderTextureType.CameraTarget);
buffer.ReleaseTemporaryRT(id);
buffer.EndSample(k_DrawCopyDepth);
}
if (WriteToColorTexture || WriteToDepthTexture)
{
camera.AddCommandBuffer(RenderBeforeTransparency ? CameraEvent.BeforeForwardAlpha : CameraEvent.AfterForwardAlpha, buffer);
}
}
}
// Camera Opaque Texture.
partial class WaterRenderer
{
bool _DoneCameraOpaqueTexture;
RenderTexture _CameraOpaqueTexture;
CommandBuffer _CameraOpaqueTextureCommands;
internal void UpdateCameraOpaqueTexture(Camera camera, CommandBuffer commands)
{
commands.BeginSample(k_DrawCopyColor);
var target = new RenderTargetIdentifier(_CameraOpaqueTexture, 0, CubemapFace.Unknown, -1);
// Use blit instead of CopyTexture as it will smooth out issues with format
// differences which is very hard to get right for BIRP.
commands.Blit(BuiltinRenderTextureType.CameraTarget, target);
commands.EndSample(k_DrawCopyColor);
}
internal void OnBeginCameraOpaqueTexture(Camera camera)
{
if (_DoneCameraOpaqueTexture)
{
return;
}
var descriptor = Rendering.BIRP.GetCameraTargetDescriptor(camera, FrameBufferFormatOverride);
// Occurred in a build and caused a black screen.
if (descriptor.width <= 0)
{
return;
}
if (_CameraOpaqueTexture == null)
{
_CameraOpaqueTexture = new(descriptor)
{
PrimaryLight.RemoveCommandBuffer(LightEvent.AfterShadowMap, _DeferredShadowMapBuffer);
}
name = "_CameraOpaqueTexture",
};
}
else
{
_CameraOpaqueTexture.Release();
_CameraOpaqueTexture.descriptor = descriptor;
}
_CameraOpaqueTexture.Create();
_CameraOpaqueTextureCommands ??= new()
{
name = "Crest.DrawWater",
};
_CameraOpaqueTextureCommands.Clear();
// Do every frame as we set to default texture at end of rendering.
_CameraOpaqueTextureCommands.SetGlobalTexture(Crest.ShaderIDs.Unity.s_CameraOpaqueTexture, _CameraOpaqueTexture);
UpdateCameraOpaqueTexture(camera, _CameraOpaqueTextureCommands);
camera.AddCommandBuffer(CameraEvent.BeforeForwardAlpha, _CameraOpaqueTextureCommands);
_DoneCameraOpaqueTexture = true;
}
internal void OnEndCameraOpaqueTexture(Camera camera)
{
if (_CameraOpaqueTextureCommands != null)
{
camera.RemoveCommandBuffer(CameraEvent.BeforeForwardAlpha, _CameraOpaqueTextureCommands);
}
}
}