From 73c31285e29d510bf4ac33910b01bc204d4f25a8 Mon Sep 17 00:00:00 2001 From: Huw Bowles Date: Sat, 8 Aug 2020 21:31:35 +0100 Subject: [PATCH 1/4] #540 - explore what multiple ocean instances would mean Once i started pulling on the thread i could not stop. This branch should work like before iwth one ocean, there are a few issues before it will support multiple instances. Questions / problems that arose: Lod data resolution should be global setting, right now taken from one instance Validation gets passed "AnyInstance" in a few places, is this ok? RenderData.Validate - uses any instance RegisterLodDataClipSurface - this sets per-ocean data on MPB. might be tricky to fix.. How to connect underwater effect to ocean instance? How to connect underwater environment lighting with ocean instance? Debuggui always takes first instance of ocean, shall we make this selectable? OceanChunkRenderer.OnWillRenderObject - tiles will need Layer so it only goes in one camera?? tag @daleeidd @moosichu in case this is of interest --- .../BoatDev/Scripts/BoatAlignNormal.cs | 7 +- .../Crest-Examples/BoatDev/Scripts/LerpCam.cs | 4 +- .../BoatDev/Scripts/RippleGenerator.cs | 13 +-- .../Collision/OceanSampleDisplacementDemo.cs | 9 ++- .../UnderwaterEnvironmentalLighting.cs | 13 +-- .../Whirlpool/Scripts/Whirlpool.cs | 14 ++-- .../Crest/Crest/Scripts/BuildCommandBuffer.cs | 6 +- .../Crest/Scripts/Collision/QueryBase.cs | 14 ++-- .../Scripts/Collision/QueryDisplacements.cs | 8 +- .../Crest/Scripts/Collision/QueryFlow.cs | 10 ++- .../Crest/Scripts/Collision/RayTraceHelper.cs | 12 ++- .../Scripts/Collision/SamplingHelpers.cs | 28 ++++--- .../Collision/VisualiseCollisionArea.cs | 4 +- .../Scripts/Collision/VisualiseRayTrace.cs | 2 +- .../Crest/Scripts/Helpers/AssignLayer.cs | 2 +- .../Helpers/Editor/WindowCrestWaterBody.cs | 2 +- .../Crest/Scripts/Helpers/FloatingOrigin.cs | 20 ++--- .../Crest/Scripts/Helpers/OceanDebugGUI.cs | 40 +++++----- .../Crest/Scripts/Helpers/PropertyWrapper.cs | 14 ++-- .../Scripts/Helpers/RenderAlphaOnSurface.cs | 29 ++++--- .../Scripts/Helpers/TextureArrayHelpers.cs | 5 +- .../Crest/Scripts/Helpers/UnderwaterEffect.cs | 26 +++--- .../Crest/Scripts/Interaction/BoatProbes.cs | 15 ++-- .../Interaction/ObjectWaterInteraction.cs | 14 ++-- .../ObjectWaterInteractionAdaptor.cs | 9 ++- .../Interaction/SimpleFloatingObject.cs | 7 +- .../Interaction/SphereWaterInteraction.cs | 14 ++-- .../Crest/Crest/Scripts/LodData/LodDataMgr.cs | 36 ++++----- .../Scripts/LodData/LodDataMgrAnimWaves.cs | 79 ++++++++++--------- .../Scripts/LodData/LodDataMgrClipSurface.cs | 6 +- .../Scripts/LodData/LodDataMgrDynWaves.cs | 22 +++--- .../Crest/Scripts/LodData/LodDataMgrFlow.cs | 4 +- .../Crest/Scripts/LodData/LodDataMgrFoam.cs | 14 ++-- .../Scripts/LodData/LodDataMgrPersistent.cs | 16 ++-- .../LodData/LodDataMgrSeaFloorDepth.cs | 2 +- .../Crest/Scripts/LodData/LodTransform.cs | 23 ++++-- .../Crest/Scripts/LodData/OceanDepthCache.cs | 8 +- .../Scripts/LodData/RegisterAnimWavesInput.cs | 49 ++++++------ .../LodData/RegisterClipSurfaceInput.cs | 32 ++++---- .../Scripts/LodData/RegisterDynWavesInput.cs | 2 +- .../Scripts/LodData/RegisterFlowInput.cs | 2 +- .../Scripts/LodData/RegisterFoamInput.cs | 2 +- .../Scripts/LodData/RegisterLodDataInput.cs | 8 +- .../LodData/RegisterSeaFloorDepthInput.cs | 2 +- .../Settings/SimSettingsAnimatedWaves.cs | 6 +- .../LodData/Shadows/LodDataMgrShadow.cs | 40 +++++----- .../Crest/Crest/Scripts/OceanBuilder.cs | 1 + .../Crest/Crest/Scripts/OceanChunkRenderer.cs | 41 +++++----- .../Crest/Crest/Scripts/OceanRenderer.cs | 73 ++++++++++++++--- .../Reflection/OceanPlanarReflection.cs | 8 +- .../Scripts/Shapes/ShapeGerstnerBatched.cs | 63 ++++++++------- crest/Assets/Crest/Crest/Scripts/WaterBody.cs | 6 +- 52 files changed, 496 insertions(+), 390 deletions(-) diff --git a/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/BoatAlignNormal.cs b/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/BoatAlignNormal.cs index e7cb4691b..df11a8612 100644 --- a/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/BoatAlignNormal.cs +++ b/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/BoatAlignNormal.cs @@ -66,7 +66,7 @@ void Start() { _rb = GetComponent(); - if (OceanRenderer.Instance == null) + if (OceanRenderer.AnyInstance == null) { enabled = false; return; @@ -75,7 +75,8 @@ void Start() void FixedUpdate() { - if (OceanRenderer.Instance == null) + var ocean = OceanRenderer.ClosestInstance(transform.position); + if (ocean == null) { return; } @@ -83,7 +84,7 @@ void FixedUpdate() UnityEngine.Profiling.Profiler.BeginSample("BoatAlignNormal.FixedUpdate"); _sampleHeightHelper.Init(transform.position, _boatWidth, true); - var height = OceanRenderer.Instance.SeaLevel; + var height = ocean.SeaLevel; _sampleHeightHelper.Sample(out Vector3 disp, out var normal, out var waterSurfaceVel); diff --git a/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/LerpCam.cs b/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/LerpCam.cs index c1ceb15ff..5866755c5 100644 --- a/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/LerpCam.cs +++ b/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/LerpCam.cs @@ -17,7 +17,7 @@ public class LerpCam : MonoBehaviour void Update() { - if (OceanRenderer.Instance == null) + if (OceanRenderer.AnyInstance == null) { return; } @@ -28,7 +28,7 @@ void Update() var targetPos = _targetPos.position; targetPos.y = Mathf.Max(targetPos.y, h + _minHeightAboveWater); - transform.position = Vector3.Lerp(transform.position, targetPos, _lerpAlpha * OceanRenderer.Instance.DeltaTime * 60f); + transform.position = Vector3.Lerp(transform.position, targetPos, _lerpAlpha * OceanRenderer.AnyInstance.DeltaTime * 60f); transform.LookAt(_targetLookatPos.position + _lookatOffset * Vector3.up); } } diff --git a/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/RippleGenerator.cs b/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/RippleGenerator.cs index 2017b584d..ce067b21c 100644 --- a/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/RippleGenerator.cs +++ b/crest/Assets/Crest/Crest-Examples/BoatDev/Scripts/RippleGenerator.cs @@ -21,7 +21,7 @@ void Start() { _rdwi = GetComponent(); - if (OceanRenderer.Instance == null || !OceanRenderer.Instance.CreateDynamicWaveSim || _rdwi == null) + if (OceanRenderer.AnyInstance == null || !OceanRenderer.AnyInstance.CreateDynamicWaveSim || _rdwi == null) { enabled = false; return; @@ -33,14 +33,15 @@ void Start() void Update() { - if (OceanRenderer.Instance == null) + var ocean = OceanRenderer.AnyInstance; + if (ocean == null) { return; } if (_animate) { - float t = OceanRenderer.Instance.CurrentTime; + float t = OceanRenderer.AnyInstance.CurrentTime; if (t < _warmUp) return; t -= _warmUp; @@ -50,7 +51,7 @@ void Update() // which lod is this object in (roughly)? Rect thisRect = new Rect(new Vector2(transform.position.x, transform.position.z), Vector3.zero); - int minLod = LodDataMgrAnimWaves.SuggestDataLOD(thisRect); + int minLod = LodDataMgrAnimWaves.SuggestDataLOD(ocean, thisRect); if (minLod == -1) { // outside all lods, nothing to update! @@ -60,7 +61,7 @@ void Update() // how many active wave sims currently apply to this object - ideally this would eliminate sims that are too // low res, by providing a max grid size param int simsPresent, simsActive; - LodDataMgrDynWaves.CountWaveSims(minLod, out simsPresent, out simsActive); + LodDataMgrDynWaves.CountWaveSims(ocean, minLod, out simsPresent, out simsActive); if (simsPresent == 0) { enabled = false; @@ -68,7 +69,7 @@ void Update() } float dt; - OceanRenderer.Instance._lodDataDynWaves.GetSimSubstepData(OceanRenderer.Instance.DeltaTimeDynamics, out _, out dt); + ocean._lodDataDynWaves.GetSimSubstepData(ocean.DeltaTimeDynamics, out _, out dt); _rend.GetPropertyBlock(_mpb); diff --git a/crest/Assets/Crest/Crest-Examples/Shared/Scripts/Collision/OceanSampleDisplacementDemo.cs b/crest/Assets/Crest/Crest-Examples/Shared/Scripts/Collision/OceanSampleDisplacementDemo.cs index 1e2d6573a..b1e9df27d 100644 --- a/crest/Assets/Crest/Crest-Examples/Shared/Scripts/Collision/OceanSampleDisplacementDemo.cs +++ b/crest/Assets/Crest/Crest-Examples/Shared/Scripts/Collision/OceanSampleDisplacementDemo.cs @@ -25,14 +25,15 @@ public class OceanSampleDisplacementDemo : MonoBehaviour void Update() { - if (OceanRenderer.Instance == null) + var ocean = OceanRenderer.ClosestInstance(transform.position); + if (ocean == null) { return; } if (_trackCamera) { - var height = Mathf.Abs(Camera.main.transform.position.y - OceanRenderer.Instance.SeaLevel); + var height = Mathf.Abs(Camera.main.transform.position.y - ocean.SeaLevel); var lookAngle = Mathf.Max(Mathf.Abs(Camera.main.transform.forward.y), 0.001f); var offset = height / lookAngle; _markerPos[0] = Camera.main.transform.position + Camera.main.transform.forward * offset; @@ -40,7 +41,7 @@ void Update() _markerPos[2] = Camera.main.transform.position + Camera.main.transform.forward * offset + _samplesRadius * Vector3.forward; } - var collProvider = OceanRenderer.Instance.CollisionProvider; + var collProvider = ocean.CollisionProvider; var status = collProvider.Query(GetHashCode(), _minGridSize, _markerPos, _resultDisps, _resultNorms, _resultVels); @@ -56,7 +57,7 @@ void Update() } var query = _markerPos[i]; - query.y = OceanRenderer.Instance.SeaLevel; + query.y = ocean.SeaLevel; var disp = _resultDisps[i]; diff --git a/crest/Assets/Crest/Crest-Examples/Shared/Scripts/UnderwaterEnvironmentalLighting.cs b/crest/Assets/Crest/Crest-Examples/Shared/Scripts/UnderwaterEnvironmentalLighting.cs index bde0bf6d1..2648d4081 100644 --- a/crest/Assets/Crest/Crest-Examples/Shared/Scripts/UnderwaterEnvironmentalLighting.cs +++ b/crest/Assets/Crest/Crest-Examples/Shared/Scripts/UnderwaterEnvironmentalLighting.cs @@ -29,13 +29,14 @@ public class UnderwaterEnvironmentalLighting : MonoBehaviour void Start() { - if (OceanRenderer.Instance == null) + // todo - how to connect this to correct ocean instance? + if (OceanRenderer.AnyInstance == null) { enabled = false; return; } - _primaryLight = OceanRenderer.Instance._primaryLight; + _primaryLight = OceanRenderer.AnyInstance._primaryLight; // Store lighting settings if (_primaryLight) @@ -47,13 +48,13 @@ void Start() _fogDensity = RenderSettings.fogDensity; // Check to make sure the property exists. We might be using a test material. - if (!OceanRenderer.Instance.OceanMaterial.HasProperty("_DepthFogDensity")) + if (!OceanRenderer.AnyInstance.OceanMaterial.HasProperty("_DepthFogDensity")) { enabled = false; return; } - Color density = OceanRenderer.Instance.OceanMaterial.GetColor("_DepthFogDensity"); + Color density = OceanRenderer.AnyInstance.OceanMaterial.GetColor("_DepthFogDensity"); _averageDensity = (density.r + density.g + density.b) / 3f; } @@ -71,13 +72,13 @@ void OnDisable() void LateUpdate() { - if (OceanRenderer.Instance == null) + if (OceanRenderer.AnyInstance == null) { return; } float depthMultiplier = Mathf.Exp(_averageDensity * - Mathf.Min(OceanRenderer.Instance.ViewerHeightAboveWater * DEPTH_OUTSCATTER_CONSTANT, 0f)); + Mathf.Min(OceanRenderer.AnyInstance.ViewerHeightAboveWater * DEPTH_OUTSCATTER_CONSTANT, 0f)); // Darken environmental lighting when viewer underwater if (_primaryLight) diff --git a/crest/Assets/Crest/Crest-Examples/Whirlpool/Scripts/Whirlpool.cs b/crest/Assets/Crest/Crest-Examples/Whirlpool/Scripts/Whirlpool.cs index b7bb058d3..6b4c81a40 100644 --- a/crest/Assets/Crest/Crest-Examples/Whirlpool/Scripts/Whirlpool.cs +++ b/crest/Assets/Crest/Crest-Examples/Whirlpool/Scripts/Whirlpool.cs @@ -37,7 +37,7 @@ private void UpdateMaterials() void Start() { - if (OceanRenderer.Instance == null) + if (OceanRenderer.AnyInstance == null) { enabled = false; return; @@ -79,12 +79,16 @@ void AddInput(Material material, float radius) where Register void Update() { - if (OceanRenderer.Instance == null) + for (var i = 0; i < OceanRenderer.InstanceCount; i++) { - return; - } + var ocean = OceanRenderer.GetInstance(i); + if (ocean == null) + { + continue; + } - OceanRenderer.Instance.ReportMaxDisplacementFromShape(0f, _amplitude, 0f); + ocean.ReportMaxDisplacementFromShape(0f, _amplitude, 0f); + } UpdateMaterials(); } diff --git a/crest/Assets/Crest/Crest/Scripts/BuildCommandBuffer.cs b/crest/Assets/Crest/Crest/Scripts/BuildCommandBuffer.cs index d0ddaaa76..94b0a98a3 100644 --- a/crest/Assets/Crest/Crest/Scripts/BuildCommandBuffer.cs +++ b/crest/Assets/Crest/Crest/Scripts/BuildCommandBuffer.cs @@ -86,10 +86,8 @@ void BuildLodData(OceanRenderer ocean, CommandBuffer buf) /// /// Construct the command buffer and attach it to the camera so that it will be executed in the render. /// - public void BuildAndExecute() + public void BuildAndExecute(OceanRenderer ocean) { - if (OceanRenderer.Instance == null) return; - if (_buf == null) { _buf = new CommandBuffer(); @@ -98,7 +96,7 @@ public void BuildAndExecute() _buf.Clear(); - BuildLodData(OceanRenderer.Instance, _buf); + BuildLodData(ocean, _buf); // This will execute at the beginning of the frame before the graphics queue Graphics.ExecuteCommandBuffer(_buf); diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/QueryBase.cs b/crest/Assets/Crest/Crest/Scripts/Collision/QueryBase.cs index 45538f5a6..2296adf27 100644 --- a/crest/Assets/Crest/Crest/Scripts/Collision/QueryBase.cs +++ b/crest/Assets/Crest/Crest/Scripts/Collision/QueryBase.cs @@ -28,6 +28,8 @@ public abstract class QueryBase const int s_maxRequests = 4; const int s_maxGuids = 1024; + protected OceanRenderer _ocean; + protected virtual ComputeShader ShaderProcessQueries => _shaderProcessQueries; ComputeShader _shaderProcessQueries; PropertyWrapperComputeStandalone _wrapper; @@ -215,13 +217,15 @@ public enum QueryStatus InvalidDtForVelocity = 16, } - public QueryBase() + public QueryBase(OceanRenderer ocean) { + _ocean = ocean; + _dataArrivedAction = new System.Action(DataArrived); - if (_maxQueryCount != OceanRenderer.Instance._lodDataAnimWaves.Settings.MaxQueryCount) + if (_maxQueryCount != ocean._lodDataAnimWaves.Settings.MaxQueryCount) { - _maxQueryCount = OceanRenderer.Instance._lodDataAnimWaves.Settings.MaxQueryCount; + _maxQueryCount = ocean._lodDataAnimWaves.Settings.MaxQueryCount; _queryPosXZ_minGridSize = new Vector3[_maxQueryCount]; } @@ -307,7 +311,7 @@ protected bool UpdateQueryPoints(int i_ownerHash, float i_minSpatialLength, Vect // The smallest wavelengths should repeat no more than twice across the smaller spatial length. Unless we're // in the last LOD - then this is the best we can do. float minWavelength = i_minSpatialLength / 2f; - float minGridSize = minWavelength / OceanRenderer.Instance.MinTexelsPerWave; + float minGridSize = minWavelength / _ocean.MinTexelsPerWave; if (countPts + segment.x > _queryPosXZ_minGridSize.Length) { @@ -392,7 +396,7 @@ protected bool RetrieveResults(int guid, Vector3[] displacements, float[] height // Retrieve Result heights if (heights != null) { - var seaLevel = OceanRenderer.Instance.SeaLevel; + var seaLevel = _ocean.SeaLevel; for (int i = 0; i < countPoints; i++) { heights[i] = seaLevel + _queryResults[i + segment.x].y; diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/QueryDisplacements.cs b/crest/Assets/Crest/Crest/Scripts/Collision/QueryDisplacements.cs index 19ecceb41..5012d184d 100644 --- a/crest/Assets/Crest/Crest/Scripts/Collision/QueryDisplacements.cs +++ b/crest/Assets/Crest/Crest/Scripts/Collision/QueryDisplacements.cs @@ -17,10 +17,14 @@ public class QueryDisplacements : QueryBase, ICollProvider protected override string QueryShaderName => "QueryDisplacements"; protected override string QueryKernelName => "CSMain"; + public QueryDisplacements(OceanRenderer ocean) : base(ocean) + { + } + protected override void BindInputsAndOutputs(PropertyWrapperComputeStandalone wrapper, ComputeBuffer resultsBuffer) { - OceanRenderer.Instance._lodDataAnimWaves.BindResultData(wrapper); - ShaderProcessQueries.SetTexture(_kernelHandle, sp_LD_TexArray_AnimatedWaves, OceanRenderer.Instance._lodDataAnimWaves.DataTexture); + _ocean._lodDataAnimWaves.BindResultData(wrapper); + ShaderProcessQueries.SetTexture(_kernelHandle, sp_LD_TexArray_AnimatedWaves, _ocean._lodDataAnimWaves.DataTexture); ShaderProcessQueries.SetBuffer(_kernelHandle, sp_ResultDisplacements, resultsBuffer); } diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/QueryFlow.cs b/crest/Assets/Crest/Crest/Scripts/Collision/QueryFlow.cs index e52081b7a..437b12c0d 100644 --- a/crest/Assets/Crest/Crest/Scripts/Collision/QueryFlow.cs +++ b/crest/Assets/Crest/Crest/Scripts/Collision/QueryFlow.cs @@ -17,12 +17,16 @@ public class QueryFlow : QueryBase, IFlowProvider protected override string QueryShaderName => "QueryFlow"; protected override string QueryKernelName => "CSMain"; + public QueryFlow(OceanRenderer ocean) : base(ocean) + { + } + protected override void BindInputsAndOutputs(PropertyWrapperComputeStandalone wrapper, ComputeBuffer resultsBuffer) { - if (OceanRenderer.Instance._lodDataFlow != null) + if (_ocean._lodDataFlow != null) { - OceanRenderer.Instance._lodDataFlow.BindResultData(wrapper); - ShaderProcessQueries.SetTexture(_kernelHandle, sp_LD_TexArray_Flow, OceanRenderer.Instance._lodDataFlow.DataTexture); + _ocean._lodDataFlow.BindResultData(wrapper); + ShaderProcessQueries.SetTexture(_kernelHandle, sp_LD_TexArray_Flow, _ocean._lodDataFlow.DataTexture); } else { diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/RayTraceHelper.cs b/crest/Assets/Crest/Crest/Scripts/Collision/RayTraceHelper.cs index 9d8728e8d..3c0259af3 100644 --- a/crest/Assets/Crest/Crest/Scripts/Collision/RayTraceHelper.cs +++ b/crest/Assets/Crest/Crest/Scripts/Collision/RayTraceHelper.cs @@ -12,6 +12,8 @@ namespace Crest /// public class RayTraceHelper { + OceanRenderer _ocean; + Vector3[] _queryPos; Vector3[] _queryResult; @@ -53,6 +55,8 @@ public RayTraceHelper(float rayLength, float rayStepSize = 2f) /// World space ray direction public void Init(Vector3 i_rayOrigin, Vector3 i_rayDirection) { + _ocean = OceanRenderer.ClosestInstance(i_rayOrigin); + for (int i = 0; i < _queryPos.Length; i++) { _queryPos[i] = i_rayOrigin + i * _rayStepSize * i_rayDirection; @@ -82,9 +86,9 @@ public bool Trace(out float o_distance) return false; } - var status = OceanRenderer.Instance.CollisionProvider.Query(GetHashCode(), _minLength, _queryPos, _queryResult, null, null); + var status = _ocean.CollisionProvider.Query(GetHashCode(), _minLength, _queryPos, _queryResult, null, null); - if (!OceanRenderer.Instance.CollisionProvider.RetrieveSucceeded(status)) + if (!_ocean.CollisionProvider.RetrieveSucceeded(status)) { _valid = false; return false; @@ -94,8 +98,8 @@ public bool Trace(out float o_distance) // the ray crosses the surface, the distance to the intersection is interpolated from the heights. for (int i = 1; i < _queryPos.Length; i++) { - var height0 = _queryResult[i - 1].y + OceanRenderer.Instance.SeaLevel - _queryPos[i - 1].y; - var height1 = _queryResult[i].y + OceanRenderer.Instance.SeaLevel - _queryPos[i].y; + var height0 = _queryResult[i - 1].y + _ocean.SeaLevel - _queryPos[i - 1].y; + var height1 = _queryResult[i].y + _ocean.SeaLevel - _queryPos[i].y; if (Mathf.Sign(height0) != Mathf.Sign(height1)) { diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/SamplingHelpers.cs b/crest/Assets/Crest/Crest/Scripts/Collision/SamplingHelpers.cs index 4640ae609..1d2224a26 100644 --- a/crest/Assets/Crest/Crest/Scripts/Collision/SamplingHelpers.cs +++ b/crest/Assets/Crest/Crest/Scripts/Collision/SamplingHelpers.cs @@ -17,6 +17,8 @@ public class SampleHeightHelper Vector3[] _queryResultNormal = new Vector3[1]; Vector3[] _queryResultVel = new Vector3[1]; + OceanRenderer _ocean; + float _minLength = 0f; #if UNITY_EDITOR @@ -35,6 +37,7 @@ public void Init(Vector3 i_queryPos, float i_minLength = 0f, bool allowMultipleC { _queryPos[0] = i_queryPos; _minLength = i_minLength; + _ocean = OceanRenderer.ClosestInstance(i_queryPos); #if UNITY_EDITOR if (!allowMultipleCallsPerFrame && _lastFrame >= OceanRenderer.FrameCount) @@ -50,7 +53,7 @@ public void Init(Vector3 i_queryPos, float i_minLength = 0f, bool allowMultipleC /// public bool Sample(out float o_height) { - var collProvider = OceanRenderer.Instance?.CollisionProvider; + var collProvider = _ocean?.CollisionProvider; if (collProvider == null) { o_height = 0f; @@ -61,18 +64,18 @@ public bool Sample(out float o_height) if (!collProvider.RetrieveSucceeded(status)) { - o_height = OceanRenderer.Instance.SeaLevel; + o_height = _ocean.SeaLevel; return false; } - o_height = _queryResult[0].y + OceanRenderer.Instance.SeaLevel; + o_height = _queryResult[0].y + _ocean.SeaLevel; return true; } public bool Sample(out float o_height, out Vector3 o_normal) { - var collProvider = OceanRenderer.Instance?.CollisionProvider; + var collProvider = _ocean?.CollisionProvider; if (collProvider == null) { o_height = 0f; @@ -84,12 +87,12 @@ public bool Sample(out float o_height, out Vector3 o_normal) if (!collProvider.RetrieveSucceeded(status)) { - o_height = OceanRenderer.Instance.SeaLevel; + o_height = _ocean.SeaLevel; o_normal = Vector3.up; return false; } - o_height = _queryResult[0].y + OceanRenderer.Instance.SeaLevel; + o_height = _queryResult[0].y + _ocean.SeaLevel; o_normal = _queryResultNormal[0]; return true; @@ -97,7 +100,7 @@ public bool Sample(out float o_height, out Vector3 o_normal) public bool Sample(out float o_height, out Vector3 o_normal, out Vector3 o_surfaceVel) { - var collProvider = OceanRenderer.Instance?.CollisionProvider; + var collProvider = _ocean?.CollisionProvider; if (collProvider == null) { o_height = 0f; @@ -110,13 +113,13 @@ public bool Sample(out float o_height, out Vector3 o_normal, out Vector3 o_surfa if (!collProvider.RetrieveSucceeded(status)) { - o_height = OceanRenderer.Instance.SeaLevel; + o_height = _ocean.SeaLevel; o_normal = Vector3.up; o_surfaceVel = Vector3.zero; return false; } - o_height = _queryResult[0].y + OceanRenderer.Instance.SeaLevel; + o_height = _queryResult[0].y + _ocean.SeaLevel; o_normal = _queryResultNormal[0]; o_surfaceVel = _queryResultVel[0]; @@ -125,7 +128,7 @@ public bool Sample(out float o_height, out Vector3 o_normal, out Vector3 o_surfa public bool Sample(out Vector3 o_displacementToPoint, out Vector3 o_normal, out Vector3 o_surfaceVel) { - var collProvider = OceanRenderer.Instance?.CollisionProvider; + var collProvider = _ocean?.CollisionProvider; if (collProvider == null) { o_displacementToPoint = Vector3.zero; @@ -159,7 +162,7 @@ public class SampleFlowHelper { Vector3[] _queryPos = new Vector3[1]; Vector3[] _queryResult = new Vector3[1]; - + OceanRenderer _ocean; float _minLength = 0f; /// @@ -172,6 +175,7 @@ public void Init(Vector3 i_queryPos, float i_minLength) { _queryPos[0] = i_queryPos; _minLength = i_minLength; + _ocean = OceanRenderer.ClosestInstance(i_queryPos); } /// @@ -179,7 +183,7 @@ public void Init(Vector3 i_queryPos, float i_minLength) /// public bool Sample(out Vector2 o_flow) { - var flowProvider = OceanRenderer.Instance?.FlowProvider; + var flowProvider = _ocean?.FlowProvider; if (flowProvider == null) { o_flow = Vector2.zero; diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseCollisionArea.cs b/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseCollisionArea.cs index 4b8d8153e..16098fdb0 100644 --- a/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseCollisionArea.cs +++ b/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseCollisionArea.cs @@ -23,12 +23,12 @@ public class VisualiseCollisionArea : MonoBehaviour void Update() { - if (OceanRenderer.Instance == null || OceanRenderer.Instance.CollisionProvider == null) + if (OceanRenderer.AnyInstance == null) { return; } - var collProvider = OceanRenderer.Instance.CollisionProvider; + var collProvider = OceanRenderer.ClosestInstance(transform.position).CollisionProvider; for (int i = 0; i < s_steps; i++) { diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseRayTrace.cs b/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseRayTrace.cs index aa631eba6..83290403a 100644 --- a/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseRayTrace.cs +++ b/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseRayTrace.cs @@ -15,7 +15,7 @@ public class VisualiseRayTrace : MonoBehaviour void Update() { - if (OceanRenderer.Instance == null || OceanRenderer.Instance.CollisionProvider == null) + if (OceanRenderer.AnyInstance == null) { return; } diff --git a/crest/Assets/Crest/Crest/Scripts/Helpers/AssignLayer.cs b/crest/Assets/Crest/Crest/Scripts/Helpers/AssignLayer.cs index 3c35fef4d..553cc7e88 100644 --- a/crest/Assets/Crest/Crest/Scripts/Helpers/AssignLayer.cs +++ b/crest/Assets/Crest/Crest/Scripts/Helpers/AssignLayer.cs @@ -21,7 +21,7 @@ private void Awake() enabled = false; #if UNITY_EDITOR - if (EditorApplication.isPlaying && !Validate(OceanRenderer.Instance, ValidatedHelper.DebugLog)) + if (EditorApplication.isPlaying && !Validate(OceanRenderer.AnyInstance, ValidatedHelper.DebugLog)) { return; } diff --git a/crest/Assets/Crest/Crest/Scripts/Helpers/Editor/WindowCrestWaterBody.cs b/crest/Assets/Crest/Crest/Scripts/Helpers/Editor/WindowCrestWaterBody.cs index 7ab218ae2..17f749b37 100644 --- a/crest/Assets/Crest/Crest/Scripts/Helpers/Editor/WindowCrestWaterBody.cs +++ b/crest/Assets/Crest/Crest/Scripts/Helpers/Editor/WindowCrestWaterBody.cs @@ -46,7 +46,7 @@ private void OnGUI() return; } - if (OceanRenderer.Instance == null) + if (OceanRenderer.AnyInstance == null) { EditorGUILayout.HelpBox( "No water object in loaded scenes, so no water will appear. To add one create a new GameObject and attach a OceanRenderer component to it.", diff --git a/crest/Assets/Crest/Crest/Scripts/Helpers/FloatingOrigin.cs b/crest/Assets/Crest/Crest/Scripts/Helpers/FloatingOrigin.cs index 3f371d183..327ba8c45 100644 --- a/crest/Assets/Crest/Crest/Scripts/Helpers/FloatingOrigin.cs +++ b/crest/Assets/Crest/Crest/Scripts/Helpers/FloatingOrigin.cs @@ -139,22 +139,24 @@ void MoveOriginParticles(Vector3 newOrigin) /// void MoveOriginOcean(Vector3 newOrigin) { - if (OceanRenderer.Instance) + for (var i = 0; i < OceanRenderer.InstanceCount; i++) { - OceanRenderer.Instance._lodTransform.SetOrigin(newOrigin); + var ocean = OceanRenderer.GetInstance(i); - var fos = OceanRenderer.Instance.GetComponentsInChildren(); + ocean._lodTransform.SetOrigin(newOrigin); + + var fos = ocean.GetComponentsInChildren(); foreach (var fo in fos) { fo.SetOrigin(newOrigin); } + } - // Gerstner components - var gerstners = _overrideGerstnerList != null && _overrideGerstnerList.Length > 0 ? _overrideGerstnerList : FindObjectsOfType(); - foreach (var gerstner in gerstners) - { - gerstner.SetOrigin(newOrigin); - } + // Gerstner components + var gerstners = _overrideGerstnerList != null && _overrideGerstnerList.Length > 0 ? _overrideGerstnerList : FindObjectsOfType(); + foreach (var gerstner in gerstners) + { + gerstner.SetOrigin(newOrigin); } } diff --git a/crest/Assets/Crest/Crest/Scripts/Helpers/OceanDebugGUI.cs b/crest/Assets/Crest/Crest/Scripts/Helpers/OceanDebugGUI.cs index 5017b82bd..05b9162a2 100644 --- a/crest/Assets/Crest/Crest/Scripts/Helpers/OceanDebugGUI.cs +++ b/crest/Assets/Crest/Crest/Scripts/Helpers/OceanDebugGUI.cs @@ -57,6 +57,8 @@ void OnGUI() { Color bkp = GUI.color; + var ocean = OceanRenderer.InstanceCount > 0 ? OceanRenderer.GetInstance(0) : null; + if (_guiVisible) { GUI.skin.toggle.normal.textColor = Color.white; @@ -109,17 +111,17 @@ void OnGUI() LodDataMgrShadow.s_processData = GUI.Toggle(new Rect(x, y, w, h), LodDataMgrShadow.s_processData, "Process Shadows"); y += h; - if (OceanRenderer.Instance) + if (ocean != null) { - if (OceanRenderer.Instance._lodDataDynWaves != null) + if (ocean._lodDataDynWaves != null) { int steps; float dt; - OceanRenderer.Instance._lodDataDynWaves.GetSimSubstepData(OceanRenderer.Instance.DeltaTimeDynamics, out steps, out dt); + ocean._lodDataDynWaves.GetSimSubstepData(ocean.DeltaTimeDynamics, out steps, out dt); GUI.Label(new Rect(x, y, w, h), string.Format("Sim steps: {0:0.00000} x {1}", dt, steps)); y += h; } - var querySystem = OceanRenderer.Instance.CollisionProvider as QueryBase; - if (OceanRenderer.Instance.CollisionProvider != null && querySystem != null) + var querySystem = ocean.CollisionProvider as QueryBase; + if (ocean.CollisionProvider != null && querySystem != null) { GUI.Label(new Rect(x, y, w, h), string.Format("Query result GUIDs: {0}", querySystem.ResultGuidCount)); y += h; } @@ -127,7 +129,7 @@ void OnGUI() #if UNITY_EDITOR if (GUI.Button(new Rect(x, y, w, h), "Select Ocean Mat")) { - var path = UnityEditor.AssetDatabase.GetAssetPath(OceanRenderer.Instance.OceanMaterial); + var path = UnityEditor.AssetDatabase.GetAssetPath(ocean.OceanMaterial); var asset = UnityEditor.AssetDatabase.LoadMainAssetAtPath(path); UnityEditor.Selection.activeObject = asset; } @@ -145,15 +147,15 @@ void OnGUI() // draw source textures to screen if (_showOceanData) { - DrawShapeTargets(); + DrawShapeTargets(ocean); } GUI.color = bkp; } - void DrawShapeTargets() + void DrawShapeTargets(OceanRenderer ocean) { - if (OceanRenderer.Instance == null) return; + if (ocean == null) return; // Draw bottom panel for toggles var bottomBar = new Rect(_guiVisible ? _leftPanelWidth : 0, @@ -164,23 +166,23 @@ void DrawShapeTargets() // Show viewer height above water in bottom panel bottomBar.x += 10; - GUI.Label(bottomBar, "Viewer Height Above Water: " + OceanRenderer.Instance.ViewerHeightAboveWater); + GUI.Label(bottomBar, "Viewer Height Above Water: " + ocean.ViewerHeightAboveWater); // Draw sim data - DrawSims(); + DrawSims(ocean); } - void DrawSims() + void DrawSims(OceanRenderer ocean) { float column = 1f; - DrawSim(OceanRenderer.Instance._lodDataAnimWaves, ref _drawAnimWaves, ref column); - DrawSim(OceanRenderer.Instance._lodDataDynWaves, ref _drawDynWaves, ref column); - DrawSim(OceanRenderer.Instance._lodDataFoam, ref _drawFoam, ref column); - DrawSim(OceanRenderer.Instance._lodDataFlow, ref _drawFlow, ref column); - DrawSim(OceanRenderer.Instance._lodDataShadow, ref _drawShadow, ref column); - DrawSim(OceanRenderer.Instance._lodDataSeaDepths, ref _drawSeaFloorDepth, ref column); - DrawSim(OceanRenderer.Instance._lodDataClipSurface, ref _drawClipSurface, ref column); + DrawSim(ocean._lodDataAnimWaves, ref _drawAnimWaves, ref column); + DrawSim(ocean._lodDataDynWaves, ref _drawDynWaves, ref column); + DrawSim(ocean._lodDataFoam, ref _drawFoam, ref column); + DrawSim(ocean._lodDataFlow, ref _drawFlow, ref column); + DrawSim(ocean._lodDataShadow, ref _drawShadow, ref column); + DrawSim(ocean._lodDataSeaDepths, ref _drawSeaFloorDepth, ref column); + DrawSim(ocean._lodDataClipSurface, ref _drawClipSurface, ref column); } static void DrawSim(LodDataMgr lodData, ref bool doDraw, ref float offset) where SimType : LodDataMgr diff --git a/crest/Assets/Crest/Crest/Scripts/Helpers/PropertyWrapper.cs b/crest/Assets/Crest/Crest/Scripts/Helpers/PropertyWrapper.cs index 70696f911..a7c914aaf 100644 --- a/crest/Assets/Crest/Crest/Scripts/Helpers/PropertyWrapper.cs +++ b/crest/Assets/Crest/Crest/Scripts/Helpers/PropertyWrapper.cs @@ -80,12 +80,12 @@ public void Initialise( // 64 recommended as a good common minimum: https://www.reddit.com/r/GraphicsProgramming/comments/aeyfkh/for_compute_shaders_is_there_an_ideal_numthreads/ public const int THREAD_GROUP_SIZE_X = 8; public const int THREAD_GROUP_SIZE_Y = 8; - public void DispatchShader() + public void DispatchShader(OceanRenderer ocean) { _commandBuffer.DispatchCompute( _computeShader, _computeKernel, - OceanRenderer.Instance.LodDataResolution / THREAD_GROUP_SIZE_X, - OceanRenderer.Instance.LodDataResolution / THREAD_GROUP_SIZE_Y, + ocean.LodDataResolution / THREAD_GROUP_SIZE_X, + ocean.LodDataResolution / THREAD_GROUP_SIZE_Y, 1 ); @@ -94,13 +94,13 @@ public void DispatchShader() _computeKernel = -1; } - public void DispatchShaderMultiLOD() + public void DispatchShaderMultiLOD(OceanRenderer ocean) { _commandBuffer.DispatchCompute( _computeShader, _computeKernel, - OceanRenderer.Instance.LodDataResolution / THREAD_GROUP_SIZE_X, - OceanRenderer.Instance.LodDataResolution / THREAD_GROUP_SIZE_Y, - OceanRenderer.Instance.CurrentLodCount + ocean.LodDataResolution / THREAD_GROUP_SIZE_X, + ocean.LodDataResolution / THREAD_GROUP_SIZE_Y, + ocean.CurrentLodCount ); _commandBuffer = null; diff --git a/crest/Assets/Crest/Crest/Scripts/Helpers/RenderAlphaOnSurface.cs b/crest/Assets/Crest/Crest/Scripts/Helpers/RenderAlphaOnSurface.cs index 0e76cc359..19f839a23 100644 --- a/crest/Assets/Crest/Crest/Scripts/Helpers/RenderAlphaOnSurface.cs +++ b/crest/Assets/Crest/Crest/Scripts/Helpers/RenderAlphaOnSurface.cs @@ -18,14 +18,16 @@ public class RenderAlphaOnSurface : MonoBehaviour Renderer _rend; Mesh _mesh; Bounds _boundsLocal; + OceanRenderer _ocean; private void Start() { _rend = GetComponent(); _mesh = GetComponent().mesh; _boundsLocal = _mesh.bounds; + _ocean = OceanRenderer.ClosestInstance(transform.position); - if (OceanRenderer.Instance != null) + if (_ocean != null) { LateUpdateBounds(); } @@ -33,14 +35,15 @@ private void Start() private void LateUpdate() { - if (OceanRenderer.Instance == null) + _ocean = OceanRenderer.ClosestInstance(transform.position); + if (_ocean == null) { return; } // find which lod this object is overlapping var rect = new Rect(transform.position.x, transform.position.z, 0f, 0f); - var lodIdx = LodDataMgrAnimWaves.SuggestDataLOD(rect); + var lodIdx = LodDataMgrAnimWaves.SuggestDataLOD(_ocean, rect); if (lodIdx > -1) { @@ -51,11 +54,11 @@ private void LateUpdate() _rend.GetPropertyBlock(_mpb.materialPropertyBlock); - var lodCount = OceanRenderer.Instance.CurrentLodCount; - var lodDataAnimWaves = OceanRenderer.Instance._lodDataAnimWaves; + var lodCount = _ocean.CurrentLodCount; + var lodDataAnimWaves = _ocean._lodDataAnimWaves; _mpb.SetInt(LodDataMgr.sp_LD_SliceIndex, lodIdx); lodDataAnimWaves.BindResultData(_mpb); - var lodDataClipSurface = OceanRenderer.Instance._lodDataClipSurface; + var lodDataClipSurface = _ocean._lodDataClipSurface; if (lodDataClipSurface != null) { lodDataClipSurface.BindResultData(_mpb); @@ -66,12 +69,12 @@ private void LateUpdate() } // blend LOD 0 shape in/out to avoid pop, if the ocean might scale up later (it is smaller than its maximum scale) - bool needToBlendOutShape = lodIdx == 0 && OceanRenderer.Instance.ScaleCouldIncrease; - float meshScaleLerp = needToBlendOutShape ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 0f; + bool needToBlendOutShape = lodIdx == 0 && _ocean.ScaleCouldIncrease; + float meshScaleLerp = needToBlendOutShape ? _ocean.ViewerAltitudeLevelAlpha : 0f; // blend furthest normals scale in/out to avoid pop, if scale could reduce - bool needToBlendOutNormals = lodIdx == lodCount - 1 && OceanRenderer.Instance.ScaleCouldDecrease; - float farNormalsWeight = needToBlendOutNormals ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 1f; + bool needToBlendOutNormals = lodIdx == lodCount - 1 && _ocean.ScaleCouldDecrease; + float farNormalsWeight = needToBlendOutNormals ? _ocean.ViewerAltitudeLevelAlpha : 1f; _mpb.SetVector(OceanChunkRenderer.sp_InstanceData, new Vector3(meshScaleLerp, farNormalsWeight, lodIdx)); _rend.SetPropertyBlock(_mpb.materialPropertyBlock); @@ -84,13 +87,13 @@ void LateUpdateBounds() { // make sure we're at sea level. we will expand the bounds which only works at sea level float y = transform.position.y; - if (!Mathf.Approximately(y, OceanRenderer.Instance.SeaLevel)) + if (!Mathf.Approximately(y, _ocean.SeaLevel)) { - transform.position += (OceanRenderer.Instance.SeaLevel - y) * Vector3.up; + transform.position += (_ocean.SeaLevel - y) * Vector3.up; } var bounds = _boundsLocal; - OceanChunkRenderer.ExpandBoundsForDisplacements(transform, ref bounds); + OceanChunkRenderer.ExpandBoundsForDisplacements(_ocean, transform, ref bounds); _mesh.bounds = bounds; if (_drawBounds) diff --git a/crest/Assets/Crest/Crest/Scripts/Helpers/TextureArrayHelpers.cs b/crest/Assets/Crest/Crest/Scripts/Helpers/TextureArrayHelpers.cs index 5ab20d108..22e4b1a22 100644 --- a/crest/Assets/Crest/Crest/Scripts/Helpers/TextureArrayHelpers.cs +++ b/crest/Assets/Crest/Crest/Scripts/Helpers/TextureArrayHelpers.cs @@ -44,10 +44,11 @@ public static void ClearToBlack(RenderTexture dst) return; } s_clearToBlackShader.SetTexture(krnl_ClearToBlack, sp_LD_TexArray_Target, dst); + // todo - make lod data resolution a global setting (or pass in ocean?) s_clearToBlackShader.Dispatch( krnl_ClearToBlack, - OceanRenderer.Instance.LodDataResolution / PropertyWrapperCompute.THREAD_GROUP_SIZE_X, - OceanRenderer.Instance.LodDataResolution / PropertyWrapperCompute.THREAD_GROUP_SIZE_Y, + OceanRenderer.AnyInstance.LodDataResolution / PropertyWrapperCompute.THREAD_GROUP_SIZE_X, + OceanRenderer.AnyInstance.LodDataResolution / PropertyWrapperCompute.THREAD_GROUP_SIZE_Y, dst.volumeDepth ); } diff --git a/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs b/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs index df432014a..0b01297f9 100644 --- a/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs +++ b/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs @@ -40,6 +40,7 @@ public partial class UnderwaterEffect : MonoBehaviour // how many vertical edges to add to curtain geometry const int GEOM_HORIZ_DIVISIONS = 64; + OceanRenderer _ocean; PropertyWrapperMPB _mpb; Renderer _rend; @@ -62,8 +63,11 @@ private void Start() _rend.sortingOrder = _overrideSortingOrder ? _overridenSortingOrder : -LodDataMgr.MAX_LOD_COUNT - 1; GetComponent().sharedMesh = Mesh2DGrid(0, 2, -0.5f, -0.5f, 1f, 1f, GEOM_HORIZ_DIVISIONS, 1); + // TODO - how to connect camera/underwater effect with ocean? + _ocean = OceanRenderer.AnyInstance; + #if UNITY_EDITOR - if (EditorApplication.isPlaying && !Validate(OceanRenderer.Instance, ValidatedHelper.DebugLog)) + if (EditorApplication.isPlaying && !Validate(_ocean, ValidatedHelper.DebugLog)) { enabled = false; return; @@ -79,7 +83,7 @@ private void Start() void ConfigureMaterial() { - if (OceanRenderer.Instance == null) return; + if (_ocean == null) return; #if UNITY_EDITOR // This prevents the shader/material from going shader error pink. @@ -88,7 +92,7 @@ void ConfigureMaterial() if (_copyParamsOnStartup) { - _rend.sharedMaterial.CopyPropertiesFromMaterial(OceanRenderer.Instance.OceanMaterial); + _rend.sharedMaterial.CopyPropertiesFromMaterial(_ocean.OceanMaterial); } } @@ -102,7 +106,7 @@ private void LateUpdate() } #endif - if (OceanRenderer.Instance == null || !ShowEffect()) + if (_ocean == null || !ShowEffect()) { _rend.enabled = false; return; @@ -124,7 +128,7 @@ private void LateUpdate() { if (_copyParamsEachFrame) { - _rend.sharedMaterial.CopyPropertiesFromMaterial(OceanRenderer.Instance.OceanMaterial); + _rend.sharedMaterial.CopyPropertiesFromMaterial(_ocean.OceanMaterial); } // Assign lod0 shape - trivial but bound every frame because lod transform comes from here @@ -136,20 +140,20 @@ private void LateUpdate() // Underwater rendering uses displacements for intersecting the waves with the near plane, and ocean depth/shadows for ScatterColour() _mpb.SetInt(LodDataMgr.sp_LD_SliceIndex, 0); - OceanRenderer.Instance._lodDataAnimWaves.BindResultData(_mpb); + _ocean._lodDataAnimWaves.BindResultData(_mpb); - if (OceanRenderer.Instance._lodDataSeaDepths != null) + if (_ocean._lodDataSeaDepths != null) { - OceanRenderer.Instance._lodDataSeaDepths.BindResultData(_mpb); + _ocean._lodDataSeaDepths.BindResultData(_mpb); } else { LodDataMgrSeaFloorDepth.BindNull(_mpb); } - if (OceanRenderer.Instance._lodDataShadow != null) + if (_ocean._lodDataShadow != null) { - OceanRenderer.Instance._lodDataShadow.BindResultData(_mpb); + _ocean._lodDataShadow.BindResultData(_mpb); } else { @@ -158,7 +162,7 @@ private void LateUpdate() _mpb.SetFloat(sp_HeightOffset, heightOffset); - _mpb.SetVector(OceanChunkRenderer.sp_InstanceData, new Vector3(OceanRenderer.Instance.ViewerAltitudeLevelAlpha, 0f, 0f)); + _mpb.SetVector(OceanChunkRenderer.sp_InstanceData, new Vector3(_ocean.ViewerAltitudeLevelAlpha, 0f, 0f)); _rend.SetPropertyBlock(_mpb.materialPropertyBlock); } diff --git a/crest/Assets/Crest/Crest/Scripts/Interaction/BoatProbes.cs b/crest/Assets/Crest/Crest/Scripts/Interaction/BoatProbes.cs index f20e78ef7..4d71e0df1 100644 --- a/crest/Assets/Crest/Crest/Scripts/Interaction/BoatProbes.cs +++ b/crest/Assets/Crest/Crest/Scripts/Interaction/BoatProbes.cs @@ -70,7 +70,7 @@ private void Start() _rb = GetComponent(); _rb.centerOfMass = _centerOfMass; - if (OceanRenderer.Instance == null) + if (OceanRenderer.AnyInstance == null) { enabled = false; return; @@ -98,19 +98,20 @@ private void FixedUpdate() // Sum weights every frame when running in editor in case weights are edited in the inspector. CalcTotalWeight(); #endif + var ocean = OceanRenderer.ClosestInstance(transform.position); - if (OceanRenderer.Instance == null) + if (ocean == null) { return; } - var collProvider = OceanRenderer.Instance.CollisionProvider; + var collProvider = ocean.CollisionProvider; // Do queries UpdateWaterQueries(collProvider); var undispPos = transform.position - _queryResultDisps[_forcePoints.Length]; - undispPos.y = OceanRenderer.Instance.SeaLevel; + undispPos.y = ocean.SeaLevel; var waterSurfaceVel = _queryResultVels[_forcePoints.Length]; @@ -121,7 +122,7 @@ private void FixedUpdate() } // Buoyancy - FixedUpdateBuoyancy(); + FixedUpdateBuoyancy(ocean); FixedUpdateDrag(waterSurfaceVel); FixedUpdateEngine(); } @@ -152,13 +153,13 @@ void FixedUpdateEngine() _rb.AddTorque(rotVec * _turnPower * sideways, ForceMode.Acceleration); } - void FixedUpdateBuoyancy() + void FixedUpdateBuoyancy(OceanRenderer ocean) { var archimedesForceMagnitude = WATER_DENSITY * Mathf.Abs(Physics.gravity.y); for (int i = 0; i < _forcePoints.Length; i++) { - var waterHeight = OceanRenderer.Instance.SeaLevel + _queryResultDisps[i].y; + var waterHeight = ocean.SeaLevel + _queryResultDisps[i].y; var heightDiff = waterHeight - _queryPoints[i].y; if (heightDiff > 0) { diff --git a/crest/Assets/Crest/Crest/Scripts/Interaction/ObjectWaterInteraction.cs b/crest/Assets/Crest/Crest/Scripts/Interaction/ObjectWaterInteraction.cs index 304d80605..8cd8b9ea6 100644 --- a/crest/Assets/Crest/Crest/Scripts/Interaction/ObjectWaterInteraction.cs +++ b/crest/Assets/Crest/Crest/Scripts/Interaction/ObjectWaterInteraction.cs @@ -41,14 +41,14 @@ public partial class ObjectWaterInteraction : MonoBehaviour private void Start() { - if (OceanRenderer.Instance == null) + if (OceanRenderer.AnyInstance == null) { enabled = false; return; } #if UNITY_EDITOR - if (EditorApplication.isPlaying && !Validate(OceanRenderer.Instance, ValidatedHelper.DebugLog)) + if (EditorApplication.isPlaying && !Validate(OceanRenderer.AnyInstance, ValidatedHelper.DebugLog)) { enabled = false; return; @@ -68,14 +68,16 @@ private void Start() void LateUpdate() { - if (OceanRenderer.Instance == null) + var ocean = OceanRenderer.ClosestInstance(transform.position); + + if (ocean == null) { return; } // which lod is this object in (roughly)? var thisRect = new Rect(new Vector2(transform.position.x, transform.position.z), Vector3.zero); - var minLod = LodDataMgrAnimWaves.SuggestDataLOD(thisRect); + var minLod = LodDataMgrAnimWaves.SuggestDataLOD(ocean, thisRect); if (minLod == -1) { // outside all lods, nothing to update! @@ -85,7 +87,7 @@ void LateUpdate() // how many active wave sims currently apply to this object - ideally this would eliminate sims that are too // low res, by providing a max grid size param int simsPresent, simsActive; - LodDataMgrDynWaves.CountWaveSims(minLod, out simsPresent, out simsActive); + LodDataMgrDynWaves.CountWaveSims(ocean, minLod, out simsPresent, out simsActive); // counting non-existent sims is expensive - stop updating if none found if (simsPresent == 0) @@ -100,8 +102,6 @@ void LateUpdate() transform.position = transform.parent.TransformPoint(_localOffset) + _velocityPositionOffset * _boat.Velocity; - var ocean = OceanRenderer.Instance; - // feed in water velocity var vel = (transform.position - _posLast) / ocean.DeltaTimeDynamics; if (ocean.DeltaTimeDynamics < 0.0001f) diff --git a/crest/Assets/Crest/Crest/Scripts/Interaction/ObjectWaterInteractionAdaptor.cs b/crest/Assets/Crest/Crest/Scripts/Interaction/ObjectWaterInteractionAdaptor.cs index 37f0ad974..0ab257f08 100644 --- a/crest/Assets/Crest/Crest/Scripts/Interaction/ObjectWaterInteractionAdaptor.cs +++ b/crest/Assets/Crest/Crest/Scripts/Interaction/ObjectWaterInteractionAdaptor.cs @@ -27,18 +27,19 @@ public class ObjectWaterInteractionAdaptor : FloatingObjectBase private void Update() { - if (OceanRenderer.Instance == null) + var ocean = OceanRenderer.ClosestInstance(transform.position); + if (ocean == null) { return; } _queryPoints[0] = transform.position; - var result = OceanRenderer.Instance.CollisionProvider.Query(GetHashCode(), ObjectWidth, _queryPoints, _resultDisps, null, null); - if (OceanRenderer.Instance.CollisionProvider.RetrieveSucceeded(result)) + var result = ocean.CollisionProvider.Query(GetHashCode(), ObjectWidth, _queryPoints, _resultDisps, null, null); + if (ocean.CollisionProvider.RetrieveSucceeded(result)) { _hasWaterData = true; - _height = OceanRenderer.Instance.SeaLevel + _resultDisps[0].y; + _height = ocean.SeaLevel + _resultDisps[0].y; } if (Time.deltaTime > 0.00001f) diff --git a/crest/Assets/Crest/Crest/Scripts/Interaction/SimpleFloatingObject.cs b/crest/Assets/Crest/Crest/Scripts/Interaction/SimpleFloatingObject.cs index d3affb5c5..ceb152a9f 100644 --- a/crest/Assets/Crest/Crest/Scripts/Interaction/SimpleFloatingObject.cs +++ b/crest/Assets/Crest/Crest/Scripts/Interaction/SimpleFloatingObject.cs @@ -52,7 +52,7 @@ void Start() { _rb = GetComponent(); - if (OceanRenderer.Instance == null) + if (OceanRenderer.AnyInstance == null) { enabled = false; return; @@ -63,7 +63,8 @@ void FixedUpdate() { UnityEngine.Profiling.Profiler.BeginSample("SimpleFloatingObject.FixedUpdate"); - if (OceanRenderer.Instance == null) + var ocean = OceanRenderer.ClosestInstance(transform.position); + if (ocean == null) { UnityEngine.Profiling.Profiler.EndSample(); return; @@ -87,7 +88,7 @@ void FixedUpdate() var velocityRelativeToWater = _rb.velocity - waterSurfaceVel; - float height = disp.y + OceanRenderer.Instance.SeaLevel; + float height = disp.y + ocean.SeaLevel; float bottomDepth = height - transform.position.y + _raiseObject; diff --git a/crest/Assets/Crest/Crest/Scripts/Interaction/SphereWaterInteraction.cs b/crest/Assets/Crest/Crest/Scripts/Interaction/SphereWaterInteraction.cs index 514304ead..12900ab5c 100644 --- a/crest/Assets/Crest/Crest/Scripts/Interaction/SphereWaterInteraction.cs +++ b/crest/Assets/Crest/Crest/Scripts/Interaction/SphereWaterInteraction.cs @@ -50,14 +50,14 @@ public partial class SphereWaterInteraction : MonoBehaviour private void Start() { - if (OceanRenderer.Instance == null) + if (OceanRenderer.AnyInstance == null) { enabled = false; return; } #if UNITY_EDITOR - if (EditorApplication.isPlaying && !Validate(OceanRenderer.Instance, ValidatedHelper.DebugLog)) + if (EditorApplication.isPlaying && !Validate(OceanRenderer.AnyInstance, ValidatedHelper.DebugLog)) { enabled = false; return; @@ -76,12 +76,12 @@ private void Start() void LateUpdate() { - var ocean = OceanRenderer.Instance; + var ocean = OceanRenderer.ClosestInstance(transform.position); if (ocean == null) return; // Which lod is this object in (roughly)? int simsActive; - if (!LateUpdateCountOverlappingSims(out simsActive, out _)) + if (!LateUpdateCountOverlappingSims(ocean, out simsActive, out _)) { // No sims running - abort. don't bother switching off renderer - camera wont be active return; @@ -118,13 +118,13 @@ void LateUpdate() // Multiple sims run at different scales in the world. Count how many sims this interaction will overlap, so that // we can normalize the interaction force for the number of sims. - bool LateUpdateCountOverlappingSims(out int simsActive, out int simsPresent) + bool LateUpdateCountOverlappingSims(OceanRenderer ocean, out int simsActive, out int simsPresent) { simsActive = 0; simsPresent = 0; var thisRect = new Rect(new Vector2(transform.position.x, transform.position.z), Vector3.zero); - var minLod = LodDataMgrAnimWaves.SuggestDataLOD(thisRect); + var minLod = LodDataMgrAnimWaves.SuggestDataLOD(ocean, thisRect); if (minLod == -1) { // Outside all lods, nothing to update! @@ -133,7 +133,7 @@ bool LateUpdateCountOverlappingSims(out int simsActive, out int simsPresent) // How many active wave sims currently apply to this object - ideally this would eliminate sims that are too // low res, by providing a max grid size param - LodDataMgrDynWaves.CountWaveSims(minLod, out simsPresent, out simsActive); + LodDataMgrDynWaves.CountWaveSims(ocean, minLod, out simsPresent, out simsActive); if (simsPresent == 0) { diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgr.cs b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgr.cs index 28821a3f0..bcfa4f05c 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgr.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgr.cs @@ -55,7 +55,7 @@ public virtual void Start() enabled = true; } - public static RenderTexture CreateLodDataTextures(RenderTextureDescriptor desc, string name, bool needToReadWriteTextureData) + public static RenderTexture CreateLodDataTextures(OceanRenderer ocean, RenderTextureDescriptor desc, string name, bool needToReadWriteTextureData) { RenderTexture result = new RenderTexture(desc); result.wrapMode = TextureWrapMode.Clamp; @@ -65,7 +65,7 @@ public static RenderTexture CreateLodDataTextures(RenderTextureDescriptor desc, result.useMipMap = false; result.name = name; result.dimension = TextureDimension.Tex2DArray; - result.volumeDepth = OceanRenderer.Instance.CurrentLodCount; + result.volumeDepth = ocean.CurrentLodCount; result.enableRandomWrite = needToReadWriteTextureData; result.Create(); return result; @@ -75,16 +75,16 @@ protected virtual void InitData() { Debug.Assert(SystemInfo.SupportsRenderTextureFormat(TextureFormat), "The graphics device does not support the render texture format " + TextureFormat.ToString()); - Debug.Assert(OceanRenderer.Instance.CurrentLodCount <= MAX_LOD_COUNT); + Debug.Assert(_ocean.CurrentLodCount <= MAX_LOD_COUNT); - var resolution = OceanRenderer.Instance.LodDataResolution; + var resolution = _ocean.LodDataResolution; var desc = new RenderTextureDescriptor(resolution, resolution, TextureFormat, 0); - _targets = CreateLodDataTextures(desc, SimName, NeedToReadWriteTextureData); + _targets = CreateLodDataTextures(_ocean, desc, SimName, NeedToReadWriteTextureData); } public virtual void UpdateLodData() { - int width = OceanRenderer.Instance.LodDataResolution; + int width = _ocean.LodDataResolution; // debug functionality to resize RT if different size was specified. if (_shapeRes == -1) { @@ -100,7 +100,7 @@ public virtual void UpdateLodData() } // determine if this LOD has changed scale and by how much (in exponent of 2) - float oceanLocalScale = OceanRenderer.Instance.Root.localScale.x; + float oceanLocalScale = _ocean.Root.localScale.x; if (_oceanLocalScalePrev == -1f) _oceanLocalScalePrev = oceanLocalScale; float ratio = oceanLocalScale / _oceanLocalScalePrev; _oceanLocalScalePrev = oceanLocalScale; @@ -110,7 +110,7 @@ public virtual void UpdateLodData() public void BindResultData(IPropertyWrapper properties, bool blendOut = true) { - BindData(properties, _targets, blendOut, ref OceanRenderer.Instance._lodTransform._renderData); + BindData(properties, _targets, blendOut, ref _ocean._lodTransform._renderData); } // Avoid heap allocations instead BindData @@ -124,21 +124,21 @@ protected virtual void BindData(IPropertyWrapper properties, Texture applyData, properties.SetTexture(GetParamIdSampler(sourceLod), applyData); } - for (int lodIdx = 0; lodIdx < OceanRenderer.Instance.CurrentLodCount; lodIdx++) + for (int lodIdx = 0; lodIdx < _ocean.CurrentLodCount; lodIdx++) { // NOTE: gets zeroed by unity, see https://www.alanzucconi.com/2016/10/24/arrays-shaders-unity-5-4/ _BindData_paramIdPosScales[lodIdx] = new Vector4( renderData[lodIdx]._posSnapped.x, renderData[lodIdx]._posSnapped.z, - OceanRenderer.Instance.CalcLodScale(lodIdx), 0f); + _ocean.CalcLodScale(lodIdx), 0f); _BindData_paramIdOceans[lodIdx] = new Vector4(renderData[lodIdx]._texelWidth, renderData[lodIdx]._textureRes, 1f, 1f / renderData[lodIdx]._textureRes); } // Duplicate the last element as the shader accesses element {slice index + 1] in a few situations. This way going // off the end of this parameter is the same as going off the end of the texture array with our clamped sampler. - _BindData_paramIdPosScales[OceanRenderer.Instance.CurrentLodCount] = _BindData_paramIdPosScales[OceanRenderer.Instance.CurrentLodCount - 1]; - _BindData_paramIdOceans[OceanRenderer.Instance.CurrentLodCount] = _BindData_paramIdOceans[OceanRenderer.Instance.CurrentLodCount - 1]; + _BindData_paramIdPosScales[_ocean.CurrentLodCount] = _BindData_paramIdPosScales[_ocean.CurrentLodCount - 1]; + _BindData_paramIdOceans[_ocean.CurrentLodCount] = _BindData_paramIdOceans[_ocean.CurrentLodCount - 1]; // Never use this last lod - it exists to give 'something' but should not be used - _BindData_paramIdOceans[OceanRenderer.Instance.CurrentLodCount].z = 0f; + _BindData_paramIdOceans[_ocean.CurrentLodCount].z = 0f; properties.SetVectorArray(LodTransform.ParamIdPosScale(sourceLod), _BindData_paramIdPosScales); properties.SetVectorArray(LodTransform.ParamIdOcean(sourceLod), _BindData_paramIdOceans); @@ -162,7 +162,7 @@ public interface IDrawFilter protected void SubmitDraws(int lodIdx, CommandBuffer buf) { - var lt = OceanRenderer.Instance._lodTransform; + var lt = _ocean._lodTransform; lt._renderData[lodIdx].Validate(0, SimName); lt.SetViewProjectionMatrices(lodIdx, buf); @@ -175,13 +175,13 @@ protected void SubmitDraws(int lodIdx, CommandBuffer buf) continue; } - draw.Value.Draw(buf, 1f, 0, lodIdx); + draw.Value.Draw(_ocean, buf, 1f, 0, lodIdx); } } protected void SubmitDrawsFiltered(int lodIdx, CommandBuffer buf, IDrawFilter filter) { - var lt = OceanRenderer.Instance._lodTransform; + var lt = _ocean._lodTransform; lt._renderData[lodIdx].Validate(0, SimName); lt.SetViewProjectionMatrices(lodIdx, buf); @@ -198,7 +198,7 @@ protected void SubmitDrawsFiltered(int lodIdx, CommandBuffer buf, IDrawFilter fi float weight = filter.Filter(draw.Value, out isTransition); if (weight > 0f) { - draw.Value.Draw(buf, weight, isTransition, lodIdx); + draw.Value.Draw(_ocean, buf, weight, isTransition, lodIdx); } } } @@ -210,7 +210,7 @@ protected struct TextureArrayParamIds public TextureArrayParamIds(string textureArrayName) { _paramId = Shader.PropertyToID(textureArrayName); - // Note: string concatonation does generate a small amount of + // Note: string concatenation does generate a small amount of // garbage. However, this is called on initialisation so should // be ok for now? Something worth considering for the future if // we want to go garbage-free. diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrAnimWaves.cs b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrAnimWaves.cs index c8e3a0b35..9d04f4e31 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrAnimWaves.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrAnimWaves.cs @@ -92,15 +92,15 @@ protected override void InitData() // for all LODs, we employ a compute shader as only they can // read and write to the same texture. - int resolution = OceanRenderer.Instance.LodDataResolution; + int resolution = _ocean.LodDataResolution; var desc = new RenderTextureDescriptor(resolution, resolution, TextureFormat, 0); - _waveBuffers = CreateLodDataTextures(desc, "WaveBuffer", false); + _waveBuffers = CreateLodDataTextures(_ocean, desc, "WaveBuffer", false); _combineBuffer = CreateCombineBuffer(desc); var combineShader = Shader.Find("Hidden/Crest/Simulation/Combine Animated Wave LODs"); - _combineMaterial = new PropertyWrapperMaterial[OceanRenderer.Instance.CurrentLodCount]; + _combineMaterial = new PropertyWrapperMaterial[_ocean.CurrentLodCount]; for (int i = 0; i < _combineMaterial.Length; i++) { var mat = new Material(combineShader); @@ -148,10 +148,11 @@ public class FilterWavelength : IDrawFilter public int _lodIdx; public int _lodCount; public float _globalMaxWavelength; + public OceanRenderer _ocean; public float Filter(ILodDataInput data, out int isTransition) { - var drawOctaveWavelength = data.Wavelength; + var drawOctaveWavelength = data.Wavelength(_ocean); isTransition = 0; // No wavelength preference - don't draw per-lod @@ -172,12 +173,12 @@ public float Filter(ILodDataInput data, out int isTransition) if (_lodIdx == _lodCount - 2) { isTransition = 1; - return 1f - OceanRenderer.Instance.ViewerAltitudeLevelAlpha; + return 1f - _ocean.ViewerAltitudeLevelAlpha; } if (_lodIdx == _lodCount - 1) { - return OceanRenderer.Instance.ViewerAltitudeLevelAlpha; + return _ocean.ViewerAltitudeLevelAlpha; } } else if (drawOctaveWavelength < _lodMaxWavelength) @@ -193,10 +194,12 @@ public float Filter(ILodDataInput data, out int isTransition) public class FilterNoLodPreference : IDrawFilter { + public OceanRenderer _ocean; + public float Filter(ILodDataInput data, out int isTransition) { isTransition = 0; - return data.Wavelength == 0f ? 1f : 0f; + return data.Wavelength(_ocean) == 0f ? 1f : 0f; } } FilterNoLodPreference _filterNoLodPreference = new FilterNoLodPreference(); @@ -205,12 +208,12 @@ public override void BuildCommandBuffer(OceanRenderer ocean, CommandBuffer buf) { base.BuildCommandBuffer(ocean, buf); - var lodCount = OceanRenderer.Instance.CurrentLodCount; + var lodCount = _ocean.CurrentLodCount; // Validation - for (int lodIdx = 0; lodIdx < OceanRenderer.Instance.CurrentLodCount; lodIdx++) + for (int lodIdx = 0; lodIdx < _ocean.CurrentLodCount; lodIdx++) { - OceanRenderer.Instance._lodTransform._renderData[lodIdx].Validate(0, SimName); + _ocean._lodTransform._renderData[lodIdx].Validate(0, SimName); } // lod-dependent data @@ -222,9 +225,10 @@ public override void BuildCommandBuffer(OceanRenderer ocean, CommandBuffer buf) // draw any data with lod preference _filterWavelength._lodIdx = lodIdx; - _filterWavelength._lodMaxWavelength = OceanRenderer.Instance._lodTransform.MaxWavelength(lodIdx); + _filterWavelength._lodMaxWavelength = _ocean._lodTransform.MaxWavelength(lodIdx); _filterWavelength._lodMinWavelength = _filterWavelength._lodMaxWavelength / 2f; - _filterWavelength._globalMaxWavelength = OceanRenderer.Instance._lodTransform.MaxWavelength(OceanRenderer.Instance.CurrentLodCount - 1); + _filterWavelength._globalMaxWavelength = _ocean._lodTransform.MaxWavelength(_ocean.CurrentLodCount - 1); + _filterWavelength._ocean = ocean; SubmitDrawsFiltered(lodIdx, buf, _filterWavelength); } @@ -244,13 +248,14 @@ public override void BuildCommandBuffer(OceanRenderer ocean, CommandBuffer buf) buf.SetRenderTarget(_targets, 0, CubemapFace.Unknown, lodIdx); // draw any data that did not express a preference for one lod or another + _filterNoLodPreference._ocean = _ocean; SubmitDrawsFiltered(lodIdx, buf, _filterNoLodPreference); } } void CombinePassPingPong(CommandBuffer buf) { - var lodCount = OceanRenderer.Instance.CurrentLodCount; + var lodCount = _ocean.CurrentLodCount; const int shaderPassCombineIntoAux = 0, shaderPassCopyResultBack = 1; // combine waves @@ -270,10 +275,10 @@ void CombinePassPingPong(CommandBuffer buf) } // Dynamic waves - if (OceanRenderer.Instance._lodDataDynWaves != null) + if (_ocean._lodDataDynWaves != null) { - OceanRenderer.Instance._lodDataDynWaves.BindCopySettings(_combineMaterial[lodIdx]); - OceanRenderer.Instance._lodDataDynWaves.BindResultData(_combineMaterial[lodIdx]); + _ocean._lodDataDynWaves.BindCopySettings(_combineMaterial[lodIdx]); + _ocean._lodDataDynWaves.BindResultData(_combineMaterial[lodIdx]); } else { @@ -281,9 +286,9 @@ void CombinePassPingPong(CommandBuffer buf) } // Flow - if (OceanRenderer.Instance._lodDataFlow != null) + if (_ocean._lodDataFlow != null) { - OceanRenderer.Instance._lodDataFlow.BindResultData(_combineMaterial[lodIdx]); + _ocean._lodDataFlow.BindResultData(_combineMaterial[lodIdx]); } else { @@ -305,13 +310,13 @@ void CombinePassPingPong(CommandBuffer buf) void CombinePassCompute(CommandBuffer buf) { - var lodCount = OceanRenderer.Instance.CurrentLodCount; + var lodCount = _ocean.CurrentLodCount; int combineShaderKernel = krnl_ShapeCombine; int combineShaderKernel_lastLOD = krnl_ShapeCombine_DISABLE_COMBINE; { - bool isFlowOn = OceanRenderer.Instance._lodDataFlow != null; - bool isDynWavesOn = OceanRenderer.Instance._lodDataDynWaves != null; + bool isFlowOn = _ocean._lodDataFlow != null; + bool isDynWavesOn = _ocean._lodDataDynWaves != null; // set the shader kernels that we will use. if (isFlowOn && isDynWavesOn) { @@ -351,10 +356,10 @@ void CombinePassCompute(CommandBuffer buf) BindResultData(_combineProperties); // Dynamic waves - if (OceanRenderer.Instance._lodDataDynWaves != null) + if (_ocean._lodDataDynWaves != null) { - OceanRenderer.Instance._lodDataDynWaves.BindCopySettings(_combineProperties); - OceanRenderer.Instance._lodDataDynWaves.BindResultData(_combineProperties); + _ocean._lodDataDynWaves.BindCopySettings(_combineProperties); + _ocean._lodDataDynWaves.BindResultData(_combineProperties); } else { @@ -362,9 +367,9 @@ void CombinePassCompute(CommandBuffer buf) } // Flow - if (OceanRenderer.Instance._lodDataFlow != null) + if (_ocean._lodDataFlow != null) { - OceanRenderer.Instance._lodDataFlow.BindResultData(_combineProperties); + _ocean._lodDataFlow.BindResultData(_combineProperties); } else { @@ -378,27 +383,27 @@ void CombinePassCompute(CommandBuffer buf) ); _combineProperties.SetInt(sp_LD_SliceIndex, lodIdx); - _combineProperties.DispatchShader(); + _combineProperties.DispatchShader(_ocean); } } public void BindWaveBuffer(IPropertyWrapper properties, bool sourceLod = false) { properties.SetTexture(sp_LD_TexArray_WaveBuffer, _waveBuffers); - BindData(properties, null, true, ref OceanRenderer.Instance._lodTransform._renderData, sourceLod); + BindData(properties, null, true, ref _ocean._lodTransform._renderData, sourceLod); } protected override void BindData(IPropertyWrapper properties, Texture applyData, bool blendOut, ref LodTransform.RenderData[] renderData, bool sourceLod = false) { base.BindData(properties, applyData, blendOut, ref renderData, sourceLod); - var lt = OceanRenderer.Instance._lodTransform; + var lt = _ocean._lodTransform; - for (int lodIdx = 0; lodIdx < OceanRenderer.Instance.CurrentLodCount; lodIdx++) + for (int lodIdx = 0; lodIdx < _ocean.CurrentLodCount; lodIdx++) { // need to blend out shape if this is the largest lod, and the ocean might get scaled down later (so the largest lod will disappear) - bool needToBlendOutShape = lodIdx == OceanRenderer.Instance.CurrentLodCount - 1 && OceanRenderer.Instance.ScaleCouldDecrease && blendOut; - float shapeWeight = needToBlendOutShape ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 1f; + bool needToBlendOutShape = lodIdx == _ocean.CurrentLodCount - 1 && _ocean.ScaleCouldDecrease && blendOut; + float shapeWeight = needToBlendOutShape ? _ocean.ViewerAltitudeLevelAlpha : 1f; _BindData_paramIdOceans[lodIdx] = new Vector4( lt._renderData[lodIdx]._texelWidth, lt._renderData[lodIdx]._textureRes, shapeWeight, @@ -412,14 +417,14 @@ protected override void BindData(IPropertyWrapper properties, Texture applyData, /// spatial length. If no such lod available, returns -1. This means high frequency wavelengths are filtered out, and the lod index can /// be used for each sample in the sample area. /// - public static int SuggestDataLOD(Rect sampleAreaXZ) + public static int SuggestDataLOD(OceanRenderer ocean, Rect sampleAreaXZ) { - return SuggestDataLOD(sampleAreaXZ, Mathf.Min(sampleAreaXZ.width, sampleAreaXZ.height)); + return SuggestDataLOD(ocean, sampleAreaXZ, Mathf.Min(sampleAreaXZ.width, sampleAreaXZ.height)); } - public static int SuggestDataLOD(Rect sampleAreaXZ, float minSpatialLength) + public static int SuggestDataLOD(OceanRenderer ocean, Rect sampleAreaXZ, float minSpatialLength) { - var lodCount = OceanRenderer.Instance.CurrentLodCount; - var lt = OceanRenderer.Instance._lodTransform; + var lodCount = ocean.CurrentLodCount; + var lt = ocean._lodTransform; for (int lod = 0; lod < lodCount; lod++) { diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrClipSurface.cs b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrClipSurface.cs index 46b42cf9b..d72c6ee2e 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrClipSurface.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrClipSurface.cs @@ -30,7 +30,7 @@ public override void Start() base.Start(); #if UNITY_EDITOR - if (!OceanRenderer.Instance.OceanMaterial.IsKeywordEnabled("_CLIPSURFACE_ON")) + if (!_ocean.OceanMaterial.IsKeywordEnabled("_CLIPSURFACE_ON")) { Debug.LogWarning("Clip Surface is not enabled on the current ocean material, so the surface clipping will not work. Please enable it on the material.", _ocean); } @@ -48,10 +48,10 @@ public override void BuildCommandBuffer(OceanRenderer ocean, CommandBuffer buf) return; } - for (int lodIdx = OceanRenderer.Instance.CurrentLodCount - 1; lodIdx >= 0; lodIdx--) + for (int lodIdx = _ocean.CurrentLodCount - 1; lodIdx >= 0; lodIdx--) { buf.SetRenderTarget(_targets, 0, CubemapFace.Unknown, lodIdx); - var defaultToClip = OceanRenderer.Instance._defaultClippingState == OceanRenderer.DefaultClippingState.EverythingClipped; + var defaultToClip = _ocean._defaultClippingState == OceanRenderer.DefaultClippingState.EverythingClipped; buf.ClearRenderTarget(false, true, defaultToClip ? Color.white : Color.black); buf.SetGlobalInt(sp_LD_SliceIndex, lodIdx); SubmitDraws(lodIdx, buf); diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrDynWaves.cs b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrDynWaves.cs index c09b2f6be..184819360 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrDynWaves.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrDynWaves.cs @@ -57,7 +57,7 @@ protected override void InitData() { base.InitData(); - _active = new bool[OceanRenderer.Instance.CurrentLodCount]; + _active = new bool[_ocean.CurrentLodCount]; for (int i = 0; i < _active.Length; i++) _active[i] = true; } @@ -81,7 +81,7 @@ protected override bool BuildCommandBufferInternal(int lodIdx) return false; // check if the sim should be running - float texelWidth = OceanRenderer.Instance._lodTransform._renderData[lodIdx].Validate(0, SimName)._texelWidth; + float texelWidth = _ocean._lodTransform._renderData[lodIdx].Validate(0, SimName)._texelWidth; _active[lodIdx] = texelWidth >= Settings._minGridSize && (texelWidth <= Settings._maxGridSize || Settings._maxGridSize == 0f); return true; @@ -98,25 +98,25 @@ protected override void SetAdditionalSimParams(IPropertyWrapper simMaterial) base.SetAdditionalSimParams(simMaterial); simMaterial.SetFloat(sp_Damping, Settings._damping); - simMaterial.SetFloat(sp_Gravity, OceanRenderer.Instance.Gravity * Settings._gravityMultiplier); + simMaterial.SetFloat(sp_Gravity, _ocean.Gravity * Settings._gravityMultiplier); float laplacianKernelAngle = _rotateLaplacian ? Mathf.PI * 2f * Random.value : 0f; simMaterial.SetVector(sp_LaplacianAxisX, new Vector2(Mathf.Cos(laplacianKernelAngle), Mathf.Sin(laplacianKernelAngle))); // assign sea floor depth - to slot 1 current frame data. minor bug here - this depth will actually be from the previous frame, // because the depth is scheduled to render just before the animated waves, and this sim happens before animated waves. - if (OceanRenderer.Instance._lodDataSeaDepths != null) + if (_ocean._lodDataSeaDepths != null) { - OceanRenderer.Instance._lodDataSeaDepths.BindResultData(simMaterial); + _ocean._lodDataSeaDepths.BindResultData(simMaterial); } else { LodDataMgrSeaFloorDepth.BindNull(simMaterial); } - if (OceanRenderer.Instance._lodDataFlow != null) + if (_ocean._lodDataFlow != null) { - OceanRenderer.Instance._lodDataFlow.BindResultData(simMaterial); + _ocean._lodDataFlow.BindResultData(simMaterial); } else { @@ -124,14 +124,14 @@ protected override void SetAdditionalSimParams(IPropertyWrapper simMaterial) } } - public static void CountWaveSims(int countFrom, out int o_present, out int o_active) + public static void CountWaveSims(OceanRenderer ocean, int countFrom, out int o_present, out int o_active) { - o_present = OceanRenderer.Instance.CurrentLodCount; + o_present = ocean.CurrentLodCount; o_active = 0; for (int i = 0; i < o_present; i++) { if (i < countFrom) continue; - if (!OceanRenderer.Instance._lodDataDynWaves.SimActive(i)) continue; + if (!ocean._lodDataDynWaves.SimActive(i)) continue; o_active++; } @@ -139,7 +139,7 @@ public static void CountWaveSims(int countFrom, out int o_present, out int o_act float MaxSimDt(int lodIdx) { - var ocean = OceanRenderer.Instance; + var ocean = _ocean; // Limit timestep based on Courant constant: https://www.uio.no/studier/emner/matnat/ifi/nedlagte-emner/INF2340/v05/foiler/sim04.pdf var Cmax = Settings._courantNumber; diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrFlow.cs b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrFlow.cs index e3cba8324..bdc46ebde 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrFlow.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrFlow.cs @@ -49,7 +49,7 @@ public override void Start() base.Start(); #if UNITY_EDITOR - if (!OceanRenderer.Instance.OceanMaterial.IsKeywordEnabled("_FLOW_ON")) + if (!_ocean.OceanMaterial.IsKeywordEnabled("_FLOW_ON")) { Debug.LogWarning("Flow is not enabled on the current ocean material and will not be visible.", _ocean); } @@ -81,7 +81,7 @@ public override void BuildCommandBuffer(OceanRenderer ocean, CommandBuffer buf) return; } - for (int lodIdx = OceanRenderer.Instance.CurrentLodCount - 1; lodIdx >= 0; lodIdx--) + for (int lodIdx = _ocean.CurrentLodCount - 1; lodIdx >= 0; lodIdx--) { buf.SetRenderTarget(_targets, 0, CubemapFace.Unknown, lodIdx); buf.ClearRenderTarget(false, true, Color.black); diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrFoam.cs b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrFoam.cs index ed62ccd6e..749a73c1a 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrFoam.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrFoam.cs @@ -50,8 +50,8 @@ public override void Start() base.Start(); #if UNITY_EDITOR - if (OceanRenderer.Instance != null && OceanRenderer.Instance.OceanMaterial != null - && !OceanRenderer.Instance.OceanMaterial.IsKeywordEnabled("_FOAM_ON")) + if (_ocean != null && _ocean.OceanMaterial != null + && !_ocean.OceanMaterial.IsKeywordEnabled("_FOAM_ON")) { Debug.LogWarning("Foam is not enabled on the current ocean material and will not be visible.", _ocean); } @@ -69,12 +69,12 @@ protected override void SetAdditionalSimParams(IPropertyWrapper simMaterial) simMaterial.SetFloat(sp_ShorelineFoamStrength, Settings._shorelineFoamStrength); // assign animated waves - to slot 1 current frame data - OceanRenderer.Instance._lodDataAnimWaves.BindResultData(simMaterial); + _ocean._lodDataAnimWaves.BindResultData(simMaterial); // assign sea floor depth - to slot 1 current frame data - if (OceanRenderer.Instance._lodDataSeaDepths != null) + if (_ocean._lodDataSeaDepths != null) { - OceanRenderer.Instance._lodDataSeaDepths.BindResultData(simMaterial); + _ocean._lodDataSeaDepths.BindResultData(simMaterial); } else { @@ -82,9 +82,9 @@ protected override void SetAdditionalSimParams(IPropertyWrapper simMaterial) } // assign flow - to slot 1 current frame data - if (OceanRenderer.Instance._lodDataFlow != null) + if (_ocean._lodDataFlow != null) { - OceanRenderer.Instance._lodDataFlow.BindResultData(simMaterial); + _ocean._lodDataFlow.BindResultData(simMaterial); } else { diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrPersistent.cs b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrPersistent.cs index d8b020912..767b1c19f 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrPersistent.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrPersistent.cs @@ -56,9 +56,9 @@ protected override void InitData() { base.InitData(); - int resolution = OceanRenderer.Instance.LodDataResolution; + int resolution = _ocean.LodDataResolution; var desc = new RenderTextureDescriptor(resolution, resolution, TextureFormat, 0); - _sources = CreateLodDataTextures(desc, SimName + "_1", NeedToReadWriteTextureData); + _sources = CreateLodDataTextures(_ocean, desc, SimName + "_1", NeedToReadWriteTextureData); TextureArrayHelpers.ClearToBlack(_targets); TextureArrayHelpers.ClearToBlack(_sources); @@ -67,8 +67,8 @@ protected override void InitData() public void ValidateSourceData(bool usePrevTransform) { var renderDataToValidate = usePrevTransform ? - OceanRenderer.Instance._lodTransform._renderDataSource - : OceanRenderer.Instance._lodTransform._renderData; + _ocean._lodTransform._renderDataSource + : _ocean._lodTransform._renderData; int validationFrame = usePrevTransform ? BuildCommandBufferBase._lastUpdateFrame - OceanRenderer.FrameCount : 0; foreach (var renderData in renderDataToValidate) { @@ -79,8 +79,8 @@ public void ValidateSourceData(bool usePrevTransform) public void BindSourceData(IPropertyWrapper properties, bool paramsOnly, bool usePrevTransform, bool sourceLod = false) { var renderData = usePrevTransform ? - OceanRenderer.Instance._lodTransform._renderDataSource - : OceanRenderer.Instance._lodTransform._renderData; + _ocean._lodTransform._renderDataSource + : _ocean._lodTransform._renderData; BindData(properties, paramsOnly ? TextureArrayHelpers.BlackTextureArray : (Texture)_sources, true, ref renderData, sourceLod); } @@ -127,9 +127,9 @@ public override void BuildCommandBuffer(OceanRenderer ocean, CommandBuffer buf) ); // Bind current data - BindData(_renderSimProperties, null, false, ref OceanRenderer.Instance._lodTransform._renderData, false); + BindData(_renderSimProperties, null, false, ref _ocean._lodTransform._renderData, false); - _renderSimProperties.DispatchShaderMultiLOD(); + _renderSimProperties.DispatchShaderMultiLOD(_ocean); for (var lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--) { diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrSeaFloorDepth.cs b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrSeaFloorDepth.cs index 80689d12a..3b23602cd 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrSeaFloorDepth.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgrSeaFloorDepth.cs @@ -40,7 +40,7 @@ public override void BuildCommandBuffer(OceanRenderer ocean, CommandBuffer buf) return; } - for (int lodIdx = OceanRenderer.Instance.CurrentLodCount - 1; lodIdx >= 0; lodIdx--) + for (int lodIdx = _ocean.CurrentLodCount - 1; lodIdx >= 0; lodIdx--) { buf.SetRenderTarget(_targets, 0, CubemapFace.Unknown, lodIdx); buf.ClearRenderTarget(false, true, s_nullColor); diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/LodTransform.cs b/crest/Assets/Crest/Crest/Scripts/LodData/LodTransform.cs index 874ccebcf..a3278a7a8 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/LodTransform.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/LodTransform.cs @@ -32,7 +32,7 @@ public RenderData Validate(int frameOffset, string context) // ignore first frame - this patches errors when using edit & continue in editor if (_frame > 0 && _frame != OceanRenderer.FrameCount + frameOffset) { - Debug.LogWarning($"RenderData validation failed - {context} - _frame of data ({_frame}) != expected ({OceanRenderer.FrameCount + frameOffset}), which may indicate some update functions are being called out of order, or script execution order is broken.", OceanRenderer.Instance); + Debug.LogWarning($"RenderData validation failed - {context} - _frame of data ({_frame}) != expected ({OceanRenderer.FrameCount + frameOffset}), which may indicate some update functions are being called out of order, or script execution order is broken.", OceanRenderer.AnyInstance); } return this; } @@ -47,6 +47,8 @@ public Rect RectXZ } } + OceanRenderer _ocean; + public RenderData[] _renderData = null; public RenderData[] _renderDataSource = null; @@ -57,6 +59,11 @@ public Rect RectXZ public Matrix4x4 GetWorldToCameraMatrix(int lodIdx) { return _worldToCameraMatrix[lodIdx]; } public Matrix4x4 GetProjectionMatrix(int lodIdx) { return _projectionMatrix[lodIdx]; } + public LodTransform(OceanRenderer ocean) + { + _ocean = ocean; + } + public void InitLODData(int lodCount) { LodCount = lodCount; @@ -83,15 +90,15 @@ public void UpdateTransforms() _renderDataSource[lodIdx] = _renderData[lodIdx]; - var lodScale = OceanRenderer.Instance.CalcLodScale(lodIdx); + var lodScale = _ocean.CalcLodScale(lodIdx); var camOrthSize = 2f * lodScale; // find snap period - _renderData[lodIdx]._textureRes = OceanRenderer.Instance.LodDataResolution; + _renderData[lodIdx]._textureRes = _ocean.LodDataResolution; _renderData[lodIdx]._texelWidth = 2f * camOrthSize / _renderData[lodIdx]._textureRes; // snap so that shape texels are stationary - _renderData[lodIdx]._posSnapped = OceanRenderer.Instance.Root.position - - new Vector3(Mathf.Repeat(OceanRenderer.Instance.Root.position.x, _renderData[lodIdx]._texelWidth), 0f, Mathf.Repeat(OceanRenderer.Instance.Root.position.z, _renderData[lodIdx]._texelWidth)); + _renderData[lodIdx]._posSnapped = _ocean.Root.position + - new Vector3(Mathf.Repeat(_ocean.Root.position.x, _renderData[lodIdx]._texelWidth), 0f, Mathf.Repeat(_ocean.Root.position.z, _renderData[lodIdx]._texelWidth)); _renderData[lodIdx]._frame = OceanRenderer.FrameCount; @@ -122,10 +129,10 @@ public void SetViewProjectionMatrices(int lodIdx, CommandBuffer buf) public float MaxWavelength(int lodIdx) { - float oceanBaseScale = OceanRenderer.Instance.Scale; + float oceanBaseScale = _ocean.Scale; float maxDiameter = 4f * oceanBaseScale * Mathf.Pow(2f, lodIdx); - float maxTexelSize = maxDiameter / OceanRenderer.Instance.LodDataResolution; - return 2f * maxTexelSize * OceanRenderer.Instance.MinTexelsPerWave; + float maxTexelSize = maxDiameter / _ocean.LodDataResolution; + return 2f * maxTexelSize * _ocean.MinTexelsPerWave; } public static int ParamIdPosScale(bool sourceLod = false) diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/OceanDepthCache.cs b/crest/Assets/Crest/Crest/Scripts/LodData/OceanDepthCache.cs index c3b899fc5..9732b5306 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/OceanDepthCache.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/OceanDepthCache.cs @@ -88,7 +88,7 @@ void Start() #if UNITY_EDITOR if (EditorApplication.isPlaying && _runValidationOnStart) { - Validate(OceanRenderer.Instance, ValidatedHelper.DebugLog); + Validate(OceanRenderer.AnyInstance, ValidatedHelper.DebugLog); } #endif @@ -217,11 +217,13 @@ public void PopulateCache() if (EditorApplication.isPlaying) #endif { + var ocean = OceanRenderer.ClosestInstance(transform.position); + // Shader needs sea level to determine water depth var centerPoint = Vector3.zero; - if (OceanRenderer.Instance != null) + if (ocean != null) { - centerPoint.y = OceanRenderer.Instance.Root.position.y; + centerPoint.y = ocean.Root.position.y; } else { diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterAnimWavesInput.cs b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterAnimWavesInput.cs index 925996aa3..1f814347a 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterAnimWavesInput.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterAnimWavesInput.cs @@ -16,13 +16,7 @@ public class RegisterAnimWavesInput : RegisterLodDataInputDisplacementCorrection [SerializeField, Tooltip("Which octave to render into, for example set this to 2 to use render into the 2m-4m octave. These refer to the same octaves as the wave spectrum editor. Set this value to 0 to render into all LODs.")] float _octaveWavelength = 0f; - public override float Wavelength - { - get - { - return _octaveWavelength; - } - } + public override float Wavelength(OceanRenderer ocean) => _octaveWavelength; public readonly static Color s_gizmoColor = new Color(0f, 1f, 0f, 0.5f); protected override Color GizmoColor => s_gizmoColor; @@ -41,27 +35,28 @@ protected override void Update() { base.Update(); - if (OceanRenderer.Instance == null) - { - return; - } - - var maxDispVert = 0f; - - // let ocean system know how far from the sea level this shape may displace the surface - if (_reportRendererBoundsToOceanSystem) - { - var minY = _renderer.bounds.min.y; - var maxY = _renderer.bounds.max.y; - var seaLevel = OceanRenderer.Instance.SeaLevel; - maxDispVert = Mathf.Max(Mathf.Abs(seaLevel - minY), Mathf.Abs(seaLevel - maxY)); - } - - maxDispVert = Mathf.Max(maxDispVert, _maxDisplacementVertical); - - if (_maxDisplacementHorizontal > 0f || _maxDisplacementVertical > 0f) + for (int i = 0; i < OceanRenderer.InstanceCount; i++) { - OceanRenderer.Instance.ReportMaxDisplacementFromShape(_maxDisplacementHorizontal, maxDispVert, 0f); + var ocean = OceanRenderer.GetInstance(i); + if (ocean == null) continue; + + var maxDispVert = 0f; + + // let ocean system know how far from the sea level this shape may displace the surface + if (_reportRendererBoundsToOceanSystem) + { + var minY = _renderer.bounds.min.y; + var maxY = _renderer.bounds.max.y; + var seaLevel = ocean.SeaLevel; + maxDispVert = Mathf.Max(Mathf.Abs(seaLevel - minY), Mathf.Abs(seaLevel - maxY)); + } + + maxDispVert = Mathf.Max(maxDispVert, _maxDisplacementVertical); + + if (_maxDisplacementHorizontal > 0f || _maxDisplacementVertical > 0f) + { + ocean.ReportMaxDisplacementFromShape(_maxDisplacementHorizontal, maxDispVert, 0f); + } } } } diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterClipSurfaceInput.cs b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterClipSurfaceInput.cs index af6d654b2..5baf85e2f 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterClipSurfaceInput.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterClipSurfaceInput.cs @@ -23,7 +23,7 @@ public class RegisterClipSurfaceInput : RegisterLodDataInput 0f; + public override float Wavelength(OceanRenderer ocean) => 0f; protected override Color GizmoColor => new Color(0f, 1f, 1f, 0.5f); @@ -39,11 +39,6 @@ public class RegisterClipSurfaceInput : RegisterLodDataInput -1) { @@ -74,20 +70,24 @@ private void LateUpdate() _renderer.GetPropertyBlock(_mpb.materialPropertyBlock); - var lodCount = OceanRenderer.Instance.CurrentLodCount; - var lodDataAnimWaves = OceanRenderer.Instance._lodDataAnimWaves; + // todo - hmm this is tricky :/ - clip data does things related to the current lod. cant use material property block then. + // move onto command buffer? + var lodDataAnimWaves = OceanRenderer.AnyInstance._lodDataAnimWaves; _mpb.SetInt(LodDataMgr.sp_LD_SliceIndex, lodIdx); _mpb.SetInt(sp_DisplacementSamplingIterations, (int)_animatedWavesDisplacementSamplingIterations); lodDataAnimWaves.BindResultData(_mpb); - // blend LOD 0 shape in/out to avoid pop, if the ocean might scale up later (it is smaller than its maximum scale) - bool needToBlendOutShape = lodIdx == 0 && OceanRenderer.Instance.ScaleCouldIncrease; - float meshScaleLerp = needToBlendOutShape ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 0f; + // todo - @daleeidd is any of this needed for the clip data? + + //// blend LOD 0 shape in/out to avoid pop, if the ocean might scale up later (it is smaller than its maximum scale) + //bool needToBlendOutShape = lodIdx == 0 && OceanRenderer.Instance.ScaleCouldIncrease; + //float meshScaleLerp = needToBlendOutShape ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 0f; - // blend furthest normals scale in/out to avoid pop, if scale could reduce - bool needToBlendOutNormals = lodIdx == lodCount - 1 && OceanRenderer.Instance.ScaleCouldDecrease; - float farNormalsWeight = needToBlendOutNormals ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 1f; - _mpb.SetVector(OceanChunkRenderer.sp_InstanceData, new Vector3(meshScaleLerp, farNormalsWeight, lodIdx)); + //// blend furthest normals scale in/out to avoid pop, if scale could reduce + //var lodCount = OceanRenderer.Instance.CurrentLodCount; + //bool needToBlendOutNormals = lodIdx == lodCount - 1 && OceanRenderer.Instance.ScaleCouldDecrease; + //float farNormalsWeight = needToBlendOutNormals ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 1f; + //_mpb.SetVector(OceanChunkRenderer.sp_InstanceData, new Vector3(meshScaleLerp, farNormalsWeight, lodIdx)); _renderer.SetPropertyBlock(_mpb.materialPropertyBlock); } diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterDynWavesInput.cs b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterDynWavesInput.cs index 041707fdb..3b963f2bf 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterDynWavesInput.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterDynWavesInput.cs @@ -12,7 +12,7 @@ namespace Crest [ExecuteAlways] public class RegisterDynWavesInput : RegisterLodDataInput { - public override float Wavelength => 0f; + public override float Wavelength(OceanRenderer ocean) => 0f; public override bool Enabled => true; diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterFlowInput.cs b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterFlowInput.cs index 467a1ff27..4c0d4f544 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterFlowInput.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterFlowInput.cs @@ -14,7 +14,7 @@ public class RegisterFlowInput : RegisterLodDataInputDisplacementCorrection true; - public override float Wavelength => 0f; + public override float Wavelength(OceanRenderer ocean) => 0f; protected override Color GizmoColor => new Color(0f, 0f, 1f, 0.5f); diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterFoamInput.cs b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterFoamInput.cs index ae3336a55..37bd507b9 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterFoamInput.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterFoamInput.cs @@ -14,7 +14,7 @@ public class RegisterFoamInput : RegisterLodDataInputDisplacementCorrection true; - public override float Wavelength => 0f; + public override float Wavelength(OceanRenderer ocean) => 0f; protected override Color GizmoColor => new Color(1f, 1f, 1f, 0.5f); diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterLodDataInput.cs b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterLodDataInput.cs index 1cf367c04..cc2996c4a 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterLodDataInput.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterLodDataInput.cs @@ -31,8 +31,8 @@ public int Compare(TKey x, TKey y) public interface ILodDataInput { - void Draw(CommandBuffer buf, float weight, int isTransition, int lodIdx); - float Wavelength { get; } + void Draw(OceanRenderer ocean, CommandBuffer buf, float weight, int isTransition, int lodIdx); + float Wavelength(OceanRenderer ocean); bool Enabled { get; } } @@ -47,7 +47,7 @@ public abstract partial class RegisterLodDataInputBase : MonoBehaviour, ILodData bool _checkShaderName = true; #endif - public abstract float Wavelength { get; } + public abstract float Wavelength(OceanRenderer ocean); public abstract bool Enabled { get; } @@ -110,7 +110,7 @@ protected virtual void Update() #endif } - public void Draw(CommandBuffer buf, float weight, int isTransition, int lodIdx) + public void Draw(OceanRenderer ocean, CommandBuffer buf, float weight, int isTransition, int lodIdx) { if (_renderer && _material && weight > 0f) { diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterSeaFloorDepthInput.cs b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterSeaFloorDepthInput.cs index 6db58ea1e..8479b7655 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/RegisterSeaFloorDepthInput.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/RegisterSeaFloorDepthInput.cs @@ -17,7 +17,7 @@ public class RegisterSeaFloorDepthInput : RegisterLodDataInput 0f; + public override float Wavelength(OceanRenderer ocean) => 0f; protected override Color GizmoColor => new Color(1f, 0f, 0f, 0.5f); diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/Settings/SimSettingsAnimatedWaves.cs b/crest/Assets/Crest/Crest/Scripts/LodData/Settings/SimSettingsAnimatedWaves.cs index 58ef300a1..81deb3f01 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/Settings/SimSettingsAnimatedWaves.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/Settings/SimSettingsAnimatedWaves.cs @@ -32,7 +32,7 @@ public enum CollisionSources /// /// Provides ocean shape to CPU. /// - public ICollProvider CreateCollisionProvider() + public ICollProvider CreateCollisionProvider(OceanRenderer ocean) { ICollProvider result = null; @@ -45,7 +45,7 @@ public ICollProvider CreateCollisionProvider() result = FindObjectOfType(); break; case CollisionSources.ComputeShaderQueries: - result = new QueryDisplacements(); + result = new QueryDisplacements(ocean); break; } @@ -66,7 +66,7 @@ public IFlowProvider CreateFlowProvider(OceanRenderer ocean) // Flow is GPU only, and can only be queried using the compute path if (ocean._lodDataFlow != null) { - return new QueryFlow(); + return new QueryFlow(ocean); } return new FlowProviderNull(); diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/Shadows/LodDataMgrShadow.cs b/crest/Assets/Crest/Crest/Scripts/LodData/Shadows/LodDataMgrShadow.cs index 4fcaf7a0e..7e3973905 100644 --- a/crest/Assets/Crest/Crest/Scripts/LodData/Shadows/LodDataMgrShadow.cs +++ b/crest/Assets/Crest/Crest/Scripts/LodData/Shadows/LodDataMgrShadow.cs @@ -92,7 +92,7 @@ public override void Start() UpdateCameraMain(); #if UNITY_EDITOR - if (!OceanRenderer.Instance.OceanMaterial.IsKeywordEnabled("_SHADOWS_ON")) + if (!_ocean.OceanMaterial.IsKeywordEnabled("_SHADOWS_ON")) { Debug.LogWarning("Shadowing is not enabled on the current ocean material and will not be visible.", _ocean); } @@ -103,9 +103,9 @@ protected override void InitData() { base.InitData(); - int resolution = OceanRenderer.Instance.LodDataResolution; + int resolution = _ocean.LodDataResolution; var desc = new RenderTextureDescriptor(resolution, resolution, TextureFormat, 0); - _sources = CreateLodDataTextures(desc, SimName + "_1", NeedToReadWriteTextureData); + _sources = CreateLodDataTextures(_ocean, desc, SimName + "_1", NeedToReadWriteTextureData); TextureArrayHelpers.ClearToBlack(_sources); TextureArrayHelpers.ClearToBlack(_targets); @@ -113,17 +113,17 @@ protected override void InitData() bool StartInitLight() { - _mainLight = OceanRenderer.Instance._primaryLight; + _mainLight = _ocean._primaryLight; if (_mainLight.type != LightType.Directional) { - Debug.LogError("Primary light must be of type Directional.", OceanRenderer.Instance); + Debug.LogError("Primary light must be of type Directional.", _ocean); return false; } if (_mainLight.shadows == LightShadows.None) { - Debug.LogError("Shadows must be enabled on primary light to enable ocean shadowing (types Hard and Soft are equivalent for the ocean system).", OceanRenderer.Instance); + Debug.LogError("Shadows must be enabled on primary light to enable ocean shadowing (types Hard and Soft are equivalent for the ocean system).", _ocean); return false; } @@ -139,7 +139,7 @@ public override void UpdateLodData() base.UpdateLodData(); - if (_mainLight != OceanRenderer.Instance._primaryLight) + if (_mainLight != _ocean._primaryLight) { if (_mainLight) { @@ -151,11 +151,11 @@ public override void UpdateLodData() _mainLight = null; } - if (!OceanRenderer.Instance._primaryLight) + if (!_ocean._primaryLight) { if (!Settings._allowNullLight) { - Debug.LogWarning("Primary light must be specified on OceanRenderer script to enable shadows.", OceanRenderer.Instance); + Debug.LogWarning("Primary light must be specified on OceanRenderer script to enable shadows.", _ocean); } return; } @@ -187,7 +187,7 @@ public override void UpdateLodData() } // Update the camera if it has changed. - if (_cameraMain.transform != OceanRenderer.Instance.Viewpoint) + if (_cameraMain.transform != _ocean.Viewpoint) { UpdateCameraMain(); } @@ -208,25 +208,25 @@ public override void UpdateLodData() TextureArrayHelpers.ClearToBlack(_targets); } - var lt = OceanRenderer.Instance._lodTransform; + var lt = _ocean._lodTransform; for (var lodIdx = lt.LodCount - 1; lodIdx >= 0; lodIdx--) { _renderProperties.Initialise(BufCopyShadowMap, _updateShadowShader, krnl_UpdateShadow); lt._renderData[lodIdx].Validate(0, SimName); _renderProperties.SetVector(sp_CenterPos, lt._renderData[lodIdx]._posSnapped); - var scale = OceanRenderer.Instance.CalcLodScale(lodIdx); + var scale = _ocean.CalcLodScale(lodIdx); _renderProperties.SetVector(sp_Scale, new Vector3(scale, 1f, scale)); - if (OceanRenderer.Instance.Viewpoint != null) + if (_ocean.Viewpoint != null) { - _renderProperties.SetVector(sp_CamPos, OceanRenderer.Instance.Viewpoint.position); - _renderProperties.SetVector(sp_CamForward, OceanRenderer.Instance.Viewpoint.forward); + _renderProperties.SetVector(sp_CamPos, _ocean.Viewpoint.position); + _renderProperties.SetVector(sp_CamForward, _ocean.Viewpoint.forward); } _renderProperties.SetVector(sp_JitterDiameters_CurrentFrameWeights, new Vector4(Settings._jitterDiameterSoft, Settings._jitterDiameterHard, Settings._currentFrameWeightSoft, Settings._currentFrameWeightHard)); _renderProperties.SetMatrix(sp_MainCameraProjectionMatrix, _cameraMain.projectionMatrix * _cameraMain.worldToCameraMatrix); - _renderProperties.SetFloat(sp_SimDeltaTime, OceanRenderer.Instance.DeltaTimeDynamics); + _renderProperties.SetFloat(sp_SimDeltaTime, _ocean.DeltaTimeDynamics); // compute which lod data we are sampling previous frame shadows from. if a scale change has happened this can be any lod up or down the chain. var srcDataIdx = lodIdx + ScaleDifferencePow2; @@ -235,13 +235,13 @@ public override void UpdateLodData() _renderProperties.SetInt(sp_LD_SliceIndex_Source, srcDataIdx); BindSourceData(_renderProperties, false); _renderProperties.SetTexture(sp_LD_TexArray_Target, _targets); - _renderProperties.DispatchShader(); + _renderProperties.DispatchShader(_ocean); } } void UpdateCameraMain() { - var viewpoint = OceanRenderer.Instance.Viewpoint; + var viewpoint = _ocean.Viewpoint; _cameraMain = viewpoint != null ? viewpoint.GetComponent() : null; if (_cameraMain == null) @@ -262,7 +262,7 @@ public void ValidateSourceData() } #endif - foreach (var renderData in OceanRenderer.Instance._lodTransform._renderDataSource) + foreach (var renderData in _ocean._lodTransform._renderDataSource) { renderData.Validate(BuildCommandBufferBase._lastUpdateFrame - OceanRenderer.FrameCount, SimName); } @@ -270,7 +270,7 @@ public void ValidateSourceData() public void BindSourceData(IPropertyWrapper simMaterial, bool paramsOnly) { - var rd = OceanRenderer.Instance._lodTransform._renderDataSource; + var rd = _ocean._lodTransform._renderDataSource; BindData(simMaterial, paramsOnly ? Texture2D.blackTexture : _sources as Texture, true, ref rd, true); } diff --git a/crest/Assets/Crest/Crest/Scripts/OceanBuilder.cs b/crest/Assets/Crest/Crest/Scripts/OceanBuilder.cs index 7a75a06d1..3f95a8eed 100644 --- a/crest/Assets/Crest/Crest/Scripts/OceanBuilder.cs +++ b/crest/Assets/Crest/Crest/Scripts/OceanBuilder.cs @@ -451,6 +451,7 @@ static void CreateLOD(OceanRenderer ocean, List tiles, Trans { var oceanChunkRenderer = patch.AddComponent(); + oceanChunkRenderer._ocean = ocean; oceanChunkRenderer._boundsLocal = meshBounds[(int)patchTypes[i]]; patch.AddComponent().sharedMesh = meshData[(int)patchTypes[i]]; oceanChunkRenderer.SetInstanceData(lodIndex, lodCount, lodDataResolution, geoDownSampleFactor); diff --git a/crest/Assets/Crest/Crest/Scripts/OceanChunkRenderer.cs b/crest/Assets/Crest/Crest/Scripts/OceanChunkRenderer.cs index a6ceccc70..0579a8b46 100644 --- a/crest/Assets/Crest/Crest/Scripts/OceanChunkRenderer.cs +++ b/crest/Assets/Crest/Crest/Scripts/OceanChunkRenderer.cs @@ -17,6 +17,9 @@ namespace Crest [ExecuteAlways] public class OceanChunkRenderer : MonoBehaviour { + [HideInInspector] + public OceanRenderer _ocean; + public bool _drawRenderBounds = false; public Bounds _boundsLocal; @@ -64,7 +67,7 @@ private void Update() void UpdateMeshBounds() { var newBounds = _boundsLocal; - ExpandBoundsForDisplacements(transform, ref newBounds); + ExpandBoundsForDisplacements(_ocean, transform, ref newBounds); _mesh.bounds = newBounds; } @@ -78,7 +81,7 @@ private static void BeginCameraRendering(ScriptableRenderContext context, Camera // Called when visible to a camera void OnWillRenderObject() { - if (OceanRenderer.Instance == null || Rend == null) + if (_ocean == null || Rend == null) { return; } @@ -92,9 +95,9 @@ void OnWillRenderObject() // Depth texture is used by ocean shader for transparency/depth fog, and for fading out foam at shoreline. _currentCamera.depthTextureMode |= DepthTextureMode.Depth; - if (Rend.sharedMaterial != OceanRenderer.Instance.OceanMaterial) + if (Rend.sharedMaterial != _ocean.OceanMaterial) { - Rend.sharedMaterial = OceanRenderer.Instance.OceanMaterial; + Rend.sharedMaterial = _ocean.OceanMaterial; } // per instance data @@ -106,18 +109,18 @@ void OnWillRenderObject() Rend.GetPropertyBlock(_mpb.materialPropertyBlock); // blend LOD 0 shape in/out to avoid pop, if the ocean might scale up later (it is smaller than its maximum scale) - var needToBlendOutShape = _lodIndex == 0 && OceanRenderer.Instance.ScaleCouldIncrease; - var meshScaleLerp = needToBlendOutShape ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 0f; + var needToBlendOutShape = _lodIndex == 0 && _ocean.ScaleCouldIncrease; + var meshScaleLerp = needToBlendOutShape ? _ocean.ViewerAltitudeLevelAlpha : 0f; // blend furthest normals scale in/out to avoid pop, if scale could reduce - var needToBlendOutNormals = _lodIndex == _totalLodCount - 1 && OceanRenderer.Instance.ScaleCouldDecrease; - var farNormalsWeight = needToBlendOutNormals ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 1f; + var needToBlendOutNormals = _lodIndex == _totalLodCount - 1 && _ocean.ScaleCouldDecrease; + var farNormalsWeight = needToBlendOutNormals ? _ocean.ViewerAltitudeLevelAlpha : 1f; _mpb.SetVector(sp_InstanceData, new Vector3(meshScaleLerp, farNormalsWeight, _lodIndex)); // geometry data // compute grid size of geometry. take the long way to get there - make sure we land exactly on a power of two // and not inherit any of the lossy-ness from lossyScale. - var scale_pow_2 = OceanRenderer.Instance.CalcLodScale(_lodIndex); + var scale_pow_2 = _ocean.CalcLodScale(_lodIndex); var gridSizeGeo = scale_pow_2 / (0.25f * _lodDataResolution / _geoDownSampleFactor); var gridSizeLodData = gridSizeGeo / _geoDownSampleFactor; var mul = 1.875f; // fudge 1 @@ -127,12 +130,12 @@ void OnWillRenderObject() _mpb.SetVector(sp_GeomData, new Vector4(gridSizeLodData, gridSizeGeo, normalScrollSpeed0, normalScrollSpeed1)); // Assign LOD data to ocean shader - var ldaws = OceanRenderer.Instance._lodDataAnimWaves; - var ldsds = OceanRenderer.Instance._lodDataSeaDepths; - var ldclip = OceanRenderer.Instance._lodDataClipSurface; - var ldfoam = OceanRenderer.Instance._lodDataFoam; - var ldflow = OceanRenderer.Instance._lodDataFlow; - var ldshadows = OceanRenderer.Instance._lodDataShadow; + var ldaws = _ocean._lodDataAnimWaves; + var ldsds = _ocean._lodDataSeaDepths; + var ldclip = _ocean._lodDataClipSurface; + var ldfoam = _ocean._lodDataFoam; + var ldflow = _ocean._lodDataFlow; + var ldshadows = _ocean._lodDataShadow; _mpb.SetInt(LodDataMgr.sp_LD_SliceIndex, _lodIndex); if (ldaws != null) ldaws.BindResultData(_mpb); @@ -156,7 +159,7 @@ void OnWillRenderObject() // add a param here that forces ocean to be in underwater state. I think the root // cause here might be imprecision or numerical issues at ocean tile boundaries, although // i'm not sure why cracks are not visible in this case. - var heightOffset = OceanRenderer.Instance.ViewerHeightAboveWater; + var heightOffset = _ocean.ViewerHeightAboveWater; _mpb.SetFloat(sp_ForceUnderwater, heightOffset < -2f ? 1f : 0f); Rend.SetPropertyBlock(_mpb.materialPropertyBlock); @@ -164,11 +167,11 @@ void OnWillRenderObject() // this is called every frame because the bounds are given in world space and depend on the transform scale, which // can change depending on view altitude - public static void ExpandBoundsForDisplacements(Transform transform, ref Bounds bounds) + public static void ExpandBoundsForDisplacements(OceanRenderer ocean, Transform transform, ref Bounds bounds) { - var boundsPadding = OceanRenderer.Instance.MaxHorizDisplacement; + var boundsPadding = ocean.MaxHorizDisplacement; var expandXZ = boundsPadding / transform.lossyScale.x; - var boundsY = OceanRenderer.Instance.MaxVertDisplacement; + var boundsY = ocean.MaxVertDisplacement; // extend the kinematic bounds slightly to give room for dynamic sim stuff boundsY += 5f; bounds.extents = new Vector3(bounds.extents.x + expandXZ, boundsY / transform.lossyScale.y, bounds.extents.z + expandXZ); diff --git a/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs b/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs index 44e2394e9..238268062 100644 --- a/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs +++ b/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs @@ -2,6 +2,15 @@ // This file is subject to the MIT License as seen in the root of this folder structure (LICENSE) +// Lod data resolution should be global setting, right now taken from one instance +// Validation passed "AnyInstance" in a few places, is this ok? +// Debuggui always takes first instance +// RenderData.Validate - uses any instance +// RegisterLodDataClipSurface - this got broken +// OceanChunkRenderer.OnWillRenderObject - needs layer so it only goes in one cam +// How to connect underwater effect to ocean instance? +// How to connect underwater environment lighting with ocean instance? + using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR @@ -257,7 +266,29 @@ public enum DefaultClippingState SampleHeightHelper _sampleHeightHelper = new SampleHeightHelper(); - public static OceanRenderer Instance { get; private set; } + public static OceanRenderer AnyInstance => _instances.Count > 0 ? _instances[0] : null; + public static int InstanceCount => _instances.Count; + public static OceanRenderer GetInstance(int index) => _instances[index]; + public static OceanRenderer ClosestInstance(Vector3 position) + { + if (_instances.Count == 0) return null; + + var result = _instances[0]; + var dist2 = (result.transform.position - position).sqrMagnitude; + for (int i = 1; i < _instances.Count; i++) + { + var newdist2 = (_instances[i].transform.position - position).sqrMagnitude; + if (newdist2 < dist2) + { + result = _instances[i]; + dist2 = newdist2; + } + } + + return result; + } + + static List _instances = new List(); // We are computing these values to be optimal based on the base mesh vertex density. float _lodAlphaBlackPointFade; @@ -317,10 +348,14 @@ void OnEnable() _isFirstUpdate = true; - Instance = this; + if (!_instances.Contains(this)) + { + _instances.Add(this); + } + Scale = Mathf.Clamp(Scale, _minScale, _maxScale); - _lodTransform = new LodTransform(); + _lodTransform = new LodTransform(this); _lodTransform.InitLODData(_lodCount); // Resolution is 4 tiles across. @@ -368,23 +403,29 @@ private void OnDisable() CleanUp(); - Instance = null; + if (_instances.Contains(this)) + { + _instances.Remove(this); + } } #if UNITY_EDITOR static void EditorUpdate() { - if (Instance == null) return; - if (!EditorApplication.isPlaying) { - if (EditorApplication.timeSinceStartup - _lastUpdateEditorTime > 1f / Mathf.Clamp(Instance._editModeFPS, 0.01f, 60f)) + var editModeFPS = AnyInstance._editModeFPS; + + if (EditorApplication.timeSinceStartup - _lastUpdateEditorTime > 1f / Mathf.Clamp(editModeFPS, 0.01f, 60f)) { _editorFrames++; _lastUpdateEditorTime = (float)EditorApplication.timeSinceStartup; - Instance.RunUpdate(); + for (var i = 0; i < InstanceCount; i++) + { + GetInstance(i).RunUpdate(); + } } } } @@ -548,7 +589,7 @@ void CreateDestroySubSystems() // Potential extension - add 'type' field to collprovider and change provider if settings have changed - this would support runtime changes. if (CollisionProvider == null) { - CollisionProvider = _lodDataAnimWaves.Settings.CreateCollisionProvider(); + CollisionProvider = _lodDataAnimWaves.Settings.CreateCollisionProvider(this); } } @@ -609,7 +650,7 @@ void InitViewpoint() static void InitStatics() { // Init here from 2019.3 onwards - Instance = null; + _instances.Clear(); } void LateUpdate() @@ -678,7 +719,7 @@ void RunUpdate() if (EditorApplication.isPlaying || !_showOceanProxyPlane) #endif { - _commandbufferBuilder.BuildAndExecute(); + _commandbufferBuilder.BuildAndExecute(this); } #if UNITY_EDITOR else @@ -910,7 +951,13 @@ private void CleanUp() [UnityEditor.Callbacks.DidReloadScripts] private static void OnReLoadScripts() { - Instance = FindObjectOfType(); + if (_instances == null) + { + _instances = new List(); + } + + _instances.Clear(); + _instances.AddRange(FindObjectsOfType()); } private void OnDrawGizmos() @@ -1016,7 +1063,7 @@ public bool Validate(OceanRenderer ocean, ValidatedHelper.ShowMessage showMessag { var isValid = true; - if (EditorSettings.enterPlayModeOptionsEnabled && + if (EditorSettings.enterPlayModeOptionsEnabled && EditorSettings.enterPlayModeOptions.HasFlag(EnterPlayModeOptions.DisableSceneReload)) { showMessage diff --git a/crest/Assets/Crest/Crest/Scripts/Reflection/OceanPlanarReflection.cs b/crest/Assets/Crest/Crest/Scripts/Reflection/OceanPlanarReflection.cs index fed642c48..0a7fb633c 100644 --- a/crest/Assets/Crest/Crest/Scripts/Reflection/OceanPlanarReflection.cs +++ b/crest/Assets/Crest/Crest/Scripts/Reflection/OceanPlanarReflection.cs @@ -119,7 +119,7 @@ public class OceanPlanarReflection : MonoBehaviour private void Start() { - if (OceanRenderer.Instance == null) + if (OceanRenderer.AnyInstance == null) { enabled = false; return; @@ -139,7 +139,7 @@ private void Start() CreateWaterObjects(_camViewpoint); #if UNITY_EDITOR - if (!OceanRenderer.Instance.OceanMaterial.IsKeywordEnabled("_PLANARREFLECTIONS_ON")) + if (!OceanRenderer.AnyInstance.OceanMaterial.IsKeywordEnabled("_PLANARREFLECTIONS_ON")) { Debug.LogWarning("Planar reflections are not enabled on the current ocean material and will not be visible.", this); } @@ -163,7 +163,7 @@ private void OnPreRender() if (!RequestRefresh(Time.renderedFrameCount)) return; // Skip if not need to refresh on this frame - if (OceanRenderer.Instance == null) + if (OceanRenderer.AnyInstance == null) { return; } @@ -176,7 +176,7 @@ private void OnPreRender() } // Find out the reflection plane: position and normal in world space - Vector3 planePos = OceanRenderer.Instance.Root.position; + Vector3 planePos = OceanRenderer.AnyInstance.Root.position; Vector3 planeNormal = Vector3.up; // Optionally disable pixel lights for reflection/refraction diff --git a/crest/Assets/Crest/Crest/Scripts/Shapes/ShapeGerstnerBatched.cs b/crest/Assets/Crest/Crest/Scripts/Shapes/ShapeGerstnerBatched.cs index e2849bd06..bfff0144e 100644 --- a/crest/Assets/Crest/Crest/Scripts/Shapes/ShapeGerstnerBatched.cs +++ b/crest/Assets/Crest/Crest/Scripts/Shapes/ShapeGerstnerBatched.cs @@ -72,16 +72,16 @@ public GerstnerBatch(ShapeGerstnerBatched gerstner, int batchIndex, MeshRenderer int _batchIndex = -1; // The ocean input system uses this to decide which lod this batch belongs in - public float Wavelength => OceanRenderer.Instance._lodTransform.MaxWavelength(_batchIndex) / 2f; + public float Wavelength(OceanRenderer ocean) => ocean._lodTransform.MaxWavelength(_batchIndex) / 2f; public bool Enabled { get; set; } public bool HasWaves { get; set; } - public void Draw(CommandBuffer buf, float weight, int isTransition, int lodIdx) + public void Draw(OceanRenderer ocean, CommandBuffer buf, float weight, int isTransition, int lodIdx) { HasWaves = false; - _gerstner.UpdateBatch(this, _batchIndex); + _gerstner.UpdateBatch(ocean, this, _batchIndex); if (HasWaves && weight > 0f) { @@ -160,7 +160,7 @@ private void OnEnable() _spectrum.name = "Default Waves (auto)"; } - if (EditorApplication.isPlaying && !Validate(OceanRenderer.Instance, ValidatedHelper.DebugLog)) + if (EditorApplication.isPlaying && !Validate(OceanRenderer.AnyInstance, ValidatedHelper.DebugLog)) { enabled = false; return; @@ -223,19 +223,19 @@ public void SetOrigin(Vector3 newOrigin) float _lastUpdateTime = -1f; - void UpdateData() + void UpdateData(OceanRenderer ocean) { - if (OceanRenderer.Instance == null) return; + if (ocean == null) return; - if (_lastUpdateTime >= OceanRenderer.Instance.CurrentTime) return; - _lastUpdateTime = OceanRenderer.Instance.CurrentTime; + if (_lastUpdateTime >= ocean.CurrentTime) return; + _lastUpdateTime = ocean.CurrentTime; if (_evaluateSpectrumAtRuntime) { UpdateWaveData(); } - ReportMaxDisplacement(); + ReportMaxDisplacement(ocean); } public void UpdateWaveData() @@ -270,7 +270,7 @@ void UpdateAmplitudes() } } - private void ReportMaxDisplacement() + private void ReportMaxDisplacement(OceanRenderer ocean) { if (_spectrum._chopScales.Length != OceanWaveSpectrum.NUM_OCTAVES) { @@ -282,7 +282,7 @@ private void ReportMaxDisplacement() { ampSum += _amplitudes[i] * _spectrum._chopScales[i / _componentsPerOctave]; } - OceanRenderer.Instance.ReportMaxDisplacementFromShape(ampSum * _spectrum._chop, ampSum, ampSum); + ocean.ReportMaxDisplacementFromShape(ampSum * _spectrum._chop, ampSum, ampSum); } void InitBatches() @@ -365,7 +365,7 @@ void InitBatches() /// Computes Gerstner params for a set of waves, for the given lod idx. Writes shader data to the given property. /// Returns number of wave components rendered in this batch. /// - void UpdateBatch(int lodIdx, int firstComponent, int lastComponentNonInc, GerstnerBatch batch) + void UpdateBatch(OceanRenderer ocean, int lodIdx, int firstComponent, int lastComponentNonInc, GerstnerBatch batch) { batch.HasWaves = false; @@ -404,11 +404,11 @@ void UpdateBatch(int lodIdx, int firstComponent, int lastComponentNonInc, Gerstn // It used to be this, but I'm pushing all the stuff that doesn't depend on position into the phase. //half4 angle = k * (C * _CrestTime + x) + _Phases[vi]; float gravityScale = _spectrum._gravityScales[(firstComponent + i) / _componentsPerOctave]; - float gravity = OceanRenderer.Instance.Gravity * _spectrum._gravityScale; + float gravity = ocean.Gravity * _spectrum._gravityScale; float C = Mathf.Sqrt(wl * gravity * gravityScale * one_over_2pi); float k = twopi / wl; // Repeat every 2pi to keep angle bounded - helps precision on 16bit platforms - UpdateBatchScratchData._phasesBatch[vi][ei] = Mathf.Repeat(_phases[firstComponent + i] + k * C * OceanRenderer.Instance.CurrentTime, Mathf.PI * 2f); + UpdateBatchScratchData._phasesBatch[vi][ei] = Mathf.Repeat(_phases[firstComponent + i] + k * C * ocean.CurrentTime, Mathf.PI * 2f); numInBatch++; } @@ -464,16 +464,16 @@ void UpdateBatch(int lodIdx, int firstComponent, int lastComponentNonInc, Gerstn mat.SetVectorArray(sp_Phases, UpdateBatchScratchData._phasesBatch); mat.SetVectorArray(sp_ChopAmps, UpdateBatchScratchData._chopAmpsBatch); mat.SetFloat(sp_NumInBatch, numInBatch); - mat.SetFloat(sp_AttenuationInShallows, OceanRenderer.Instance._lodDataAnimWaves.Settings.AttenuationInShallows); + mat.SetFloat(sp_AttenuationInShallows, ocean._lodDataAnimWaves.Settings.AttenuationInShallows); int numVecs = (numInBatch + 3) / 4; mat.SetInt(sp_NumWaveVecs, numVecs); mat.SetInt(LodDataMgr.sp_LD_SliceIndex, lodIdx - i); - OceanRenderer.Instance._lodDataAnimWaves.BindResultData(mat); + ocean._lodDataAnimWaves.BindResultData(mat); - if (OceanRenderer.Instance._lodDataSeaDepths != null) + if (ocean._lodDataSeaDepths != null) { - OceanRenderer.Instance._lodDataSeaDepths.BindResultData(mat, false); + ocean._lodDataSeaDepths.BindResultData(mat, false); } else { @@ -489,7 +489,7 @@ void UpdateBatch(int lodIdx, int firstComponent, int lastComponentNonInc, Gerstn batch.HasWaves = true; } - void UpdateBatch(GerstnerBatch batch, int batchIdx) + void UpdateBatch(OceanRenderer ocean, GerstnerBatch batch, int batchIdx) { #if UNITY_EDITOR if (_spectrum == null) return; @@ -498,24 +498,24 @@ void UpdateBatch(GerstnerBatch batch, int batchIdx) // Default to disabling all batches batch.HasWaves = false; - if (OceanRenderer.Instance == null) + if (ocean == null) { return; } - UpdateData(); + UpdateData(ocean); if (_wavelengths.Length == 0) { return; } - int lodIdx = Mathf.Min(batchIdx, OceanRenderer.Instance.CurrentLodCount - 1); + int lodIdx = Mathf.Min(batchIdx, ocean.CurrentLodCount - 1); int componentIdx = 0; // seek forward to first wavelength that is big enough to render into current LODs - float minWl = OceanRenderer.Instance._lodTransform.MaxWavelength(batchIdx) / 2f; + float minWl = ocean._lodTransform.MaxWavelength(batchIdx) / 2f; while (componentIdx < _wavelengths.Length && _wavelengths[componentIdx] < minWl) { componentIdx++; @@ -532,7 +532,7 @@ void UpdateBatch(GerstnerBatch batch, int batchIdx) if (componentIdx > startCompIdx) { //Debug.Log($"Batch {batch}, lodIdx {lodIdx}, range: {minWl} -> {2f * minWl}, indices: {startCompIdx} -> {componentIdx}"); - UpdateBatch(lodIdx, startCompIdx, componentIdx, batch); + UpdateBatch(ocean, lodIdx, startCompIdx, componentIdx, batch); } } @@ -589,7 +589,8 @@ public bool GetSurfaceVelocity(ref Vector3 i_worldPos, float i_minSpatialLength, if (_amplitudes == null) return false; Vector2 pos = new Vector2(i_worldPos.x, i_worldPos.z); - float mytime = OceanRenderer.Instance.CurrentTime; + // TODO - whats the solve here? + float mytime = OceanRenderer.AnyInstance.CurrentTime; float windAngle = _windDirectionAngle; float minWaveLength = i_minSpatialLength / 2f; @@ -623,7 +624,8 @@ public bool SampleHeight(ref Vector3 i_worldPos, float i_minSpatialLength, out f o_height = 0f; Vector3 posFlatland = i_worldPos; - posFlatland.y = OceanRenderer.Instance.Root.position.y; + // todo + posFlatland.y = OceanRenderer.AnyInstance.Root.position.y; Vector3 undisplacedPos; if (!ComputeUndisplacedPosition(ref posFlatland, i_minSpatialLength, out undisplacedPos)) @@ -655,7 +657,8 @@ public bool ComputeUndisplacedPosition(ref Vector3 i_worldPos, float i_minSpatia } o_undisplacedWorldPos = guess; - o_undisplacedWorldPos.y = OceanRenderer.Instance.SeaLevel; + // todo + o_undisplacedWorldPos.y = OceanRenderer.AnyInstance.SeaLevel; return true; } @@ -668,7 +671,8 @@ public bool SampleNormal(ref Vector3 i_undisplacedWorldPos, float i_minSpatialLe if (_amplitudes == null) return false; var pos = new Vector2(i_undisplacedWorldPos.x, i_undisplacedWorldPos.z); - float mytime = OceanRenderer.Instance.CurrentTime; + // todo + float mytime = OceanRenderer.AnyInstance.CurrentTime; float windAngle = _windDirectionAngle; float minWaveLength = i_minSpatialLength / 2f; @@ -714,7 +718,8 @@ public bool SampleDisplacement(ref Vector3 i_worldPos, float i_minSpatialLength, } Vector2 pos = new Vector2(i_worldPos.x, i_worldPos.z); - float mytime = OceanRenderer.Instance.CurrentTime; + // todo + float mytime = OceanRenderer.AnyInstance.CurrentTime; float windAngle = _windDirectionAngle; float minWavelength = i_minSpatialLength / 2f; diff --git a/crest/Assets/Crest/Crest/Scripts/WaterBody.cs b/crest/Assets/Crest/Crest/Scripts/WaterBody.cs index c7bb7551e..373a43aa0 100644 --- a/crest/Assets/Crest/Crest/Scripts/WaterBody.cs +++ b/crest/Assets/Crest/Crest/Scripts/WaterBody.cs @@ -56,7 +56,7 @@ private void Start() { if (EditorApplication.isPlaying && _runValidationOnStart) { - Validate(OceanRenderer.Instance, ValidatedHelper.DebugLog); + Validate(OceanRenderer.AnyInstance, ValidatedHelper.DebugLog); } } @@ -68,9 +68,9 @@ private void OnDrawGizmosSelected() var oldColor = Gizmos.color; Gizmos.color = new Color(1f, 1f, 1f, 0.5f); var center = AABB.center; - if (OceanRenderer.Instance != null && OceanRenderer.Instance.Root != null) + if (OceanRenderer.AnyInstance != null && OceanRenderer.AnyInstance.Root != null) { - center.y = OceanRenderer.Instance.Root.position.y; + center.y = OceanRenderer.AnyInstance.Root.position.y; } Gizmos.DrawCube(center, 2f * new Vector3(AABB.extents.x, 1f, AABB.extents.z)); Gizmos.color = oldColor; From 68b60bf54965b4f44f4d53295b0fbb31953059fe Mon Sep 17 00:00:00 2001 From: Dale Eidd Date: Thu, 13 May 2021 11:50:24 -0700 Subject: [PATCH 2/4] Connect underwater effect with ocean --- .../Crest/Scripts/Helpers/UnderwaterEffect.cs | 7 +++++-- crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs b/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs index 0b01297f9..97836160b 100644 --- a/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs +++ b/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs @@ -44,6 +44,8 @@ public partial class UnderwaterEffect : MonoBehaviour PropertyWrapperMPB _mpb; Renderer _rend; + [SerializeField] Camera _camera; + readonly int sp_HeightOffset = Shader.PropertyToID("_HeightOffset"); SampleHeightHelper _sampleWaterHeight = new SampleHeightHelper(); @@ -59,12 +61,13 @@ private void Start() #endif _rend = GetComponent(); + _camera = transform.parent.gameObject.GetComponent(); + // Render before the surface mesh _rend.sortingOrder = _overrideSortingOrder ? _overridenSortingOrder : -LodDataMgr.MAX_LOD_COUNT - 1; GetComponent().sharedMesh = Mesh2DGrid(0, 2, -0.5f, -0.5f, 1f, 1f, GEOM_HORIZ_DIVISIONS, 1); - // TODO - how to connect camera/underwater effect with ocean? - _ocean = OceanRenderer.AnyInstance; + _ocean = OceanRenderer.GetInstance(_camera); #if UNITY_EDITOR if (EditorApplication.isPlaying && !Validate(_ocean, ValidatedHelper.DebugLog)) diff --git a/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs b/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs index 238268062..3991ec8e8 100644 --- a/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs +++ b/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs @@ -288,6 +288,21 @@ public static OceanRenderer ClosestInstance(Vector3 position) return result; } + public static OceanRenderer GetInstance(Camera camera) + { + if (_instances.Count == 0) return null; + + for (int i = 0; i < _instances.Count; i++) + { + if (_instances[i].Viewpoint == camera.transform) + { + return _instances[i]; + } + } + + return null; + } + static List _instances = new List(); // We are computing these values to be optimal based on the base mesh vertex density. From 69f441e51916f4ddaefd968c73830a91ae490aa8 Mon Sep 17 00:00:00 2001 From: Dale Eidd Date: Thu, 13 May 2021 11:54:49 -0700 Subject: [PATCH 3/4] Remove multiple ocean instance validation --- crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs b/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs index 3991ec8e8..3eba58f00 100644 --- a/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs +++ b/crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs @@ -1099,16 +1099,6 @@ public bool Validate(OceanRenderer ocean, ValidatedHelper.ShowMessage showMessag isValid = false; } - // OceanRenderer - if (FindObjectsOfType().Length > 1) - { - showMessage - ( - "Multiple OceanRenderer scripts detected in open scenes, this is not typical - usually only one OceanRenderer is expected to be present.", - ValidatedHelper.MessageType.Warning, ocean - ); - } - // ShapeGerstnerBatched var gerstners = FindObjectsOfType(); if (gerstners.Length == 0) From eca9f891661f5546d38319e7178a722a5ab26350 Mon Sep 17 00:00:00 2001 From: Dale Eidd Date: Thu, 13 May 2021 16:59:50 -0700 Subject: [PATCH 4/4] Don't serialise camera Validation already enforces a camera as a parent. --- crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs b/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs index 97836160b..00e2ba731 100644 --- a/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs +++ b/crest/Assets/Crest/Crest/Scripts/Helpers/UnderwaterEffect.cs @@ -43,8 +43,7 @@ public partial class UnderwaterEffect : MonoBehaviour OceanRenderer _ocean; PropertyWrapperMPB _mpb; Renderer _rend; - - [SerializeField] Camera _camera; + Camera _camera; readonly int sp_HeightOffset = Shader.PropertyToID("_HeightOffset"); @@ -61,7 +60,7 @@ private void Start() #endif _rend = GetComponent(); - _camera = transform.parent.gameObject.GetComponent(); + _camera = GetComponentInParent(); // Render before the surface mesh _rend.sortingOrder = _overrideSortingOrder ? _overridenSortingOrder : -LodDataMgr.MAX_LOD_COUNT - 1;