还原水插件

This commit is contained in:
2026-03-05 00:14:42 +08:00
parent 0de35591e7
commit e82f2ea6b7
270 changed files with 2773 additions and 12445 deletions

View File

@@ -63,35 +63,23 @@ namespace WaveHarmonic.Crest
_FollowHorizontalWaveMotion = true;
}
private protected override void Initialize()
{
base.Initialize();
_Reporter ??= new(this);
_DisplacementReporter = _Reporter;
}
private protected override void OnDisable()
{
base.OnDisable();
_DisplacementReporter = null;
}
internal override float Filter(WaterRenderer water, int slice)
{
return AnimatedWavesLod.FilterByWavelength(water, slice, _FilterByWavelength ? _OctaveWavelength : 0f);
}
bool ReportDisplacement(WaterRenderer water, ref Rect bounds, ref float horizontal, ref float vertical)
private protected override void OnUpdate(WaterRenderer water)
{
base.OnUpdate(water);
if (!Enabled)
{
return false;
return;
}
var maxDispVert = _MaximumDisplacementVertical;
// let water system know how far from the sea level this shape may displace the surface
// TODO: we need separate min/max vertical displacement to be optimal.
if (_ReportRendererBounds)
{
var range = Data.HeightRange;
@@ -101,34 +89,10 @@ namespace WaveHarmonic.Crest
maxDispVert = Mathf.Max(maxDispVert, Mathf.Abs(seaLevel - minY), Mathf.Abs(seaLevel - maxY));
}
var rect = Data.Rect;
if (bounds.Overlaps(rect, false))
if (_MaximumDisplacementHorizontal > 0f || maxDispVert > 0f)
{
horizontal += _MaximumDisplacementHorizontal;
vertical += maxDispVert;
return true;
water.ReportMaximumDisplacement(_MaximumDisplacementHorizontal, maxDispVert, 0f);
}
return false;
}
float ReportWaveDisplacement(WaterRenderer water, float displacement)
{
return displacement;
}
}
partial class AnimatedWavesLodInput
{
Reporter _Reporter;
sealed class Reporter : IReportsDisplacement, IReportWaveDisplacement
{
readonly AnimatedWavesLodInput _Input;
public Reporter(AnimatedWavesLodInput input) => _Input = input;
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);
}
}

View File

