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

@@ -19,14 +19,18 @@ namespace WaveHarmonic.Crest
[@Space(10)]
// If disabled, there will be a difference due to Random.value.
[Tooltip("Use a swell spectrum as the default.\n\nUses a swell spectrum as default (when none is assigned), and disabled reverse waves.")]
[@Order("Waves")]
[@DecoratedField]
[@GenerateAPI]
[@DecoratedField(order = -3), SerializeField]
[@SerializeField]
bool _Swell = true;
[Tooltip("The weight of the opposing, second pair of Gerstner waves.\n\nEach Gerstner wave is actually a pair of waves travelling in opposite directions (similar to FFT). This weight is applied to the wave travelling in against-wind direction. Set to zero to obtain simple single waves which are useful for shorelines waves.")]
[Predicated(nameof(_Swell), inverted: true)]
[@Range(0f, 1f, order = -4)]
[@Order("Waves")]
[@Disable(nameof(_Swell))]
[@Range(0f, 1f)]
[@GenerateAPI(Getter.Custom)]
[SerializeField]
float _ReverseWaveWeight = 0.5f;
@@ -35,23 +39,28 @@ namespace WaveHarmonic.Crest
// Generation Settings
[Tooltip("How many wave components to generate in each octave.")]
[@Order("Generation Settings")]
[@Delayed]
[@GenerateAPI]
[SerializeField]
int _ComponentsPerOctave = 8;
[Tooltip("Change to get a different set of waves.")]
[@Order("Generation Settings")]
[@GenerateAPI]
[@DecoratedField]
[SerializeField]
int _RandomSeed = 0;
[Tooltip("Prevent data arrays from being written to so one can provide their own.")]
[@Order("Generation Settings")]
[@GenerateAPI]
[@DecoratedField]
[SerializeField]
bool _ManualGeneration;
private protected override int MinimumResolution => 8;
private protected override int MaximumResolution => 64;
private protected override int MaximumResolution => int.MaxValue;
float _WindSpeedWhenGenerated = -1f;
@@ -93,12 +102,7 @@ namespace WaveHarmonic.Crest
float[] _Amplitudes2;
float[] _Phases2;
struct GerstnerCascadeParams
{
public int _StartIndex;
}
ComputeBuffer _BufferCascadeParameters;
readonly GerstnerCascadeParams[] _CascadeParameters = new GerstnerCascadeParams[k_CascadeCount + 1];
readonly int[] _StartIndices = new int[k_CascadeCount];
// Caution - order here impact performance. Rearranging these to match order
// they're read in the compute shader made it 50% slower..
@@ -111,6 +115,7 @@ namespace WaveHarmonic.Crest
public Vector4 _Omega;
public Vector4 _Phase;
public Vector4 _ChopAmplitude;
// Waves are generated in pairs, these values are for the second in the pair
public Vector4 _Amplitude2;
public Vector4 _ChopAmplitude2;
@@ -119,8 +124,7 @@ namespace WaveHarmonic.Crest
ComputeBuffer _BufferWaveData;
readonly GerstnerWaveComponent4[] _WaveData = new GerstnerWaveComponent4[k_MaximumWaveComponents / 4];
ComputeShader _ShaderGerstner;
int _KernelGerstner = -1;
WaterResources.GerstnerCompute _Shader;
private protected override WaveSpectrum DefaultSpectrum => _Swell ? SwellSpectrum : WindSpectrum;
static WaveSpectrum s_SwellSpectrum;
@@ -154,7 +158,7 @@ namespace WaveHarmonic.Crest
{
public static readonly int s_FirstCascadeIndex = Shader.PropertyToID("_Crest_FirstCascadeIndex");
public static readonly int s_TextureRes = Shader.PropertyToID("_Crest_TextureRes");
public static readonly int s_CascadeParams = Shader.PropertyToID("_Crest_GerstnerCascadeParams");
public static readonly int s_StartIndices = Shader.PropertyToID("_Crest_StartIndices");
public static readonly int s_GerstnerWaveData = Shader.PropertyToID("_Crest_GerstnerWaveData");
}
@@ -179,7 +183,7 @@ namespace WaveHarmonic.Crest
{
if (_WaveBuffers == null)
{
_WaveBuffers = new(_Resolution, _Resolution, 0, GraphicsFormat.R16G16B16A16_SFloat);
_WaveBuffers = new(Resolution, Resolution, 0, Helpers.GetCompatibleTextureFormat(GraphicsFormat.R16G16B16A16_SFloat, randomWrite: true));
}
else
{
@@ -187,7 +191,7 @@ namespace WaveHarmonic.Crest
}
{
_WaveBuffers.width = _WaveBuffers.height = _Resolution;
_WaveBuffers.width = _WaveBuffers.height = Resolution;
_WaveBuffers.wrapMode = TextureWrapMode.Clamp;
_WaveBuffers.antiAliasing = 1;
_WaveBuffers.filterMode = FilterMode.Bilinear;
@@ -200,14 +204,11 @@ namespace WaveHarmonic.Crest
_WaveBuffers.Create();
}
_BufferCascadeParameters?.Release();
_BufferWaveData?.Release();
_BufferCascadeParameters = new(k_CascadeCount + 1, UnsafeUtility.SizeOf<GerstnerCascadeParams>());
_BufferWaveData = new(k_MaximumWaveComponents / 4, UnsafeUtility.SizeOf<GerstnerWaveComponent4>());
_ShaderGerstner = WaterResources.Instance.Compute._Gerstner;
_KernelGerstner = _ShaderGerstner.FindKernel("Gerstner");
_Shader = WaterResources.Instance._ComputeLibrary._GerstnerCompute;
}
private protected override void OnUpdate(WaterRenderer water)
@@ -216,7 +217,7 @@ namespace WaveHarmonic.Crest
base.OnUpdate(water);
if (_WaveBuffers == null || _Resolution != _WaveBuffers.width || _BufferCascadeParameters == null || _BufferWaveData == null)
if (_WaveBuffers == null || Resolution != _WaveBuffers.width || _BufferWaveData == null)
{
InitData();
}
@@ -266,7 +267,7 @@ namespace WaveHarmonic.Crest
var cascadeIdx = 0;
var componentIdx = 0;
var outputIdx = 0;
_CascadeParameters[0]._StartIndex = 0;
_StartIndices[0] = 0;
if (_ManualGeneration)
{
@@ -313,12 +314,14 @@ namespace WaveHarmonic.Crest
_WaveData[vi]._Omega[ei] = 0f;
_WaveData[vi]._Phase[ei] = 0f;
_WaveData[vi]._ChopAmplitude[ei] = 0f;
if (!_ManualGeneration)
if (!_ManualGeneration && !_Swell)
{
_WaveData[vi]._Phase2[ei] = 0f;
_WaveData[vi]._Amplitude2[ei] = 0f;
_WaveData[vi]._ChopAmplitude2[ei] = 0f;
}
ei = (ei + 1) % 4;
outputIdx++;
}
@@ -326,7 +329,7 @@ namespace WaveHarmonic.Crest
if (outputIdx > 0 && _FirstCascade < 0) _FirstCascade = cascadeIdx;
cascadeIdx++;
_CascadeParameters[cascadeIdx]._StartIndex = outputIdx / 4;
_StartIndices[cascadeIdx] = outputIdx / 4;
minWl *= 2f;
//Debug.Log($"Crest: {cascadeIdx}: start {_cascadeParams[cascadeIdx]._startIndex} minWL {minWl}");
@@ -343,7 +346,7 @@ namespace WaveHarmonic.Crest
var chopScale = _ActiveSpectrum._ChopScales[componentIdx / _ComponentsPerOctave];
_WaveData[vi]._ChopAmplitude[ei] = -chopScale * _ActiveSpectrum._Chop * _Amplitudes[componentIdx];
if (!_ManualGeneration)
if (!_ManualGeneration && !_Swell)
{
_WaveData[vi]._Amplitude2[ei] = _Amplitudes2[componentIdx];
_WaveData[vi]._ChopAmplitude2[ei] = -chopScale * _ActiveSpectrum._Chop * _Amplitudes2[componentIdx];
@@ -385,7 +388,7 @@ namespace WaveHarmonic.Crest
_WaveData[vi]._Omega[ei] = k * c;
_WaveData[vi]._Phase[ei] = Mathf.Repeat(_Phases[componentIdx], Mathf.PI * 2f);
if (!_ManualGeneration)
if (!_ManualGeneration && !_Swell)
{
_WaveData[vi]._Phase2[ei] = Mathf.Repeat(_Phases2[componentIdx], Mathf.PI * 2f);
}
@@ -410,40 +413,46 @@ namespace WaveHarmonic.Crest
_WaveData[vi]._Omega[ei] = 0f;
_WaveData[vi]._Phase[ei] = 0f;
_WaveData[vi]._ChopAmplitude[ei] = 0f;
if (!_ManualGeneration)
if (!_ManualGeneration && !_Swell)
{
_WaveData[vi]._Phase2[ei] = 0f;
_WaveData[vi]._Amplitude2[ei] = 0f;
_WaveData[vi]._ChopAmplitude2[ei] = 0f;
}
ei = (ei + 1) % 4;
outputIdx++;
}
}
while (cascadeIdx < k_CascadeCount)
// Fill the remaining.
while (cascadeIdx < k_CascadeCount - 1)
{
cascadeIdx++;
minWl *= 2f;
_CascadeParameters[cascadeIdx]._StartIndex = outputIdx / 4;
_StartIndices[cascadeIdx] = outputIdx / 4;
//Debug.Log($"Crest: {cascadeIdx}: start {_cascadeParams[cascadeIdx]._startIndex} minWL {minWl}");
}
_BufferCascadeParameters.SetData(_CascadeParameters);
_BufferWaveData.SetData(_WaveData);
}
void UpdateGenerateWaves(CommandBuffer buf)
void UpdateGenerateWaves(CommandBuffer buffer)
{
// Clear existing waves or they could get copied.
CoreUtils.SetRenderTarget(buf, _WaveBuffers, ClearFlag.Color);
buf.SetComputeFloatParam(_ShaderGerstner, ShaderIDs.s_TextureRes, _WaveBuffers.width);
buf.SetComputeIntParam(_ShaderGerstner, ShaderIDs.s_FirstCascadeIndex, _FirstCascade);
buf.SetComputeBufferParam(_ShaderGerstner, _KernelGerstner, ShaderIDs.s_CascadeParams, _BufferCascadeParameters);
buf.SetComputeBufferParam(_ShaderGerstner, _KernelGerstner, ShaderIDs.s_GerstnerWaveData, _BufferWaveData);
buf.SetComputeTextureParam(_ShaderGerstner, _KernelGerstner, ShapeWaves.ShaderIDs.s_WaveBuffer, _WaveBuffers);
CoreUtils.SetRenderTarget(buffer, _WaveBuffers, ClearFlag.Color);
buf.DispatchCompute(_ShaderGerstner, _KernelGerstner, _WaveBuffers.width / Lod.k_ThreadGroupSizeX, _WaveBuffers.height / Lod.k_ThreadGroupSizeY, _LastCascade - _FirstCascade + 1);
var wrapper = new PropertyWrapperCompute(buffer, _Shader._Shader, _Shader._ExecuteKernel);
wrapper.SetFloat(ShaderIDs.s_TextureRes, _WaveBuffers.width);
wrapper.SetInteger(ShaderIDs.s_FirstCascadeIndex, _FirstCascade);
wrapper.SetIntegers(ShaderIDs.s_StartIndices, _StartIndices);
wrapper.SetBuffer(ShaderIDs.s_GerstnerWaveData, _BufferWaveData);
wrapper.SetTexture(ShapeWaves.ShaderIDs.s_WaveBuffer, _WaveBuffers);
wrapper.SetKeyword(_Shader._WavePairsKeyword, !_Swell && _ReverseWaveWeight > 0f);
wrapper.Dispatch(_WaveBuffers.width / Lod.k_ThreadGroupSizeX, _WaveBuffers.height / Lod.k_ThreadGroupSizeY, _LastCascade - _FirstCascade + 1);
}
/// <summary>
@@ -503,16 +512,16 @@ namespace WaveHarmonic.Crest
{
var amp = _ActiveSpectrum.GetAmplitude(_Wavelengths[i], _ComponentsPerOctave, windSpeed, water.Gravity, out _Powers[i]);
_Amplitudes[i] = Random.value * amp;
_Amplitudes2[i] = Random.value * amp * ReverseWaveWeight;
if (!_Swell)
{
_Amplitudes2[i] = Random.value * amp * ReverseWaveWeight;
}
}
}
void InitPhases()
{
// Set random seed to get repeatable results
var randomStateBkp = Random.state;
Random.InitState(_RandomSeed);
var totalComps = _ComponentsPerOctave * WaveSpectrum.k_NumberOfOctaves;
_Phases = new float[totalComps];
_Phases2 = new float[totalComps];
@@ -524,12 +533,13 @@ namespace WaveHarmonic.Crest
var rnd = (i + Random.value) / _ComponentsPerOctave;
_Phases[index] = 2f * Mathf.PI * rnd;
var rnd2 = (i + Random.value) / _ComponentsPerOctave;
_Phases2[index] = 2f * Mathf.PI * rnd2;
if (!_Swell)
{
var rnd2 = (i + Random.value) / _ComponentsPerOctave;
_Phases2[index] = 2f * Mathf.PI * rnd2;
}
}
}
Random.state = randomStateBkp;
}
private protected override void ReportMaxDisplacement(WaterRenderer water)
@@ -546,23 +556,23 @@ namespace WaveHarmonic.Crest
return;
}
var ampSum = 0f;
MaximumReportedVerticalDisplacement = 0;
MaximumReportedHorizontalDisplacement = 0;
for (var i = 0; i < _Wavelengths.Length; i++)
{
ampSum += _Amplitudes[i] * _ActiveSpectrum._ChopScales[i / _ComponentsPerOctave];
var amplitude = _Amplitudes[i];
MaximumReportedVerticalDisplacement += amplitude;
MaximumReportedHorizontalDisplacement += amplitude * _ActiveSpectrum._ChopScales[i / _ComponentsPerOctave];
}
MaximumReportedHorizontalDisplacement *= _ActiveSpectrum._Chop;
// Apply weight or will cause popping due to scale change.
ampSum *= Weight;
MaximumReportedVerticalDisplacement *= Weight;
MaximumReportedHorizontalDisplacement *= Weight;
MaximumReportedHorizontalDisplacement = ampSum * _ActiveSpectrum._Chop;
MaximumReportedVerticalDisplacement = ampSum;
MaximumReportedWavesDisplacement = ampSum;
if (Mode == LodInputMode.Global)
{
water.ReportMaximumDisplacement(ampSum * _ActiveSpectrum._Chop, ampSum, ampSum);
}
MaximumReportedWavesDisplacement = MaximumReportedVerticalDisplacement;
}
private protected override void Initialize()
@@ -577,11 +587,6 @@ namespace WaveHarmonic.Crest
s_Instances.Remove(this);
if (_BufferCascadeParameters != null && _BufferCascadeParameters.IsValid())
{
_BufferCascadeParameters.Dispose();
_BufferCascadeParameters = null;
}
if (_BufferWaveData != null && _BufferWaveData.IsValid())
{
_BufferWaveData.Dispose();
@@ -623,32 +628,23 @@ namespace WaveHarmonic.Crest
if (s_SwellSpectrum != null)
{
Helpers.Destroy(s_SwellSpectrum);
s_SwellSpectrum = null;
}
}
}
partial class ShapeGerstner : ISerializationCallbackReceiver
partial class ShapeGerstner
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 2;
#pragma warning restore 414
private protected override int Version => Mathf.Max(base.Version, 2);
void ISerializationCallbackReceiver.OnAfterDeserialize()
private protected override void OnMigrate()
{
_Version = MigrateV1(_Version);
base.OnMigrate();
if (_Version < 2)
{
_Swell = false;
}
_Version = MigrateV2(_Version);
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
// Empty.
}
}
}