升级6.4.升级水,升级天气

This commit is contained in:
2026-04-05 00:26:54 +08:00
parent 63bc9b5536
commit 5f7cbfb713
635 changed files with 34718 additions and 22567 deletions

View File

@@ -20,6 +20,9 @@ namespace WaveHarmonic.Crest
readonly System.Action<CommandBuffer> _CopyColorTexture;
readonly System.Action<CommandBuffer> _SetRenderTargetToBackBuffers;
bool _AllocatedColor;
GraphicsFormat _GraphicsFormat;
public UnderwaterEffectPass(UnderwaterRenderer renderer)
{
_Renderer = renderer;
@@ -40,7 +43,9 @@ namespace WaveHarmonic.Crest
public void Allocate(GraphicsFormat format)
{
if (_Renderer.RenderBeforeTransparency && !_Renderer._NeedsColorTexture)
_GraphicsFormat = format;
if (_Renderer.RenderBeforeTransparency && !_Renderer.NeedsColorTexture)
{
return;
}
@@ -57,11 +62,13 @@ namespace WaveHarmonic.Crest
wrapMode: TextureWrapMode.Clamp,
name: "_Crest_UnderwaterCameraColorTexture"
);
_AllocatedColor = true;
}
public void ReAllocate(RenderTextureDescriptor descriptor)
{
if (_Renderer.RenderBeforeTransparency && !_Renderer._NeedsColorTexture)
if (_Renderer.RenderBeforeTransparency && !_Renderer.NeedsColorTexture)
{
return;
}
@@ -83,8 +90,13 @@ namespace WaveHarmonic.Crest
_ColorTarget = color;
_DepthTarget = depth;
if (!_Renderer.RenderBeforeTransparency || _Renderer._NeedsColorTexture)
if (!_Renderer.RenderBeforeTransparency || _Renderer.NeedsColorTexture)
{
if (!_AllocatedColor)
{
Allocate(_GraphicsFormat);
}
buffer.SetGlobalTexture(UnderwaterRenderer.ShaderIDs.s_CameraColorTexture, _ColorTexture);
}

View File

@@ -105,7 +105,7 @@ namespace WaveHarmonic.Crest
{
var camera = context.hdCamera.camera;
if (!s_Renderer.ShouldRender(camera, UnderwaterRenderer.Pass.Effect))
if (!s_Renderer._Water._ActiveModules.HasFlag(WaterRenderer.ActiveModules.Volume))
{
return;
}

View File

@@ -30,6 +30,7 @@ namespace WaveHarmonic.Crest
}
}
#if URP_COMPATIBILITY_MODE
[System.Obsolete]
public override void OnCameraSetup(CommandBuffer buffer, ref RenderingData data)
{
@@ -46,6 +47,7 @@ namespace WaveHarmonic.Crest
context.ExecuteCommandBuffer(buffer);
CommandBufferPool.Release(buffer);
}
#endif
}
partial class CopyDepthBufferPassURP
@@ -63,6 +65,7 @@ namespace WaveHarmonic.Crest
var resources = frameData.Get<UniversalResourceData>();
cameraData = frameData.Get<UniversalCameraData>();
#if URP_COMPATIBILITY_MODE
if (builder == null)
{
#pragma warning disable CS0618 // Type or member is obsolete
@@ -71,6 +74,7 @@ namespace WaveHarmonic.Crest
#pragma warning restore CS0618 // Type or member is obsolete
}
else
#endif
{
// We need reset render targets to these before the next pass, but we do not read
// or write to the color target.
@@ -99,6 +103,7 @@ namespace WaveHarmonic.Crest
}
}
#if URP_COMPATIBILITY_MODE
[System.Obsolete]
public override void OnCameraSetup(CommandBuffer buffer, ref RenderingData data)
{
@@ -115,6 +120,7 @@ namespace WaveHarmonic.Crest
context.ExecuteCommandBuffer(buffer);
CommandBufferPool.Release(buffer);
}
#endif
}
}

View File