@@ -2,7 +2,6 @@
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using WaveHarmonic.Crest.Internal;
namespace WaveHarmonic.Crest
{
@@ -39,6 +38,8 @@ namespace WaveHarmonic.Crest
private protected override bool FollowHorizontalMotion => true;
internal override LodInputMode DefaultMode => LodInputMode.Geometry;
internal Rect _Rect;
internal override void InferBlend()
{
base.InferBlend();
@@ -55,60 +56,35 @@ namespace WaveHarmonic.Crest
{
base.Initialize();
_Reporter ??= new(this);
_HeightReporter = _Reporter;
WaterChunkRenderer.HeightReporters.Add(_Reporter);
}
private protected override void OnDisable()
{
base.OnDisable();
_HeightReporter = null;
WaterChunkRenderer.HeightReporters.Remove(_Reporter);
}
bool ReportHeight(WaterRenderer water, ref Rect bounds, ref float minimum, ref float maximum)
bool ReportHeight(ref Rect bounds, ref float minimum, ref float maximum)
{
if (!Enabled)
{
return false;
}
_Rect = Data.Rect;
// These modes do not provide a height yet.
if (!Data.HasHeightRange && !_OverrideHeight)
{
return false;
}
var rect = Data.Rect;
if (bounds.Overlaps(rect, false))
if (bounds.Overlaps(_Rect, false))
{
var range = _OverrideHeight ? _HeightRange : Data.HeightRange;
range *= Weight;
// Make relative to sea level.
range.x -= water.SeaLevel;
range.y -= water.SeaLevel;
var r = new Vector2(minimum, maximum);
range = _Blend switch
{
LodInputBlend.Additive => range + r,
LodInputBlend.Minimum => Vector2.Min(range, r),
LodInputBlend.Maximum => Vector2.Max(range, r),
_ => range,
};
if (rect.Encapsulates(bounds))
{
minimum = range.x;
maximum = range.y;
}
else
{
minimum = Mathf.Min(minimum, range.x);
maximum = Mathf.Max(maximum, range.y);
}
minimum = range.x;
maximum = range.y;
return true;
}
@@ -124,8 +100,7 @@ namespace WaveHarmonic.Crest
{
readonly LevelLodInput _Input;
public Reporter(LevelLodInput input) => _Input = input;
public bool ReportHeight(WaterRenderer water, ref Rect bounds, ref float minimum, ref float maximum) =>
_Input.ReportHeight(water, ref bounds, ref minimum, ref maximum);
public bool ReportHeight(ref Rect bounds, ref float minimum, ref float maximum) => _Input.ReportHeight(ref bounds, ref minimum, ref maximum);
}
}

View File

@@ -36,10 +36,6 @@ namespace WaveHarmonic.Crest
MonoBehaviour Component { get; }
IReportsHeight HeightReporter => null;
IReportsDisplacement DisplacementReporter => null;
IReportWaveDisplacement WaveDisplacementReporter => null;
// Allow sorting within a queue. Callers can pass in things like sibling index to
// get deterministic sorting.
int Order => Queue * k_QueueMaximumSubIndex + Mathf.Min(Component.transform.GetSiblingIndex(), k_QueueMaximumSubIndex - 1);
@@ -380,16 +376,6 @@ namespace WaveHarmonic.Crest
//
#if UNITY_EDITOR
void SetMode(LodInputMode previous, LodInputMode current)
{
if (previous == current) return;
if (!isActiveAndEnabled) { ChangeMode(Mode); return; }
OnDisable();
ChangeMode(Mode);
UnityEditor.EditorTools.ToolManager.RefreshAvailableTools();
OnEnable();
}
[@OnChange(skipIfInactive: false)]
void OnChange(string propertyPath, object previousValue)
{
@@ -399,7 +385,11 @@ namespace WaveHarmonic.Crest
SetQueue((int)previousValue, _Queue);
break;
case nameof(_Mode):
SetMode((LodInputMode)previousValue, Mode);
if (!isActiveAndEnabled) { ChangeMode(Mode); break; }
OnDisable();
ChangeMode(Mode);
UnityEditor.EditorTools.ToolManager.RefreshAvailableTools();
OnEnable();
break;
case nameof(_Blend):
// TODO: Make compatible with disabled.
@@ -477,9 +467,6 @@ namespace WaveHarmonic.Crest
partial class LodInput
{
Input _Input;
private protected IReportsHeight _HeightReporter;
internal IReportsDisplacement _DisplacementReporter;
private protected IReportWaveDisplacement _WaveDisplacementReporter;
sealed class Input : ILodInput
{
@@ -491,9 +478,6 @@ namespace WaveHarmonic.Crest
public int Pass => _Input.Pass;
public Rect Rect => _Input.Rect;
public MonoBehaviour Component => _Input;
public IReportsHeight HeightReporter => _Input._HeightReporter;
public IReportsDisplacement DisplacementReporter => _Input._DisplacementReporter;
public IReportWaveDisplacement WaveDisplacementReporter => _Input._WaveDisplacementReporter;
public float Filter(WaterRenderer water, int slice) => _Input.Filter(water, slice);
public void Draw(Lod lod, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1, int slice = -1) => _Input.Draw(lod, buffer, target, pass, weight, slice);
}

View File

@@ -2,15 +2,10 @@
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using WaveHarmonic.Crest.Internal;
using WaveHarmonic.Crest.Utility;
#if !UNITY_6000_0_OR_NEWER
using GraphicsFormatUsage = UnityEngine.Experimental.Rendering.FormatUsage;
#endif
namespace WaveHarmonic.Crest
{
/// <summary>
@@ -363,17 +358,16 @@ namespace WaveHarmonic.Crest
return texture != null &&
texture.width != _Resolution ||
texture.height != _Resolution ||
texture.graphicsFormat != (target ? SystemInfo.GetGraphicsFormat(DefaultFormat.DepthStencil) : FinalFormat);
texture.format != (target ? RenderTextureFormat.Depth : FinalFormat);
}
GraphicsFormat FinalFormat => _GenerateSignedDistanceField ? Helpers.GetCompatibleTextureFormat(GraphicsFormat.R32G32_SFloat, true) : GraphicsFormat.R32_SFloat;
RenderTextureFormat FinalFormat => _GenerateSignedDistanceField ? RenderTextureFormat.RGFloat : RenderTextureFormat.RFloat;
void MakeRT(RenderTexture texture, bool target)
{
var format = target ? SystemInfo.GetGraphicsFormat(DefaultFormat.DepthStencil) : FinalFormat;
var format = target ? RenderTextureFormat.Depth : FinalFormat;
var descriptor = texture.descriptor;
descriptor.graphicsFormat = target ? GraphicsFormat.None : format;
descriptor.depthStencilFormat = target ? format : GraphicsFormat.None;
descriptor.colorFormat = format;
descriptor.width = descriptor.height = _Resolution;
descriptor.depthBufferBits = target ? 24 : 0;
descriptor.useMipMap = false;
@@ -381,11 +375,7 @@ namespace WaveHarmonic.Crest
descriptor.enableRandomWrite = !target;
texture.descriptor = descriptor;
texture.Create();
if (!target)
{
Debug.Assert(SystemInfo.IsFormatSupported(format, GraphicsFormatUsage.Sample), "Crest: The graphics device does not support the render texture format " + format.ToString());
}
Debug.Assert(SystemInfo.SupportsRenderTextureFormat(format), "Crest: The graphics device does not support the render texture format " + format.ToString());
}
bool InitObjects()
@@ -714,7 +704,7 @@ namespace WaveHarmonic.Crest
var descriptor = new RenderTextureDescriptor(_Resolution, _Resolution)
{
autoGenerateMips = false,
graphicsFormat = Helpers.GetCompatibleTextureFormat(GraphicsFormat.R16G16_SFloat, true),
colorFormat = RenderTextureFormat.RGHalf,
useMipMap = false,
enableRandomWrite = true,
depthBufferBits = 0,

View File

@@ -16,19 +16,19 @@ namespace WaveHarmonic.Crest
[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 = -4), SerializeField]
[@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 = -5)]
[@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 = -6)]
[@Range(0, 1, order = -5)]
[@GenerateAPI]
[SerializeField]
float _WindAlignment;
@@ -37,7 +37,7 @@ namespace WaveHarmonic.Crest
// Generation
[Tooltip("FFT waves will loop with a period of this many seconds.")]
[@Range(4f, 128f, Range.Clamp.Minimum, order = -6)]
[@Range(4f, 128f, Range.Clamp.Minimum)]
[@GenerateAPI]
[SerializeField]
float _TimeLoopLength = Mathf.Infinity;
@@ -45,11 +45,6 @@ namespace WaveHarmonic.Crest
[Header("Culling")]
[Tooltip("Whether to override automatic culling based on heuristics.")]
[@GenerateAPI]
[SerializeField]
bool _OverrideCulling;
[Tooltip("Maximum amount the surface will be displaced vertically from sea level.\n\nIncrease this if gaps appear at bottom of screen.")]
[@GenerateAPI]
[SerializeField]
@@ -109,9 +104,8 @@ namespace WaveHarmonic.Crest
#endif
_TimeLoopLength;
// WebGPU will crash above at 128.
private protected override int MinimumResolution => 16;
private protected override int MaximumResolution => Helpers.IsWebGPU ? 64 : int.MaxValue;
private protected override int MaximumResolution => int.MaxValue;
FFTCompute _FFTCompute;
@@ -195,28 +189,13 @@ namespace WaveHarmonic.Crest
{
if (!Enabled) return;
if (_OverrideCulling)
{
// Apply weight or will cause popping due to scale change.
MaximumReportedHorizontalDisplacement = _MaximumHorizontalDisplacement * Weight;
MaximumReportedVerticalDisplacement = MaximumReportedWavesDisplacement = _MaximumVerticalDisplacement * Weight;
}
else
{
var powerLinear = 0f;
// Apply weight or will cause popping due to scale change.
MaximumReportedHorizontalDisplacement = _MaximumHorizontalDisplacement * Weight;
MaximumReportedVerticalDisplacement = MaximumReportedWavesDisplacement = _MaximumVerticalDisplacement * Weight;
for (var i = 0; i < WaveSpectrum.k_NumberOfOctaves; i++)
{
powerLinear += _ActiveSpectrum._PowerLinearScales[i];
}
// Empirical multiplier (3-5), went with 5 to be safe.
// We may be missing some more multipliers from the compute shader.
// Look there if this proves insufficient.
var wind = Mathf.Clamp01(WindSpeedKPH / 150f);
var rms = Mathf.Sqrt(powerLinear) * 5f;
MaximumReportedHorizontalDisplacement = rms * _ActiveSpectrum._Chop * Weight * wind;
MaximumReportedVerticalDisplacement = MaximumReportedWavesDisplacement = rms * Weight * wind;
if (Mode == LodInputMode.Global)
{
water.ReportMaximumDisplacement(MaximumReportedHorizontalDisplacement, MaximumReportedVerticalDisplacement, MaximumReportedVerticalDisplacement);
}
}
@@ -288,7 +267,6 @@ namespace WaveHarmonic.Crest
}
_Version = MigrateV2(_Version);
_Version = MigrateV3(_Version);
}
void ISerializationCallbackReceiver.OnBeforeSerialize()

View File

@@ -21,12 +21,12 @@ namespace WaveHarmonic.Crest
[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 = -4), SerializeField]
[@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 = -5)]
[@Range(0f, 1f, order = -4)]
[@GenerateAPI(Getter.Custom)]
[SerializeField]
float _ReverseWaveWeight = 0.5f;
@@ -35,25 +35,23 @@ namespace WaveHarmonic.Crest
// Generation Settings
[Tooltip("How many wave components to generate in each octave.")]
[@Delayed(order = -5)]
[@Delayed]
[@GenerateAPI]
[SerializeField]
int _ComponentsPerOctave = 8;
[Tooltip("Change to get a different set of waves.")]
[@GenerateAPI]
[@DecoratedField(order = -6)]
[SerializeField]
int _RandomSeed = 0;
[Tooltip("Prevent data arrays from being written to so one can provide their own.")]
[@GenerateAPI]
[@DecoratedField(order = -7)]
[SerializeField]
bool _ManualGeneration;
private protected override int MinimumResolution => 8;
private protected override int MaximumResolution => int.MaxValue;
private protected override int MaximumResolution => 64;
float _WindSpeedWhenGenerated = -1f;
@@ -181,7 +179,7 @@ namespace WaveHarmonic.Crest
{
if (_WaveBuffers == null)
{
_WaveBuffers = new(Resolution, Resolution, 0, Helpers.GetCompatibleTextureFormat(GraphicsFormat.R16G16B16A16_SFloat, randomWrite: true));
_WaveBuffers = new(_Resolution, _Resolution, 0, GraphicsFormat.R16G16B16A16_SFloat);
}
else
{
@@ -189,7 +187,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;
@@ -218,7 +216,7 @@ namespace WaveHarmonic.Crest
base.OnUpdate(water);
if (_WaveBuffers == null || Resolution != _WaveBuffers.width || _BufferCascadeParameters == null || _BufferWaveData == null)
if (_WaveBuffers == null || _Resolution != _WaveBuffers.width || _BufferCascadeParameters == null || _BufferWaveData == null)
{
InitData();
}
@@ -548,23 +546,23 @@ namespace WaveHarmonic.Crest
return;
}
MaximumReportedVerticalDisplacement = 0;
MaximumReportedHorizontalDisplacement = 0;
var ampSum = 0f;
for (var i = 0; i < _Wavelengths.Length; i++)
{
var amplitude = _Amplitudes[i];
MaximumReportedVerticalDisplacement += amplitude;
MaximumReportedHorizontalDisplacement += amplitude * _ActiveSpectrum._ChopScales[i / _ComponentsPerOctave];
ampSum += _Amplitudes[i] * _ActiveSpectrum._ChopScales[i / _ComponentsPerOctave];
}
MaximumReportedHorizontalDisplacement *= _ActiveSpectrum._Chop;
// Apply weight or will cause popping due to scale change.
MaximumReportedVerticalDisplacement *= Weight;
MaximumReportedHorizontalDisplacement *= Weight;
ampSum *= Weight;
MaximumReportedWavesDisplacement = MaximumReportedVerticalDisplacement;
MaximumReportedHorizontalDisplacement = ampSum * _ActiveSpectrum._Chop;
MaximumReportedVerticalDisplacement = ampSum;
MaximumReportedWavesDisplacement = ampSum;
if (Mode == LodInputMode.Global)
{
water.ReportMaximumDisplacement(ampSum * _ActiveSpectrum._Chop, ampSum, ampSum);
}
}
private protected override void Initialize()
@@ -646,7 +644,6 @@ namespace WaveHarmonic.Crest
}
_Version = MigrateV2(_Version);
_Version = MigrateV3(_Version);
}
void ISerializationCallbackReceiver.OnBeforeSerialize()

