升级水插件

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

@@ -17,9 +17,17 @@ namespace WaveHarmonic.Crest
{
// Waves
[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.")]
[@Range(0f, 1f, order = -3)]
[@Space(10)]
[Tooltip("Use a swell spectrum as the default.\n\nUses a swell spectrum as default (when none is assigned), and disabled reverse waves.")]
[@GenerateAPI]
[@DecoratedField(order = -3), 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)]
[@GenerateAPI(Getter.Custom)]
[SerializeField]
float _ReverseWaveWeight = 0.5f;
@@ -37,6 +45,11 @@ namespace WaveHarmonic.Crest
[SerializeField]
int _RandomSeed = 0;
[Tooltip("Prevent data arrays from being written to so one can provide their own.")]
[@GenerateAPI]
[SerializeField]
bool _ManualGeneration;
private protected override int MinimumResolution => 8;
private protected override int MaximumResolution => 64;
@@ -45,12 +58,39 @@ namespace WaveHarmonic.Crest
const int k_MaximumWaveComponents = 1024;
// Data for all components
float[] _Wavelengths;
float[] _Amplitudes;
/// <summary>
/// Wavelengths. Requires Manual Generation to be enabled.
/// </summary>
[System.NonSerialized]
public float[] _Wavelengths;
/// <summary>
/// Amplitudes. Requires Manual Generation to be enabled.
/// </summary>
[System.NonSerialized]
public float[] _Amplitudes;
/// <summary>
/// Powers. Requires Manual Generation to be enabled.
/// </summary>
[System.NonSerialized]
public float[] _Powers;
/// <summary>
/// Angles. Requires Manual Generation to be enabled.
/// </summary>
[System.NonSerialized]
public float[] _AngleDegrees;
/// <summary>
/// Phases. Requires Manual Generation to be enabled.
/// </summary>
[System.NonSerialized]
public float[] _Phases;
// Reverse.
float[] _Amplitudes2;
float[] _Powers;
float[] _AngleDegrees;
float[] _Phases;
float[] _Phases2;
struct GerstnerCascadeParams
@@ -82,6 +122,33 @@ namespace WaveHarmonic.Crest
ComputeShader _ShaderGerstner;
int _KernelGerstner = -1;
private protected override WaveSpectrum DefaultSpectrum => _Swell ? SwellSpectrum : WindSpectrum;
static WaveSpectrum s_SwellSpectrum;
static WaveSpectrum SwellSpectrum
{
get
{
if (s_SwellSpectrum == null)
{
s_SwellSpectrum = ScriptableObject.CreateInstance<WaveSpectrum>();
s_SwellSpectrum.name = "Swell Waves (auto)";
s_SwellSpectrum.hideFlags = HideFlags.DontSave | HideFlags.NotEditable;
s_SwellSpectrum._PowerDisabled[0] = true;
s_SwellSpectrum._PowerDisabled[1] = true;
s_SwellSpectrum._PowerDisabled[2] = true;
s_SwellSpectrum._PowerDisabled[3] = true;
s_SwellSpectrum._PowerDisabled[4] = true;
s_SwellSpectrum._PowerDisabled[5] = true;
s_SwellSpectrum._PowerDisabled[6] = true;
s_SwellSpectrum._PowerDisabled[7] = true;
s_SwellSpectrum._WaveDirectionVariance = 15f;
s_SwellSpectrum._Chop = 1.3f;
}
return s_SwellSpectrum;
}
}
static new class ShaderIDs
{
@@ -103,6 +170,11 @@ namespace WaveHarmonic.Crest
s_Instances.Clear();
}
float GetReverseWaveWeight()
{
return _Swell ? 0f : _ReverseWaveWeight;
}
void InitData()
{
if (_WaveBuffers == null)
@@ -167,7 +239,7 @@ namespace WaveHarmonic.Crest
{
UpdateGenerateWaves(buffer);
// Above changes the render target. Change it back if necessary.
if (!IsCompute) buffer.SetRenderTarget(target, 0, CubemapFace.Unknown, slice);
if (!IsCompute) CoreUtils.SetRenderTarget(buffer, target, depthSlice: slice);
}
_LastGenerateFrameCount = Time.frameCount;
@@ -196,6 +268,16 @@ namespace WaveHarmonic.Crest
var outputIdx = 0;
_CascadeParameters[0]._StartIndex = 0;
if (_ManualGeneration)
{
for (var i = 0; i < _WaveData.Length; i++)
{
_WaveData[i]._Phase2 = Vector4.zero;
_WaveData[i]._Amplitude2 = Vector4.zero;
_WaveData[i]._ChopAmplitude2 = Vector4.zero;
}
}
// Seek forward to first wavelength that is big enough to render into current cascades
var minWl = MinWavelength(cascadeIdx);
while (componentIdx < _Wavelengths.Length && _Wavelengths[componentIdx] < minWl)
@@ -230,10 +312,13 @@ namespace WaveHarmonic.Crest
_WaveData[vi]._WaveDirectionZ[ei] = 0f;
_WaveData[vi]._Omega[ei] = 0f;
_WaveData[vi]._Phase[ei] = 0f;
_WaveData[vi]._Phase2[ei] = 0f;
_WaveData[vi]._ChopAmplitude[ei] = 0f;
_WaveData[vi]._Amplitude2[ei] = 0f;
_WaveData[vi]._ChopAmplitude2[ei] = 0f;
if (!_ManualGeneration)
{
_WaveData[vi]._Phase2[ei] = 0f;
_WaveData[vi]._Amplitude2[ei] = 0f;
_WaveData[vi]._ChopAmplitude2[ei] = 0f;
}
ei = (ei + 1) % 4;
outputIdx++;
}
@@ -254,11 +339,15 @@ namespace WaveHarmonic.Crest
var ei = outputIdx - vi * 4;
_WaveData[vi]._Amplitude[ei] = _Amplitudes[componentIdx];
_WaveData[vi]._Amplitude2[ei] = _Amplitudes2[componentIdx];
var chopScale = _ActiveSpectrum._ChopScales[componentIdx / _ComponentsPerOctave];
_WaveData[vi]._ChopAmplitude[ei] = -chopScale * _ActiveSpectrum._Chop * _Amplitudes[componentIdx];
_WaveData[vi]._ChopAmplitude2[ei] = -chopScale * _ActiveSpectrum._Chop * _Amplitudes2[componentIdx];
if (!_ManualGeneration)
{
_WaveData[vi]._Amplitude2[ei] = _Amplitudes2[componentIdx];
_WaveData[vi]._ChopAmplitude2[ei] = -chopScale * _ActiveSpectrum._Chop * _Amplitudes2[componentIdx];
}
var angle = Mathf.Deg2Rad * _AngleDegrees[componentIdx];
var dx = Mathf.Cos(angle);
@@ -295,7 +384,11 @@ namespace WaveHarmonic.Crest
// Repeat every 2pi to keep angle bounded - helps precision on 16bit platforms
_WaveData[vi]._Omega[ei] = k * c;
_WaveData[vi]._Phase[ei] = Mathf.Repeat(_Phases[componentIdx], Mathf.PI * 2f);
_WaveData[vi]._Phase2[ei] = Mathf.Repeat(_Phases2[componentIdx], Mathf.PI * 2f);
if (!_ManualGeneration)
{
_WaveData[vi]._Phase2[ei] = Mathf.Repeat(_Phases2[componentIdx], Mathf.PI * 2f);
}
outputIdx++;
}
@@ -316,10 +409,13 @@ namespace WaveHarmonic.Crest
_WaveData[vi]._WaveDirectionZ[ei] = 0f;
_WaveData[vi]._Omega[ei] = 0f;
_WaveData[vi]._Phase[ei] = 0f;
_WaveData[vi]._Phase2[ei] = 0f;
_WaveData[vi]._ChopAmplitude[ei] = 0f;
_WaveData[vi]._Amplitude2[ei] = 0f;
_WaveData[vi]._ChopAmplitude2[ei] = 0f;
if (!_ManualGeneration)
{
_WaveData[vi]._Phase2[ei] = 0f;
_WaveData[vi]._Amplitude2[ei] = 0f;
_WaveData[vi]._ChopAmplitude2[ei] = 0f;
}
ei = (ei + 1) % 4;
outputIdx++;
}
@@ -340,8 +436,7 @@ namespace WaveHarmonic.Crest
void UpdateGenerateWaves(CommandBuffer buf)
{
// Clear existing waves or they could get copied.
buf.SetRenderTarget(_WaveBuffers, 0, CubemapFace.Unknown, -1);
buf.ClearRenderTarget(RTClearFlags.Color, Color.black, 0, 0);
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);
@@ -358,13 +453,23 @@ namespace WaveHarmonic.Crest
/// <param name="windSpeed">Wind speed in m/s</param>
void UpdateWaveData(WaterRenderer water, float windSpeed)
{
if (_ManualGeneration)
{
if (_Wavelengths != null)
{
SliceUpWaves(water, windSpeed);
}
return;
}
// Set random seed to get repeatable results
var randomStateBkp = Random.state;
Random.InitState(_RandomSeed);
_ActiveSpectrum.GenerateWaveData(_ComponentsPerOctave, ref _Wavelengths, ref _AngleDegrees);
UpdateAmplitudes();
UpdateAmplitudes(water);
// Won't run every time so put last in the random sequence
if (_Phases == null || _Phases.Length != _Wavelengths.Length || _Phases2 == null || _Phases2.Length != _Wavelengths.Length)
@@ -377,7 +482,7 @@ namespace WaveHarmonic.Crest
SliceUpWaves(water, windSpeed);
}
void UpdateAmplitudes()
void UpdateAmplitudes(WaterRenderer water)
{
if (_Amplitudes == null || _Amplitudes.Length != _Wavelengths.Length)
{
@@ -396,9 +501,9 @@ namespace WaveHarmonic.Crest
for (var i = 0; i < _Wavelengths.Length; i++)
{
var amp = _ActiveSpectrum.GetAmplitude(_Wavelengths[i], _ComponentsPerOctave, windSpeed, out _Powers[i]);
var amp = _ActiveSpectrum.GetAmplitude(_Wavelengths[i], _ComponentsPerOctave, windSpeed, water.Gravity, out _Powers[i]);
_Amplitudes[i] = Random.value * amp;
_Amplitudes2[i] = Random.value * amp * _ReverseWaveWeight;
_Amplitudes2[i] = Random.value * amp * ReverseWaveWeight;
}
}
@@ -490,8 +595,6 @@ namespace WaveHarmonic.Crest
}
}
private protected override void DestroySharedResources() { }
#if UNITY_EDITOR
void OnGUI()
{
@@ -503,16 +606,44 @@ namespace WaveHarmonic.Crest
#endif
}
partial class ShapeGerstner
{
static int s_InstanceCount;
private protected override void Awake()
{
base.Awake();
s_InstanceCount++;
}
private protected override void OnDestroy()
{
base.OnDestroy();
if (s_SwellSpectrum != null)
{
Helpers.Destroy(s_SwellSpectrum);
}
}
}
partial class ShapeGerstner : ISerializationCallbackReceiver
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 1;
int _Version = 2;
#pragma warning restore 414
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
_Version = MigrateV1(_Version);
if (_Version < 2)
{
_Swell = false;
}
_Version = MigrateV2(_Version);
}
void ISerializationCallbackReceiver.OnBeforeSerialize()