升级水插件
This commit is contained in:
@@ -14,14 +14,21 @@ namespace WaveHarmonic.Crest
|
||||
{
|
||||
// Waves
|
||||
|
||||
[Tooltip("How turbulent/chaotic the waves are.")]
|
||||
[@Range(0, 1, order = -3)]
|
||||
[Tooltip("Whether to use the wind turbulence on this component rather than the global wind turbulence.\n\nGlobal wind turbulence comes from the Water Renderer component.")]
|
||||
[@GenerateAPI]
|
||||
[@InlineToggle(order = -3), SerializeField]
|
||||
bool _OverrideGlobalWindTurbulence;
|
||||
|
||||
[Tooltip("How turbulent/chaotic the waves are.")]
|
||||
[@Predicated(nameof(_OverrideGlobalWindTurbulence), hide: true)]
|
||||
[@ShowComputedProperty(nameof(WindTurbulence))]
|
||||
[@Range(0, 1, order = -4)]
|
||||
[@GenerateAPI(Getter.Custom)]
|
||||
[SerializeField]
|
||||
float _WindTurbulence = 0.145f;
|
||||
|
||||
[Tooltip("How aligned the waves are with wind.")]
|
||||
[@Range(0, 1, order = -4)]
|
||||
[@Range(0, 1, order = -5)]
|
||||
[@GenerateAPI]
|
||||
[SerializeField]
|
||||
float _WindAlignment;
|
||||
@@ -51,23 +58,39 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
[@Heading("Collision Data Baking")]
|
||||
|
||||
#if !d_WaveHarmonic_Crest_CPUQueries
|
||||
[HideInInspector]
|
||||
#endif
|
||||
|
||||
[Tooltip("Enable running this FFT with baked data.\n\nThis makes the FFT periodic (repeating in time).")]
|
||||
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)]
|
||||
[@DecoratedField, SerializeField]
|
||||
internal bool _EnableBakedCollision = false;
|
||||
|
||||
#if !d_WaveHarmonic_Crest_CPUQueries
|
||||
[HideInInspector]
|
||||
#endif
|
||||
|
||||
[Tooltip("Frames per second of baked data.\n\nLarger values may help the collision track the surface closely at the cost of more frames and increase baked data size.")]
|
||||
[@Predicated(nameof(_EnableBakedCollision))]
|
||||
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)]
|
||||
[@DecoratedField, SerializeField]
|
||||
internal int _TimeResolution = 4;
|
||||
|
||||
#if !d_WaveHarmonic_Crest_CPUQueries
|
||||
[HideInInspector]
|
||||
#endif
|
||||
|
||||
[Tooltip("Smallest wavelength required in collision.\n\nTo preview the effect of this, disable power sliders in spectrum for smaller values than this number. Smaller values require more resolution and increase baked data size.")]
|
||||
[@Predicated(nameof(_EnableBakedCollision))]
|
||||
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)]
|
||||
[@DecoratedField, SerializeField]
|
||||
internal float _SmallestWavelengthRequired = 2f;
|
||||
|
||||
#if !d_WaveHarmonic_Crest_CPUQueries
|
||||
[HideInInspector]
|
||||
#endif
|
||||
|
||||
[Tooltip("FFT waves will loop with a period of this many seconds.\n\nSmaller values decrease data size but can make waves visibly repetitive.")]
|
||||
[@Predicated(nameof(_EnableBakedCollision))]
|
||||
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)]
|
||||
@@ -75,21 +98,28 @@ namespace WaveHarmonic.Crest
|
||||
[SerializeField]
|
||||
internal float _BakedTimeLoopLength = 32f;
|
||||
|
||||
internal float LoopPeriod => _EnableBakedCollision ? _BakedTimeLoopLength : _TimeLoopLength;
|
||||
internal float LoopPeriod =>
|
||||
#if d_WaveHarmonic_Crest_CPUQueries
|
||||
_EnableBakedCollision ? _BakedTimeLoopLength :
|
||||
#endif
|
||||
_TimeLoopLength;
|
||||
|
||||
private protected override int MinimumResolution => 16;
|
||||
private protected override int MaximumResolution => int.MaxValue;
|
||||
|
||||
FFTCompute _FFTCompute;
|
||||
|
||||
FFTCompute.Parameters _OldFFTParameters;
|
||||
internal FFTCompute.Parameters FFTParameters => new
|
||||
internal FFTCompute.Parameters GetFFTParameters(float gravity) => new
|
||||
(
|
||||
_ActiveSpectrum,
|
||||
Resolution,
|
||||
_TimeLoopLength,
|
||||
WindSpeedMPS,
|
||||
WindDirRadForFFT,
|
||||
_WindTurbulence,
|
||||
_WindAlignment
|
||||
WindTurbulence,
|
||||
_WindAlignment,
|
||||
gravity
|
||||
);
|
||||
|
||||
private protected override void OnUpdate(WaterRenderer water)
|
||||
@@ -103,7 +133,7 @@ namespace WaveHarmonic.Crest
|
||||
ReportMaxDisplacement(water);
|
||||
|
||||
// If geometry is being used, the water input shader will rotate the waves to align to geo
|
||||
var parameters = FFTParameters;
|
||||
var parameters = GetFFTParameters(water.Gravity);
|
||||
|
||||
// Don't create tons of generators when values are varying. Notify so that existing generators may be adapted.
|
||||
if (parameters.GetHashCode() != _OldFFTParameters.GetHashCode())
|
||||
@@ -111,6 +141,10 @@ namespace WaveHarmonic.Crest
|
||||
FFTCompute.OnGenerationDataUpdated(_OldFFTParameters, parameters);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
_FFTCompute = FFTCompute.GetInstance(parameters);
|
||||
#endif
|
||||
|
||||
_OldFFTParameters = parameters;
|
||||
}
|
||||
|
||||
@@ -118,14 +152,22 @@ namespace WaveHarmonic.Crest
|
||||
{
|
||||
if (_LastGenerateFrameCount != Time.frameCount)
|
||||
{
|
||||
// Parameters will unlikely change as our Update is called in LateUpdate with Draw
|
||||
// not too far after.
|
||||
var parameters = GetFFTParameters(lod.Water.Gravity);
|
||||
|
||||
_WaveBuffers = FFTCompute.GenerateDisplacements
|
||||
(
|
||||
buffer,
|
||||
lod.Water.CurrentTime,
|
||||
FFTParameters,
|
||||
parameters,
|
||||
UpdateDataEachFrame
|
||||
);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
_FFTCompute = FFTCompute.GetInstance(parameters);
|
||||
#endif
|
||||
|
||||
_LastGenerateFrameCount = Time.frameCount;
|
||||
}
|
||||
|
||||
@@ -157,11 +199,6 @@ namespace WaveHarmonic.Crest
|
||||
}
|
||||
}
|
||||
|
||||
private protected override void DestroySharedResources()
|
||||
{
|
||||
FFTCompute.CleanUpAll();
|
||||
}
|
||||
|
||||
float WindDirRadForFFT
|
||||
{
|
||||
get
|
||||
@@ -172,36 +209,64 @@ namespace WaveHarmonic.Crest
|
||||
return 0f;
|
||||
}
|
||||
|
||||
return _WaveDirectionHeadingAngle * Mathf.Deg2Rad;
|
||||
return WaveDirectionHeadingAngle * Mathf.Deg2Rad;
|
||||
}
|
||||
}
|
||||
|
||||
float GetWindTurbulence()
|
||||
{
|
||||
return _OverrideGlobalWindTurbulence || WaterRenderer.Instance == null ? _WindTurbulence : WaterRenderer.Instance.WindTurbulence;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnGUI()
|
||||
{
|
||||
if (_DrawSlicesInEditor)
|
||||
{
|
||||
FFTCompute.GetInstance(FFTParameters)?.OnGUI();
|
||||
_FFTCompute?.OnGUI();
|
||||
}
|
||||
}
|
||||
|
||||
internal FFTCompute GetFFTComputeInstance()
|
||||
{
|
||||
return FFTCompute.GetInstance(FFTParameters);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
partial class ShapeFFT
|
||||
{
|
||||
static int s_InstanceCount;
|
||||
|
||||
private protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
s_InstanceCount++;
|
||||
}
|
||||
|
||||
private protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
|
||||
if (--s_InstanceCount <= 0)
|
||||
{
|
||||
FFTCompute.CleanUpAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial class ShapeFFT : 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)
|
||||
{
|
||||
_OverrideGlobalWindTurbulence = true;
|
||||
}
|
||||
|
||||
_Version = MigrateV2(_Version);
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
@@ -209,4 +274,19 @@ namespace WaveHarmonic.Crest
|
||||
// Empty.
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
partial class ShapeFFT
|
||||
{
|
||||
private protected override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
if (_Mode != LodInputMode.Global)
|
||||
{
|
||||
_OverrideGlobalWindTurbulence = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace WaveHarmonic.Crest
|
||||
[@Heading("Waves")]
|
||||
|
||||
[Tooltip("The spectrum that defines the water surface shape.")]
|
||||
[@Embedded]
|
||||
[@Embedded(defaultPropertyName: nameof(_ActiveSpectrum))]
|
||||
[@GenerateAPI]
|
||||
[SerializeField]
|
||||
internal WaveSpectrum _Spectrum;
|
||||
@@ -35,17 +35,25 @@ namespace WaveHarmonic.Crest
|
||||
[SerializeField]
|
||||
float _RespectShallowWaterAttenuation = 1f;
|
||||
|
||||
[Tooltip("Whether to use the wind direction on this component rather than the global wind direction.\n\nGlobal wind direction comes from the Water Renderer component.")]
|
||||
[@GenerateAPI]
|
||||
[@InlineToggle, SerializeField]
|
||||
bool _OverrideGlobalWindDirection;
|
||||
|
||||
[@Label("Wind Direction")]
|
||||
[Tooltip("Primary wave direction heading (degrees).\n\nThis is the angle from x axis in degrees that the waves are oriented towards. If a spline is being used to place the waves, this angle is relative to the spline.")]
|
||||
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Paint))]
|
||||
[@Predicated(nameof(_OverrideGlobalWindDirection), hide: true)]
|
||||
[@ShowComputedProperty(nameof(WaveDirectionHeadingAngle))]
|
||||
[@Range(-180, 180)]
|
||||
[@GenerateAPI]
|
||||
[@GenerateAPI(Getter.Custom)]
|
||||
[SerializeField]
|
||||
private protected float _WaveDirectionHeadingAngle = 0f;
|
||||
|
||||
[Tooltip("Whether to use the wind speed on this component rather than the global wind speed.\n\nGlobal wind speed comes from the Water Renderer component.")]
|
||||
[@GenerateAPI]
|
||||
[SerializeField]
|
||||
bool _OverrideGlobalWindSpeed = false;
|
||||
[@InlineToggle, SerializeField]
|
||||
bool _OverrideGlobalWindSpeed;
|
||||
|
||||
[Tooltip("Wind speed in km/h. Controls wave conditions.")]
|
||||
[@ShowComputedProperty(nameof(WindSpeedKPH))]
|
||||
@@ -86,19 +94,21 @@ namespace WaveHarmonic.Crest
|
||||
public static readonly int s_AxisX = Shader.PropertyToID("_Crest_AxisX");
|
||||
}
|
||||
|
||||
static WaveSpectrum s_DefaultSpectrum;
|
||||
private protected static WaveSpectrum DefaultSpectrum
|
||||
private protected virtual WaveSpectrum DefaultSpectrum => WindSpectrum;
|
||||
|
||||
static WaveSpectrum s_WindSpectrum;
|
||||
private protected static WaveSpectrum WindSpectrum
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_DefaultSpectrum == null)
|
||||
if (s_WindSpectrum == null)
|
||||
{
|
||||
s_DefaultSpectrum = ScriptableObject.CreateInstance<WaveSpectrum>();
|
||||
s_DefaultSpectrum.name = "Default Waves (instance)";
|
||||
s_DefaultSpectrum.hideFlags = HideFlags.DontSave | HideFlags.NotEditable;
|
||||
s_WindSpectrum = ScriptableObject.CreateInstance<WaveSpectrum>();
|
||||
s_WindSpectrum.name = "Wind Waves (instance)";
|
||||
s_WindSpectrum.hideFlags = HideFlags.DontSave | HideFlags.NotEditable;
|
||||
}
|
||||
|
||||
return s_DefaultSpectrum;
|
||||
return s_WindSpectrum;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +123,7 @@ namespace WaveHarmonic.Crest
|
||||
internal static int s_RenderPassOverride = -1;
|
||||
|
||||
private protected WaveSpectrum _ActiveSpectrum = null;
|
||||
private protected Vector2 PrimaryWaveDirection => new(Mathf.Cos(Mathf.PI * _WaveDirectionHeadingAngle / 180f), Mathf.Sin(Mathf.PI * _WaveDirectionHeadingAngle / 180f));
|
||||
private protected Vector2 PrimaryWaveDirection => new(Mathf.Cos(Mathf.PI * WaveDirectionHeadingAngle / 180f), Mathf.Sin(Mathf.PI * WaveDirectionHeadingAngle / 180f));
|
||||
|
||||
/// <summary>
|
||||
/// The wind speed in kilometers per hour (KPH).
|
||||
@@ -121,7 +131,7 @@ namespace WaveHarmonic.Crest
|
||||
/// <remarks>
|
||||
/// Wind speed can come from this component or the <see cref="WaterRenderer"/>.
|
||||
/// </remarks>
|
||||
public float WindSpeedKPH => _OverrideGlobalWindSpeed || WaterRenderer.Instance == null ? _WindSpeed : WaterRenderer.Instance.WindSpeedKPH;
|
||||
public float WindSpeedKPH => _OverrideGlobalWindSpeed || WaterRenderer.Instance == null ? _WindSpeed : WaterRenderer.Instance.WindSpeed;
|
||||
|
||||
/// <summary>
|
||||
/// The wind speed in meters per second (MPS).
|
||||
@@ -301,7 +311,7 @@ namespace WaveHarmonic.Crest
|
||||
// Wave generation done in Draw. Keeps track to limit to once per frame.
|
||||
private protected int _LastGenerateFrameCount = -1;
|
||||
|
||||
internal override bool Enabled => _FirstCascade > -1 && WaterRenderer.Instance.Gravity != 0f && Mode switch
|
||||
internal override bool Enabled => _FirstCascade > -1 && (WaterRenderer.Instance == null || WaterRenderer.Instance.Gravity != 0f) && Mode switch
|
||||
{
|
||||
LodInputMode.Global => enabled && s_TransferWavesComputeShader != null,
|
||||
_ => base.Enabled,
|
||||
@@ -324,7 +334,6 @@ namespace WaveHarmonic.Crest
|
||||
private protected float MaximumReportedVerticalDisplacement { get; set; }
|
||||
private protected float MaximumReportedWavesDisplacement { get; set; }
|
||||
|
||||
static int s_InstanceCount = 0;
|
||||
|
||||
private protected bool UpdateDataEachFrame
|
||||
{
|
||||
@@ -349,7 +358,6 @@ namespace WaveHarmonic.Crest
|
||||
}
|
||||
|
||||
private protected abstract void ReportMaxDisplacement(WaterRenderer water);
|
||||
private protected abstract void DestroySharedResources();
|
||||
|
||||
private protected override void OnUpdate(WaterRenderer water)
|
||||
{
|
||||
@@ -367,26 +375,6 @@ namespace WaveHarmonic.Crest
|
||||
wrapper.SetFloat(ShaderIDs.s_MaximumAttenuationDepth, water._AnimatedWavesLod.ShallowsMaximumDepth);
|
||||
}
|
||||
|
||||
private protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
s_InstanceCount++;
|
||||
}
|
||||
|
||||
private protected void OnDestroy()
|
||||
{
|
||||
// Since FFTCompute resources are shared we will clear after last ShapeFFT is destroyed.
|
||||
if (--s_InstanceCount <= 0)
|
||||
{
|
||||
DestroySharedResources();
|
||||
|
||||
if (s_DefaultSpectrum != null)
|
||||
{
|
||||
Helpers.Destroy(s_DefaultSpectrum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -441,6 +429,11 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float GetWaveDirectionHeadingAngle()
|
||||
{
|
||||
return _OverrideGlobalWindDirection || WaterRenderer.Instance == null ? _WaveDirectionHeadingAngle : WaterRenderer.Instance.WindDirection;
|
||||
}
|
||||
}
|
||||
|
||||
partial class ShapeWaves
|
||||
@@ -455,6 +448,28 @@ namespace WaveHarmonic.Crest
|
||||
}
|
||||
}
|
||||
|
||||
partial class ShapeWaves
|
||||
{
|
||||
static int s_InstanceCount = 0;
|
||||
|
||||
private protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
s_InstanceCount++;
|
||||
}
|
||||
|
||||
private protected virtual void OnDestroy()
|
||||
{
|
||||
if (--s_InstanceCount <= 0)
|
||||
{
|
||||
if (s_WindSpectrum != null)
|
||||
{
|
||||
Helpers.Destroy(s_WindSpectrum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial class ShapeWaves
|
||||
{
|
||||
[HideInInspector, SerializeField]
|
||||
@@ -486,5 +501,34 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
private protected int MigrateV2(int version)
|
||||
{
|
||||
// Version 2
|
||||
// - Global wind direction
|
||||
if (version < 2)
|
||||
{
|
||||
_OverrideGlobalWindDirection = true;
|
||||
version = 2;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
partial class ShapeWaves
|
||||
{
|
||||
private protected override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
if (_Mode != LodInputMode.Global)
|
||||
{
|
||||
_OverrideGlobalWindSpeed = true;
|
||||
_OverrideGlobalWindDirection = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user