View File

@@ -4,7 +4,6 @@
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Serialization;
using WaveHarmonic.Crest.Internal;
namespace WaveHarmonic.Crest
{
@@ -36,13 +35,6 @@ 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.")]
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global))]
[@GenerateAPI]
[@DecoratedField]
[SerializeField]
bool _SeaLevelOnly = true;
[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]
@@ -76,21 +68,11 @@ namespace WaveHarmonic.Crest
[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(Getter.Custom)]
[@GenerateAPI]
[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).")]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Global))]
[@GenerateAPI]
[@DecoratedField]
[SerializeField]
bool _IncludeInDropDetailHeightBasedOnWaves;
// Debug
[Tooltip("In Editor, shows the wave generation buffers on screen.")]
@@ -110,7 +92,6 @@ 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");
}
private protected virtual WaveSpectrum DefaultSpectrum => WindSpectrum;
@@ -155,7 +136,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;
@@ -169,15 +150,13 @@ namespace WaveHarmonic.Crest
{
base.Attach();
_Reporter ??= new(this);
_DisplacementReporter = _Reporter;
_WaveDisplacementReporter = _Reporter;
WaterChunkRenderer.DisplacementReporters.Add(_Reporter);
}
private protected override void Detach()
{
base.Detach();
_DisplacementReporter = null;
_WaveDisplacementReporter = null;
WaterChunkRenderer.DisplacementReporters.Remove(_Reporter);
}
internal override void Draw(Lod simulation, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1f, int slice = -1)
@@ -210,13 +189,11 @@ namespace WaveHarmonic.Crest
// 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, 1);
_WaveBufferParameters[lodIdx] = new(-1, -2, 0, 0);
var found = false;
var filter = new AnimatedWavesLod.WavelengthFilter(water, lodIdx);
@@ -244,11 +221,7 @@ namespace WaveHarmonic.Crest
}
// Set transitional weights.
if (!shape.PreserveWaveQuality)
{
_WaveBufferParameters[lodCount - 2].w = 1f - water.ViewerAltitudeLevelAlpha;
}
_WaveBufferParameters[lodCount - 2].w = 1f - water.ViewerAltitudeLevelAlpha;
_WaveBufferParameters[lodCount - 1].w = water.ViewerAltitudeLevelAlpha;
SetRenderParameters(water, wrapper);
@@ -270,8 +243,6 @@ 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);
}
@@ -440,109 +411,40 @@ namespace WaveHarmonic.Crest
s_KeywordTextureBlend = WaterResources.Instance.Keywords.AnimatedWavesTransferWavesTextureBlend;
}
bool ReportDisplacement(WaterRenderer water, ref Rect bounds, ref float horizontal, ref float vertical)
bool ReportDisplacement(ref Rect bounds, ref float horizontal, ref float vertical)
{
if (!Enabled)
if (Mode == LodInputMode.Global || !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))
{
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;
}
if (_Rect.Encapsulates(bounds))
{
horizontal = nh;
vertical = nv;
}
else
{
horizontal = Mathf.Max(horizontal, nh);
vertical = Mathf.Max(vertical, nv);
}
horizontal = MaximumReportedHorizontalDisplacement;
vertical = MaximumReportedVerticalDisplacement;
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, IReportWaveDisplacement
sealed class Reporter : IReportsDisplacement
{
readonly ShapeWaves _Input;
public Reporter(ShapeWaves input) => _Input = input;
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);
public bool ReportDisplacement(ref Rect bounds, ref float horizontal, ref float vertical) => _Input.ReportDisplacement(ref bounds, ref horizontal, ref vertical);
}
}
@@ -612,17 +514,6 @@ namespace WaveHarmonic.Crest
return version;
}
private protected int MigrateV3(int version)
{
if (version < 3)
{
_SeaLevelOnly = false;
version = 3;
}
return version;
}
}
#if UNITY_EDITOR

View File

@@ -45,7 +45,7 @@ namespace WaveHarmonic.Crest
wrapper.SetVector(ShaderIDs.s_TextureSize, transform.lossyScale.XZ());
wrapper.SetVector(ShaderIDs.s_TexturePosition, transform.position.XZ());
wrapper.SetVector(ShaderIDs.s_TextureRotation, rotation);
wrapper.SetVector(ShaderIDs.s_TextureResolution, new(_Texture.width, _Texture.height));
wrapper.SetVector(ShaderIDs.s_Resolution, new(_Texture.width, _Texture.height));
wrapper.SetVector(ShaderIDs.s_Multiplier, _Multiplier);
wrapper.SetFloat(ShaderIDs.s_FeatherWidth, _Input.FeatherWidth);
wrapper.SetTexture(ShaderIDs.s_Texture, _Texture);