升级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

@@ -1,7 +1,6 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using System.Collections.Generic;
using UnityEngine;
using WaveHarmonic.Crest.Internal;
@@ -9,12 +8,12 @@ namespace WaveHarmonic.Crest
{
interface IReportsHeight
{
bool ReportHeight(ref Rect bounds, ref float minimum, ref float maximum);
bool ReportHeight(WaterRenderer water, ref Rect bounds, ref float minimum, ref float maximum);
}
interface IReportsDisplacement
{
bool ReportDisplacement(ref Rect bounds, ref float horizontal, ref float vertical);
bool ReportDisplacement(WaterRenderer water, ref Rect bounds, ref float horizontal, ref float vertical);
}
/// <summary>
@@ -24,7 +23,7 @@ namespace WaveHarmonic.Crest
[AddComponentMenu("")]
#endif
[@ExecuteDuringEditMode]
sealed class WaterChunkRenderer : ManagedBehaviour<WaterRenderer>
sealed partial class WaterChunkRenderer : ManagedBehaviour<WaterRenderer>
{
[SerializeField]
internal bool _DrawRenderBounds = false;
@@ -46,7 +45,13 @@ namespace WaveHarmonic.Crest
internal Rect _UnexpandedBoundsXZ = new();
public Rect UnexpandedBoundsXZ => _UnexpandedBoundsXZ;
internal Bounds _LocalBounds;
internal float _LocalScale;
// WaterBody culling.
internal bool _Culled;
// Frustum visibility.
internal bool _Visible;
internal WaterRenderer _Water;
@@ -59,10 +64,8 @@ namespace WaveHarmonic.Crest
// contiguous surface.
internal bool _WaterDataHasBeenBound = true;
int _LodIndex = -1;
internal int _LodIndex = -1;
public static List<IReportsHeight> HeightReporters { get; } = new();
public static List<IReportsDisplacement> DisplacementReporters { get; } = new();
// There is a 1-frame delay with Initialized in edit mode due to setting
// enableInEditMode in EditorApplication.update. This only really affect this
@@ -73,7 +76,6 @@ namespace WaveHarmonic.Crest
_LodIndex = index;
Rend = renderer;
_Mesh = mesh;
_PreviousObjectToWorld = _CurrentObjectToWorld = transform.localToWorldMatrix;
_Transform = transform;
}
@@ -118,8 +120,9 @@ namespace WaveHarmonic.Crest
internal void OnLateUpdate()
{
_PreviousObjectToWorld = _CurrentObjectToWorld;
_PreviousObjectToWorld = _Water.Surface.PreviousObjectToWorld[_SiblingIndex];
_CurrentObjectToWorld = _Transform.localToWorldMatrix;
_Water.Surface.PreviousObjectToWorld[_SiblingIndex] = _CurrentObjectToWorld;
}
internal void RenderMotionVectors(SurfaceRenderer surface, Camera camera)
@@ -144,6 +147,7 @@ namespace WaveHarmonic.Crest
matProps = _MaterialPropertyBlock,
worldBounds = Rend.bounds,
layer = surface.Layer,
renderingLayerMask = (uint)surface.Layer,
receiveShadows = false,
shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off,
lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off,
@@ -158,37 +162,26 @@ namespace WaveHarmonic.Crest
{
s_UpdateMeshBoundsMarker.Begin(this);
var bounds = _Mesh.bounds;
var bounds = _LocalBounds;
if (WaterBody.WaterBodies.Count > 0)
bounds = ComputeBounds(_Transform, bounds);
_UnexpandedBoundsXZ = new(0, 0, bounds.size.x, bounds.size.z)
{
_UnexpandedBoundsXZ = ComputeBoundsXZ(_Transform, bounds);
}
center = bounds.center.XZ(),
};
bounds = ExpandBoundsForDisplacements(_Transform, bounds);
Rend.localBounds = bounds;
Rend.bounds = bounds;
s_UpdateMeshBoundsMarker.End();
}
public static Rect ComputeBoundsXZ(Transform transform, Bounds bounds)
{
// Since chunks are axis-aligned it is safe to rotate the bounds.
var center = transform.rotation * bounds.center * transform.lossyScale.x + transform.position;
var size = transform.rotation * bounds.size * transform.lossyScale.x;
// Rotation can make size negative.
return new(0, 0, Mathf.Abs(size.x), Mathf.Abs(size.z))
{
center = center.XZ(),
};
}
// Used by the water mask system if we need to render the water mask in situations
// where the water itself doesn't need to be rendered or has otherwise been disabled
internal void Bind()
{
_MaterialPropertyBlock = _Water.Surface._PerCascadeMPB.Current[_LodIndex];
_MaterialPropertyBlock = _Water.Surface.PerCascadeMPB[_LodIndex];
new PropertyWrapperMPB(_MaterialPropertyBlock).SetSHCoefficients(_Transform.position);
Rend.SetPropertyBlock(_MaterialPropertyBlock);
_WaterDataHasBeenBound = true;
@@ -197,6 +190,7 @@ namespace WaveHarmonic.Crest
void OnDestroy()
{
Helpers.Destroy(_Mesh);
_Mesh = null;
}
// Called when visible to a camera
@@ -207,6 +201,14 @@ namespace WaveHarmonic.Crest
return;
}
#if CREST_DEBUG
if (_Water._Debug._VisualizeData)
{
Rend.sharedMaterial = _Water.Surface.VisualizeDataMaterial;
MaterialOverridden = true;
}
#endif
if (!MaterialOverridden && Rend.sharedMaterial != _Water.Surface.Material)
{
Rend.sharedMaterial = _Water.Surface.Material;
@@ -217,13 +219,28 @@ namespace WaveHarmonic.Crest
{
Bind();
}
if (_DrawRenderBounds)
{
Rend.bounds.DebugDraw();
}
}
public Bounds ComputeBounds(Transform transform, Bounds bounds)
{
var extents = bounds.extents;
var center = bounds.center;
// Apply transform. Rotation already done.
var scale = _LocalScale * _Water.Scale;
extents.x *= scale;
extents.z *= scale;
center.x *= scale;
center.z *= scale;
center += transform.position;
bounds.center = center;
bounds.extents = extents;
return bounds;
}
// this is called every frame because the bounds are given in world space and depend on the transform scale, which
// can change depending on view altitude
public Bounds ExpandBoundsForDisplacements(Transform transform, Bounds bounds)
@@ -231,99 +248,53 @@ namespace WaveHarmonic.Crest
var extents = bounds.extents;
var center = bounds.center;
var scale = transform.lossyScale;
var rotation = transform.rotation;
var boundsPadding = _Water.MaximumHorizontalDisplacement;
var expandXZ = boundsPadding / scale.x;
var boundsY = _Water.MaximumVerticalDisplacement;
var rect = _UnexpandedBoundsXZ;
// Extend the kinematic bounds slightly to give room for dynamic waves.
if (_Water._DynamicWavesLod.Enabled)
{
boundsY += 5f;
}
// Extend bounds by global waves.
extents.x += expandXZ;
extents.y += boundsY;
extents.z += expandXZ;
// Get XZ bounds. Doing this manually bypasses updating render bounds call.
Rect rect;
{
var p1 = transform.position;
var p2 = rotation * new Vector3(center.x, 0f, center.z);
var s1 = scale;
var s2 = rotation * (extents.XNZ(0f) * 2f);
rect = new(0, 0, Mathf.Abs(s1.x * s2.x), Mathf.Abs(s1.z * s2.z))
{
center = new(p1.x + p2.x, p1.z + p2.z)
};
var settings = _Water.DynamicWavesLod.Settings;
extents.x += settings._HorizontalDisplace;
extents.y += settings._VerticalDisplacementCullingContributions;
extents.z += settings._HorizontalDisplace;
}
// Extend bounds by local waves.
{
var totalHorizontal = 0f;
var totalVertical = 0f;
var horizontal = 0f;
var vertical = 0f;
foreach (var reporter in DisplacementReporters)
foreach (var (key, input) in AnimatedWavesLod.s_Inputs)
{
var horizontal = 0f;
var vertical = 0f;
if (reporter.ReportDisplacement(ref rect, ref horizontal, ref vertical))
{
totalHorizontal += horizontal;
totalVertical += vertical;
}
input.DisplacementReporter?.ReportDisplacement(_Water, ref rect, ref horizontal, ref vertical);
}
boundsPadding = totalHorizontal;
expandXZ = boundsPadding / scale.x;
boundsY = totalVertical;
extents.x += expandXZ;
extents.y += boundsY;
extents.z += expandXZ;
extents.x += horizontal;
extents.y += vertical;
extents.z += horizontal;
}
// Expand and offset bounds by height.
{
var minimumWaterLevelBounds = 0f;
var maximumWaterLevelBounds = 0f;
var minimum = 0f;
var maximum = 0f;
foreach (var reporter in HeightReporters)
foreach (var (key, input) in LevelLod.s_Inputs)
{
var minimum = 0f;
var maximum = 0f;
if (reporter.ReportHeight(ref rect, ref minimum, ref maximum))
{
minimumWaterLevelBounds = Mathf.Max(minimumWaterLevelBounds, Mathf.Abs(Mathf.Min(minimum, _Water.SeaLevel) - _Water.SeaLevel));
maximumWaterLevelBounds = Mathf.Max(maximumWaterLevelBounds, Mathf.Abs(Mathf.Max(maximum, _Water.SeaLevel) - _Water.SeaLevel));
}
input.HeightReporter?.ReportHeight(_Water, ref rect, ref minimum, ref maximum);
}
minimumWaterLevelBounds *= 0.5f;
maximumWaterLevelBounds *= 0.5f;
extents.y += Mathf.Abs((minimum - maximum) * 0.5f);
boundsY = minimumWaterLevelBounds + maximumWaterLevelBounds;
extents.y += boundsY;
bounds.extents = extents;
var offset = maximumWaterLevelBounds - minimumWaterLevelBounds;
var offset = Mathf.Lerp(minimum, maximum, 0.5f);
center.y += offset;
bounds.center = center;
}
return bounds;
}
// Get XZ bounds. Doing this manually bypasses updating render bounds call.
bounds.center = center;
bounds.extents = extents;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void InitStatics()
{
HeightReporters.Clear();
DisplacementReporters.Clear();
return bounds;
}
}