@@ -52,7 +52,7 @@ namespace WaveHarmonic.Crest
internal void EnqueuePass(ScriptableRenderContext context, Camera camera)
{
if (!_Renderer.ShouldRender(camera, UnderwaterRenderer.Pass.Effect))
if (!_Renderer._Water._ActiveModules.HasFlag(WaterRenderer.ActiveModules.Volume))
{
return;
}

View File

@@ -11,8 +11,13 @@ namespace WaveHarmonic.Crest
// Edit Mode.
partial class UnderwaterRenderer
{
static bool IsFogEnabledForEditorCamera(Camera camera)
internal bool ShouldRenderForSceneView(Camera camera)
{
if (GL.wireframe)
{
return false;
}
// Check if scene view has disabled fog rendering.
if (camera.cameraType == CameraType.SceneView)
{

View File

@@ -68,9 +68,6 @@ namespace WaveHarmonic.Crest
-1
);
// Requested the temporary color texture.
internal bool _NeedsColorTexture;
sealed class UnderwaterSphericalHarmonicsData
{
internal Color[] _AmbientLighting = new Color[1];
@@ -118,7 +115,7 @@ namespace WaveHarmonic.Crest
_EffectCommandBuffer.Clear();
if (!RenderBeforeTransparency || _NeedsColorTexture)
if (!RenderBeforeTransparency || NeedsColorTexture)
{
// No need to clear as Blit will overwrite everything.
_EffectCommandBuffer.GetTemporaryRT(ShaderIDs.s_CameraColorTexture, descriptor);
@@ -140,7 +137,7 @@ namespace WaveHarmonic.Crest
if (UseStencilBuffer)
{
descriptor.colorFormat = RenderTextureFormat.Depth;
descriptor.depthBufferBits = (int)Helpers.k_DepthBits;
descriptor.depthBufferBits = (int)Rendering.GetDefaultDepthBufferBits();
// bindMS is necessary in this case for depth.
descriptor.SetMSAASamples(camera);
descriptor.bindMS = descriptor.msaaSamples > 1;
@@ -176,7 +173,7 @@ namespace WaveHarmonic.Crest
ExecuteEffect(camera, _EffectCommandBuffer, _CopyColor, _SetRenderTargetToBackBuffers);
if (!RenderBeforeTransparency || _NeedsColorTexture)
if (!RenderBeforeTransparency || NeedsColorTexture)
{
_EffectCommandBuffer.ReleaseTemporaryRT(ShaderIDs.s_CameraColorTexture);
}
@@ -192,7 +189,7 @@ namespace WaveHarmonic.Crest
var isFullScreenRequired = true;
#if d_CrestPortals
if (_Portals.Active)
if (_Water._ActiveModules.HasFlag(WaterRenderer.ActiveModules.Portal))
{
isFullScreenRequired = _Portals.RenderEffect(camera, buffer, _VolumeMaterial, copyColor, resetRenderTargets, properties);
}
@@ -272,9 +269,9 @@ namespace WaveHarmonic.Crest
if (camera.cameraType != CameraType.Reflection)
{
// Skip work if camera is far enough below the surface.
var forceFullShader = !_Water.Surface.Enabled || (_Water._ViewerHeightAboveWaterPerCamera < -8f && !Portaled);
var forceFullShader = !_MaskRead || (_Water._PerCameraHeightReady && _Water._ViewerHeightAboveWaterPerCamera < -8f && !Portaled);
_VolumeMaterial.SetKeyword("d_Crest_NoMaskColor", forceFullShader);
_VolumeMaterial.SetKeyword("d_Crest_NoMaskDepth", !_Water.Surface.Enabled || RenderBeforeTransparency);
_VolumeMaterial.SetKeyword("d_Crest_NoMaskDepth", !_MaskRead || RenderBeforeTransparency);
}
// Compute ambient lighting SH.

View File

@@ -87,7 +87,7 @@ namespace WaveHarmonic.Crest
#if UNITY_EDITOR
// Only repaint, otherwise changes might persist.
if (Event.current.type != EventType.Repaint)
if (Event.current?.type != EventType.Repaint)
{
return;
}

View File

@@ -26,7 +26,7 @@ namespace WaveHarmonic.Crest
// Listening to OnPreCull. Camera must have underwater layer.
void OnBeforeLegacyRender(Camera camera)
{
if (ShouldRender(camera, Pass.Effect))
if (_Water._ActiveModules.HasFlag(WaterRenderer.ActiveModules.Volume))
{
_Water.UpdateMatrices(camera);

View File

@@ -90,10 +90,7 @@ namespace WaveHarmonic.Crest
FixMaskArtefacts(commands, descriptor, mask._ColorRTI);
}
// Portals have their own fitted to the portal bounds.
else
#if d_CrestPortals
if (!Portaled || _Water.Portals.RequiresFullScreenMask)
#endif
else if (RequiresFullScreenMask)
{
RenderLineMask(commands, camera, mask.ColorRT.descriptor, mask._ColorRTI);
}
@@ -109,7 +106,7 @@ namespace WaveHarmonic.Crest
var keep = false;
#if d_CrestPortals
if (_Water.Portals.Active)
if (_Water._ActiveModules.HasFlag(WaterRenderer.ActiveModules.Portal))
{
keep = _Water.Portals.RenderLineMask(buffer, target);
}
@@ -195,27 +192,25 @@ namespace WaveHarmonic.Crest
}
internal bool _MaskRead;
bool _DoneMaskRead;
MaskRenderer.MaskInput MaskRenderer.IMaskProvider.Allocate()
{
return MaskRenderer.MaskInput.Both;
return UseLegacyMask || UseStencilBuffer ? MaskRenderer.MaskInput.Both : MaskRenderer.MaskInput.Color;
}
MaskRenderer.MaskInput MaskRenderer.IMaskReceiver.Allocate()
{
return MaskRenderer.MaskInput.Both;
return UseLegacyMask || UseStencilBuffer ? MaskRenderer.MaskInput.Both : MaskRenderer.MaskInput.Color;
}
MaskRenderer.MaskInput MaskRenderer.IMaskProvider.Write(Camera camera)
{
if (!_DoneMaskRead)
{
_MaskRead = ShouldRender(camera, Pass.Mask);
_DoneMaskRead = true;
}
_MaskRead = _Water._ActiveModules.HasFlag(WaterRenderer.ActiveModules.SurfaceAndVolume);
return _MaskRead ? _Water.Surface.Enabled ? MaskRenderer.MaskInput.Both : MaskRenderer.MaskInput.Color : MaskRenderer.MaskInput.None;
// We only need the mask if rendering both surface and volume.
return _MaskRead
? (UseLegacyMask || UseStencilBuffer ? MaskRenderer.MaskInput.Both : MaskRenderer.MaskInput.Color)
: MaskRenderer.MaskInput.None;
}
}
}

View File

@@ -13,11 +13,6 @@ namespace WaveHarmonic.Crest
[System.Serializable]
public sealed partial class UnderwaterRenderer
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 0;
#pragma warning restore 414
internal const float k_CullLimitMinimum = 0.000001f;
internal const float k_CullLimitMaximum = 0.01f;
@@ -62,7 +57,7 @@ namespace WaveHarmonic.Crest
#if d_UnitySRP
[@Label("Volume")]
[Tooltip("This profile will be weighed in the deeper underwater the camera goes.")]
[@Predicated(RenderPipeline.HighDefinition, hide: true)]
[@Show(RenderPipeline.HighDefinition)]
[@DecoratedField, SerializeField]
VolumeProfile _EnvironmentalLightingVolumeProfile = null;
@@ -72,23 +67,34 @@ namespace WaveHarmonic.Crest
[@Heading("Advanced")]
[Tooltip("Whether to execute for all cameras.\n\nIf disabled, then additionally ignore any camera that is not the view camera or our reflection camera. It will require managing culling masks of all cameras.")]
[Tooltip("Rules to exclude cameras from rendering underwater.\n\nThese are exclusion rules, so for all cameras, select Nothing. These rules are applied on top of the Layer rules.")]
[@DecoratedField]
[@GenerateAPI]
[@DecoratedField, SerializeField]
bool _AllCameras;
[SerializeField]
internal WaterCameraExclusion _CameraExclusions = WaterCameraExclusion.Hidden | WaterCameraExclusion.Reflection;
[Tooltip("Copying parameters each frame ensures underwater appearance stays consistent with the water surface.\n\nHas a small overhead so should be disabled if not needed.")]
[@GenerateAPI]
[@DecoratedField, SerializeField]
bool _CopyWaterMaterialParametersEachFrame = true;
#if !d_Crest_LegacyUnderwater
[@HideInInspector]
#endif
[Tooltip("Adjusts the far plane for horizon line calculation. Helps with horizon line issue.")]
[@Range(0f, 1f)]
[@GenerateAPI]
[SerializeField]
float _FarPlaneMultiplier = 0.68f;
[Tooltip("Whether to enable culling of water chunks when below water.")]
[@GenerateAPI]
[@InlineToggle]
[@SerializeField]
bool _EnableChunkCulling = true;
[Tooltip("Proportion of visibility below which the water surface will be culled when underwater.\n\nThe larger the number, the closer to the camera the water tiles will be culled.")]
[@Enable(nameof(_EnableChunkCulling))]
[@Range(k_CullLimitMinimum, k_CullLimitMaximum)]
[@GenerateAPI]
[SerializeField]
@@ -105,6 +111,9 @@ namespace WaveHarmonic.Crest
[SerializeField]
internal bool _VisualizeMask;
#if !d_Crest_LegacyUnderwater
[@HideInInspector]
#endif
[SerializeField]
internal bool _DisableMask;
@@ -114,6 +123,9 @@ namespace WaveHarmonic.Crest
[SerializeField]
internal bool _DisableHeightAboveWaterOptimization;
#if !d_Crest_LegacyUnderwater
[@HideInInspector]
#endif
[SerializeField]
internal bool _DisableArtifactCorrection;
@@ -132,7 +144,7 @@ namespace WaveHarmonic.Crest
internal bool RenderBeforeTransparency => false;
#else
// Legacy mask works except for negative volumes. Not officially supported.
internal bool UseLegacyMask => _AllCameras;
internal bool UseLegacyMask => false;
internal bool RenderBeforeTransparency => true;
#endif
@@ -142,21 +154,25 @@ namespace WaveHarmonic.Crest
// BUG: NonSerialized as Unity shows a serialization depth warning even though field is internal.
[System.NonSerialized]
internal Portals.PortalRenderer _Portals;
internal bool Portaled => _Portals.Active;
#else
bool Portaled => false;
#endif
bool Portaled => _Water._ActiveModules.HasFlag(WaterRenderer.ActiveModules.Portal);
int _MaterialLastUpdatedFrame = -1;
//
// Camera Loop Flags
//
internal bool UseStencilBuffer { get; set; }
internal enum Pass
{
Culling,
Mask,
Effect,
}
// Force the full-screen mask for Portals that need it.
internal bool RequiresFullScreenMask { get; set; }
// Requested the temporary color texture.
internal bool NeedsColorTexture { get; set; }
// These are the materials we actually use, overridable by Water Body.
Material _SurfaceMaterial;
@@ -253,14 +269,14 @@ namespace WaveHarmonic.Crest
_HorizonMaskMaterial = null;
}
internal bool ShouldRender(Camera camera, Pass pass)
internal bool ShouldRender(Camera camera)
{
if (!_Enabled || _Material == null)
{
return false;
}
// Clear state.
UseStencilBuffer = false;
NeedsColorTexture = false;
RequiresFullScreenMask = true;
if (_Water == null)
if (!_Enabled || _Material == null)
{
return false;
}
@@ -270,35 +286,7 @@ namespace WaveHarmonic.Crest
return false;
}
// Skip entire mask pass if possible.
if (pass == Pass.Mask && !_Water.Surface.Enabled)
{
return false;
}
#if UNITY_EDITOR
if (GL.wireframe)
{
return false;
}
// Skip camera if fog is disabled. Do not skip if mask pass and a portal or volume as we want it to still
// mask the water surface.
if ((pass != Pass.Mask || !Portaled) && !IsFogEnabledForEditorCamera(camera))
{
return false;
}
#endif
var isReflectionCamera = camera.cameraType == CameraType.Reflection;
// Mask or culling is not needed for reflections.
if (isReflectionCamera && pass != Pass.Effect)
{
return false;
}
if (_Debug._OnlyReflectionCameras && !isReflectionCamera)
if (_Debug._OnlyReflectionCameras && camera.cameraType != CameraType.Reflection)
{
return false;
}
@@ -307,12 +295,14 @@ namespace WaveHarmonic.Crest
// Otherwise, filtering depends on the camera's culling mask which is not always
// accessible like with the global "Reflection Probes Camera". But whether those
// cameras triggering camera events is a bug is TBD as it is intermittent.
if (!_AllCameras && camera != _Water.GetViewer(includeSceneCamera: false) && camera.cameraType != CameraType.SceneView && camera != WaterReflections.CurrentCamera)
if (camera != _Water.Reflections.ReflectionCamera && !WaterRenderer.ShouldRender(camera, _CameraExclusions))
{
return false;
}
if (!_Debug._DisableHeightAboveWaterOptimization && !Portaled)
var flags = _Water._ActiveModules;
if (!_Debug._DisableHeightAboveWaterOptimization && !Portaled && flags.HasFlag(WaterRenderer.ActiveModules.Surface))
{
_Water.UpdatePerCameraHeight(camera);
_ViewerWaterHeight = _Water._ViewerHeightAboveWaterPerCamera;
@@ -326,25 +316,17 @@ namespace WaveHarmonic.Crest
return true;
}
void RevertCulling()
{
foreach (var tile in _Water.Surface.Chunks)
{
if (tile.Rend == null || tile._Culled)
{
continue;
}
tile.Rend.enabled = true;
}
}
// Called by WaterRenderer. Camera must have water layer.
internal void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
{
OnBeginCameraRendering(camera);
#if UNITY_EDITOR
if (_VolumeMaterial == null)
{
return;
}
// Populated by this point.
if (_VolumeMaterial.shader != WaterResources.Instance.Shaders._UnderwaterEffect)
{
@@ -352,6 +334,7 @@ namespace WaveHarmonic.Crest
}
#endif
#pragma warning disable format
#if d_UnityURP
if (RenderPipelineHelper.IsUniversal)
{
@@ -371,28 +354,11 @@ namespace WaveHarmonic.Crest
{
OnBeforeLegacyRender(camera);
}
#pragma warning restore format
}
internal void OnBeginCameraRendering(Camera camera)
{
if (!ShouldRender(camera, Pass.Culling))
{
return;
}
// Only one camera supported due to LOD center dependency.
if (!UseLegacyMask && ShouldRender(camera, Pass.Mask) && camera == _Water.Viewer)
{
_Water.Surface.UpdateDisplacedSurfaceData(camera);
}
#if d_UnityHDRP
if (RenderPipelineHelper.IsHighDefinition)
{
_Water.UpdateHighDefinitionLighting(camera);
}
#endif
_SurfaceMaterial = _Water.Surface.AboveOrBelowSurfaceMaterial;
_VolumeMaterial = _Material;
@@ -466,9 +432,20 @@ namespace WaveHarmonic.Crest
UpdateEnvironmentalLighting(camera, extinction, _ViewerWaterHeight);
}
if (!_EnableChunkCulling)
{
return;
}
// Only relevant to cameras rendering the surface from here.
if (!_Water._ActiveModules.HasFlag(WaterRenderer.ActiveModules.Surface))
{
return;
}
// Redo culling. Culling is per camera. But chunks are shared.
if (Portaled || _ViewerWaterHeight > -5f)
{
RevertCulling();
return;
}
@@ -489,7 +466,6 @@ namespace WaveHarmonic.Crest
}
else
{
// Previous camera might have culled in underwater pass.
tile.Rend.enabled = true;
}
}
@@ -498,8 +474,6 @@ namespace WaveHarmonic.Crest
internal void OnEndCameraRendering(Camera camera)
{
RestoreEnvironmentalLighting();
RevertCulling();
_DoneMaskRead = false;
if (RenderPipelineHelper.IsLegacy)
{
@@ -507,6 +481,26 @@ namespace WaveHarmonic.Crest
}
}
internal void ExecuteHeightField(Camera camera)
{
if (UseLegacyMask)
{
return;
}
if (!RequiresFullScreenMask)
{
return;
}
if (!_Water._ActiveModules.HasFlag(WaterRenderer.ActiveModules.Surface))
{
return;
}
_Water.Surface.UpdateDisplacedSurfaceData(camera);
}
void SetEnabled(bool previous, bool current)
{
if (previous == current) return;
@@ -537,4 +531,16 @@ namespace WaveHarmonic.Crest
}
#endif
}
// Obsolete / Migration
partial class UnderwaterRenderer : Versioned
{
// No migration as default value for new control is far more effective than this toggle.
[System.Obsolete("Please use Camera Exclusion instead.")]
[Tooltip("Whether to execute for all cameras.\n\nIf disabled, then additionally ignore any camera that is not the view camera or our reflection camera. It will require managing culling masks of all cameras.")]
[@GenerateAPI]
[@DecoratedField, SerializeField]
[HideInInspector]
bool _AllCameras;
}
}