升级水插件
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user