升级6.4.升级水,升级天气
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Serialization;
|
||||
using WaveHarmonic.Crest.Internal;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
@@ -26,8 +27,11 @@ namespace WaveHarmonic.Crest
|
||||
[Tooltip("Whether to evaluate the spectrum every frame.\n\nWhen false, the wave spectrum is evaluated once on startup in editor play mode and standalone builds, rather than every frame. This is less flexible, but it reduces the performance cost significantly.")]
|
||||
[@GenerateAPI]
|
||||
[FormerlySerializedAs("_SpectrumFixedAtRuntime")]
|
||||
[@DecoratedField]
|
||||
[SerializeField]
|
||||
bool _EvaluateSpectrumAtRunTimeEveryFrame;
|
||||
private protected bool _EvaluateSpectrumAtRunTimeEveryFrame;
|
||||
|
||||
[@Space(10)]
|
||||
|
||||
[Tooltip("How much these waves respect the shallow water attenuation.\n\nAttenuation is defined on the Animated Waves. Set to zero to ignore attenuation.")]
|
||||
[@Range(0f, 1f)]
|
||||
@@ -35,6 +39,15 @@ namespace WaveHarmonic.Crest
|
||||
[SerializeField]
|
||||
float _RespectShallowWaterAttenuation = 1f;
|
||||
|
||||
[Tooltip("Whether global waves is applied above or below sea level.\n\nWaves are faded out to avoid hard transitionds. They are fully faded by 1m from sea level.")]
|
||||
[@Enable(nameof(_Mode), nameof(LodInputMode.Global))]
|
||||
[@GenerateAPI]
|
||||
[@DecoratedField]
|
||||
[SerializeField]
|
||||
bool _SeaLevelOnly = true;
|
||||
|
||||
[@Space(10)]
|
||||
|
||||
[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]
|
||||
@@ -42,8 +55,8 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
[@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)]
|
||||
[@Disable(nameof(_Mode), nameof(LodInputMode.Paint))]
|
||||
[@Show(nameof(_OverrideGlobalWindDirection))]
|
||||
[@ShowComputedProperty(nameof(WaveDirectionHeadingAngle))]
|
||||
[@Range(-180, 180)]
|
||||
[@GenerateAPI(Getter.Custom)]
|
||||
@@ -57,22 +70,32 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
[Tooltip("Wind speed in km/h. Controls wave conditions.")]
|
||||
[@ShowComputedProperty(nameof(WindSpeedKPH))]
|
||||
[@Predicated(nameof(_OverrideGlobalWindSpeed), hide: true)]
|
||||
[@Show(nameof(_OverrideGlobalWindSpeed))]
|
||||
[@Range(0, 150f, scale: 2f)]
|
||||
[@GenerateAPI]
|
||||
[SerializeField]
|
||||
float _WindSpeed = 20f;
|
||||
|
||||
|
||||
[Header("Generation Settings")]
|
||||
[@Heading("Generation Settings")]
|
||||
|
||||
[Tooltip("Resolution to use for wave generation buffers.\n\nLow resolutions are more efficient but can result in noticeable patterns in the shape.")]
|
||||
[@Stepped(16, 512, step: 2, power: true)]
|
||||
[@GenerateAPI]
|
||||
[@GenerateAPI(Getter.Custom)]
|
||||
[SerializeField]
|
||||
private protected int _Resolution = 128;
|
||||
|
||||
|
||||
[@Heading("Level of Detail")]
|
||||
|
||||
[Tooltip("Whether the maximum possible vertical displacement is used for the Drop Detail Height Based On Waves calculation.\n\nThis setting is ignored for global waves, as they always contribute. For local waves, only enable for large areas that are treated like global waves (eg a storm).")]
|
||||
[@Disable(nameof(_Mode), nameof(LodInputMode.Global))]
|
||||
[@GenerateAPI]
|
||||
[@DecoratedField]
|
||||
[SerializeField]
|
||||
bool _IncludeInDropDetailHeightBasedOnWaves;
|
||||
|
||||
|
||||
// Debug
|
||||
|
||||
[Tooltip("In Editor, shows the wave generation buffers on screen.")]
|
||||
@@ -92,6 +115,8 @@ namespace WaveHarmonic.Crest
|
||||
public static readonly int s_RespectShallowWaterAttenuation = Shader.PropertyToID("_Crest_RespectShallowWaterAttenuation");
|
||||
public static readonly int s_MaximumAttenuationDepth = Shader.PropertyToID("_Crest_MaximumAttenuationDepth");
|
||||
public static readonly int s_AxisX = Shader.PropertyToID("_Crest_AxisX");
|
||||
public static readonly int s_SeaLevelOnly = Shader.PropertyToID("_Crest_SeaLevelOnly");
|
||||
public static readonly int s_WaveBufferAttenuation = Shader.PropertyToID("_Crest_WaveBufferAttenuation");
|
||||
}
|
||||
|
||||
private protected virtual WaveSpectrum DefaultSpectrum => WindSpectrum;
|
||||
@@ -136,7 +161,7 @@ namespace WaveHarmonic.Crest
|
||||
/// <summary>
|
||||
/// The wind speed in meters per second (MPS).
|
||||
/// </summary>
|
||||
/// /// <remarks>
|
||||
/// <remarks>
|
||||
/// Wind speed can come from this component or the <see cref="WaterRenderer"/>.
|
||||
/// </remarks>
|
||||
public float WindSpeedMPS => WindSpeedKPH / 3.6f;
|
||||
@@ -150,13 +175,32 @@ namespace WaveHarmonic.Crest
|
||||
{
|
||||
base.Attach();
|
||||
_Reporter ??= new(this);
|
||||
WaterChunkRenderer.DisplacementReporters.Add(_Reporter);
|
||||
_DisplacementReporter = _Reporter;
|
||||
_WaveDisplacementReporter = _Reporter;
|
||||
}
|
||||
|
||||
private protected override void Detach()
|
||||
{
|
||||
base.Detach();
|
||||
WaterChunkRenderer.DisplacementReporters.Remove(_Reporter);
|
||||
_DisplacementReporter = null;
|
||||
_WaveDisplacementReporter = null;
|
||||
}
|
||||
|
||||
internal enum WindSpeedSource
|
||||
{
|
||||
None, // Wind Speed is at maximum.
|
||||
ShapeWaves,
|
||||
WaterRenderer,
|
||||
}
|
||||
|
||||
internal WindSpeedSource GetWindSpeedSource()
|
||||
{
|
||||
if (WindSpeedKPH >= WaterRenderer.k_MaximumWindSpeedKPH)
|
||||
{
|
||||
return WindSpeedSource.None;
|
||||
}
|
||||
|
||||
return OverrideGlobalWindSpeed ? WindSpeedSource.ShapeWaves : WindSpeedSource.WaterRenderer;
|
||||
}
|
||||
|
||||
internal override void Draw(Lod simulation, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1f, int slice = -1)
|
||||
@@ -173,30 +217,32 @@ namespace WaveHarmonic.Crest
|
||||
return;
|
||||
}
|
||||
|
||||
var lodCount = simulation.Slices;
|
||||
|
||||
var shape = (AnimatedWavesLod)simulation;
|
||||
|
||||
var wrapper = new PropertyWrapperCompute(buffer, s_TransferWavesComputeShader, 0);
|
||||
|
||||
if (_FirstCascade < 0 || _LastCascade < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var lodCount = simulation.Slices;
|
||||
var lodResolution = simulation.Resolution;
|
||||
var shape = (AnimatedWavesLod)simulation;
|
||||
|
||||
var wrapper = new PropertyWrapperCompute(buffer, s_TransferWavesComputeShader, 0);
|
||||
|
||||
// Write to per-octave _WaveBuffers (ie pre-combined). Not the same as _AnimatedWaves.
|
||||
wrapper.SetTexture(Crest.ShaderIDs.s_Target, target);
|
||||
// Input weight. Weight for each octave calculated in compute.
|
||||
wrapper.SetFloat(LodInput.ShaderIDs.s_Weight, Weight);
|
||||
|
||||
wrapper.SetInteger(Crest.ShaderIDs.s_Resolution, Resolution);
|
||||
|
||||
var water = shape._Water;
|
||||
|
||||
for (var lodIdx = lodCount - 1; lodIdx >= lodCount - slice; lodIdx--)
|
||||
{
|
||||
_WaveBufferParameters[lodIdx] = new(-1, -2, 0, 0);
|
||||
_WaveBufferParameters[lodIdx] = new(-1, -2, 0, 1);
|
||||
|
||||
var found = false;
|
||||
var filter = new AnimatedWavesLod.WavelengthFilter(water, lodIdx);
|
||||
var filter = new AnimatedWavesLod.WavelengthFilter(water, lodIdx, lodResolution);
|
||||
|
||||
for (var i = _FirstCascade; i <= _LastCascade; i++)
|
||||
{
|
||||
@@ -221,13 +267,17 @@ namespace WaveHarmonic.Crest
|
||||
}
|
||||
|
||||
// Set transitional weights.
|
||||
_WaveBufferParameters[lodCount - 2].w = 1f - water.ViewerAltitudeLevelAlpha;
|
||||
if (!shape.PreserveWaveQuality)
|
||||
{
|
||||
_WaveBufferParameters[lodCount - 2].w = 1f - water.ViewerAltitudeLevelAlpha;
|
||||
}
|
||||
|
||||
_WaveBufferParameters[lodCount - 1].w = water.ViewerAltitudeLevelAlpha;
|
||||
|
||||
SetRenderParameters(water, wrapper);
|
||||
|
||||
wrapper.SetFloat(ShaderIDs.s_WaveResolutionMultiplier, shape.WaveResolutionMultiplier);
|
||||
wrapper.SetFloat(ShaderIDs.s_TransitionalWavelengthThreshold, water.MaximumWavelength(water.LodLevels - 1) * 0.5f);
|
||||
wrapper.SetFloat(ShaderIDs.s_TransitionalWavelengthThreshold, water.MaximumWavelength(water.LodLevels - 1, simulation.Resolution) * 0.5f);
|
||||
wrapper.SetVectorArray(ShaderIDs.s_WaveBufferParameters, _WaveBufferParameters);
|
||||
|
||||
var isTexture = Mode is LodInputMode.Paint or LodInputMode.Texture;
|
||||
@@ -236,6 +286,8 @@ namespace WaveHarmonic.Crest
|
||||
wrapper.SetKeyword(s_KeywordTexture, isTexture && !isAlphaBlend);
|
||||
wrapper.SetKeyword(s_KeywordTextureBlend, isTexture && isAlphaBlend);
|
||||
|
||||
wrapper.SetFloatArray(ShaderIDs.s_WaveBufferAttenuation, _ActiveSpectrum._Attenuation);
|
||||
|
||||
if (isTexture)
|
||||
{
|
||||
wrapper.SetInteger(Crest.ShaderIDs.s_Blend, (int)_Blend);
|
||||
@@ -243,6 +295,8 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
if (Mode == LodInputMode.Global)
|
||||
{
|
||||
wrapper.SetBoolean(ShaderIDs.s_SeaLevelOnly, _SeaLevelOnly);
|
||||
|
||||
var threads = shape.Resolution / Lod.k_ThreadGroupSize;
|
||||
wrapper.Dispatch(threads, threads, slice);
|
||||
}
|
||||
@@ -255,6 +309,7 @@ namespace WaveHarmonic.Crest
|
||||
void GraphicsDraw(Lod simulation, CommandBuffer buffer, RenderTargetIdentifier target, int pass, float weight, int slice)
|
||||
{
|
||||
var lod = simulation as AnimatedWavesLod;
|
||||
var lodResolution = simulation.Resolution;
|
||||
|
||||
var wrapper = new PropertyWrapperBuffer(buffer);
|
||||
SetRenderParameters(simulation._Water, wrapper);
|
||||
@@ -266,7 +321,7 @@ namespace WaveHarmonic.Crest
|
||||
_Wavelength = MinWavelength(i) / lod.WaveResolutionMultiplier;
|
||||
|
||||
// Do the weight from scratch because this is the real filter.
|
||||
weight = AnimatedWavesLod.FilterByWavelength(simulation._Water, slice, _Wavelength) * Weight;
|
||||
weight = AnimatedWavesLod.FilterByWavelength(simulation._Water, slice, _Wavelength, lodResolution) * Weight;
|
||||
if (weight <= 0f) continue;
|
||||
|
||||
var average = _Wavelength * 1.5f * lod.WaveResolutionMultiplier;
|
||||
@@ -411,40 +466,101 @@ namespace WaveHarmonic.Crest
|
||||
s_KeywordTextureBlend = WaterResources.Instance.Keywords.AnimatedWavesTransferWavesTextureBlend;
|
||||
}
|
||||
|
||||
bool ReportDisplacement(ref Rect bounds, ref float horizontal, ref float vertical)
|
||||
bool ReportDisplacement(WaterRenderer water, ref Rect bounds, ref float horizontal, ref float vertical)
|
||||
{
|
||||
if (Mode == LodInputMode.Global || !Enabled)
|
||||
if (!Enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Mode == LodInputMode.Global)
|
||||
{
|
||||
// Global is always additive.
|
||||
horizontal += MaximumReportedHorizontalDisplacement;
|
||||
vertical += MaximumReportedVerticalDisplacement;
|
||||
return true;
|
||||
}
|
||||
|
||||
_Rect = Data.Rect;
|
||||
|
||||
if (bounds.Overlaps(_Rect, false))
|
||||
{
|
||||
horizontal = MaximumReportedHorizontalDisplacement;
|
||||
vertical = MaximumReportedVerticalDisplacement;
|
||||
var nh = horizontal;
|
||||
var nv = vertical;
|
||||
switch (Blend)
|
||||
{
|
||||
case LodInputBlend.Off:
|
||||
nh = MaximumReportedHorizontalDisplacement;
|
||||
nv = MaximumReportedVerticalDisplacement;
|
||||
break;
|
||||
case LodInputBlend.Additive:
|
||||
nh += MaximumReportedHorizontalDisplacement;
|
||||
nv += MaximumReportedVerticalDisplacement;
|
||||
break;
|
||||
case LodInputBlend.Alpha:
|
||||
case LodInputBlend.AlphaClip:
|
||||
nh = Mathf.Max(nh, MaximumReportedHorizontalDisplacement);
|
||||
nv = Mathf.Max(nh, MaximumReportedVerticalDisplacement);
|
||||
break;
|
||||
}
|
||||
|
||||
horizontal = Mathf.Max(horizontal, nh);
|
||||
vertical = Mathf.Max(vertical, nv);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float ReportWaveDisplacement(WaterRenderer water, float displacement)
|
||||
{
|
||||
if (Mode == LodInputMode.Global)
|
||||
{
|
||||
return displacement + MaximumReportedWavesDisplacement;
|
||||
}
|
||||
|
||||
if (!_IncludeInDropDetailHeightBasedOnWaves)
|
||||
{
|
||||
return displacement;
|
||||
}
|
||||
|
||||
// TODO: use bounds to transition slowly to avoid pops.
|
||||
if (_Rect.Contains(water.Position.XZ()))
|
||||
{
|
||||
displacement = Blend switch
|
||||
{
|
||||
LodInputBlend.Off => MaximumReportedWavesDisplacement,
|
||||
LodInputBlend.Additive => displacement + MaximumReportedWavesDisplacement,
|
||||
LodInputBlend.Alpha or LodInputBlend.AlphaClip => Mathf.Max(displacement, MaximumReportedWavesDisplacement),
|
||||
_ => MaximumReportedWavesDisplacement,
|
||||
};
|
||||
}
|
||||
|
||||
return displacement;
|
||||
}
|
||||
|
||||
float GetWaveDirectionHeadingAngle()
|
||||
{
|
||||
return _OverrideGlobalWindDirection || WaterRenderer.Instance == null ? _WaveDirectionHeadingAngle : WaterRenderer.Instance.WindDirection;
|
||||
}
|
||||
|
||||
internal int GetResolution()
|
||||
{
|
||||
return Mathf.Clamp(_Resolution, MinimumResolution, MaximumResolution);
|
||||
}
|
||||
}
|
||||
|
||||
partial class ShapeWaves
|
||||
{
|
||||
Reporter _Reporter;
|
||||
|
||||
sealed class Reporter : IReportsDisplacement
|
||||
sealed class Reporter : IReportsDisplacement, IReportWaveDisplacement
|
||||
{
|
||||
readonly ShapeWaves _Input;
|
||||
public Reporter(ShapeWaves input) => _Input = input;
|
||||
public bool ReportDisplacement(ref Rect bounds, ref float horizontal, ref float vertical) => _Input.ReportDisplacement(ref bounds, ref horizontal, ref vertical);
|
||||
public bool ReportDisplacement(WaterRenderer water, ref Rect bounds, ref float horizontal, ref float vertical) => _Input.ReportDisplacement(water, ref bounds, ref horizontal, ref vertical);
|
||||
public float ReportWaveDisplacement(WaterRenderer water, float displacement) => _Input.ReportWaveDisplacement(water, displacement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,6 +581,7 @@ namespace WaveHarmonic.Crest
|
||||
if (s_WindSpectrum != null)
|
||||
{
|
||||
Helpers.Destroy(s_WindSpectrum);
|
||||
s_WindSpectrum = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -472,16 +589,20 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
partial class ShapeWaves
|
||||
{
|
||||
private protected override int Version => Mathf.Max(base.Version, 3);
|
||||
|
||||
[HideInInspector, SerializeField]
|
||||
AlphaSource _AlphaSource;
|
||||
enum AlphaSource { AlwaysOne, FromZero, FromZeroNormalized }
|
||||
|
||||
private protected int MigrateV1(int version)
|
||||
private protected override void OnMigrate()
|
||||
{
|
||||
base.OnMigrate();
|
||||
|
||||
// Version 1
|
||||
// - Merge Alpha Source into Blend.
|
||||
// - Rename and invert Spectrum Fixed at Run-Time
|
||||
if (version < 1)
|
||||
if (_Version < 1)
|
||||
{
|
||||
if (_Blend == LodInputBlend.Alpha)
|
||||
{
|
||||
@@ -495,24 +616,19 @@ namespace WaveHarmonic.Crest
|
||||
}
|
||||
|
||||
_EvaluateSpectrumAtRunTimeEveryFrame = !_EvaluateSpectrumAtRunTimeEveryFrame;
|
||||
|
||||
version = 1;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
private protected int MigrateV2(int version)
|
||||
{
|
||||
// Version 2
|
||||
// - Global wind direction
|
||||
if (version < 2)
|
||||
if (_Version < 2)
|
||||
{
|
||||
_OverrideGlobalWindDirection = true;
|
||||
version = 2;
|
||||
}
|
||||
|
||||
return version;
|
||||
if (_Version < 3)
|
||||
{
|
||||
_SeaLevelOnly = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user