// 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)
        {
            simsActive  = 0;
            simsPresent = 0;

            var thisRect = new Rect(new Vector2(transform.position.x, transform.position.z), Vector3.zero);
            var minLod   = LodDataMgrAnimWaves.SuggestDataLOD(thisRect);

            if (minLod == -1)
            {
                // Outside all lods, nothing to update!
                return(false);
            }

            // 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);

            if (simsPresent == 0)
            {
                return(false);
            }

            // No sims running - abort
            return(simsActive > 0);
        }
Exemple #2
0
        private void CleanUp()
        {
            foreach (var lodData in _lodDatas)
            {
                lodData.OnDisable();
            }
            _lodDatas.Clear();

#if UNITY_EDITOR
            if (!EditorApplication.isPlaying && Root != null)
            {
                DestroyImmediate(Root.gameObject);
            }
            else
#endif
            if (Root != null)
            {
                Destroy(Root.gameObject);
            }

            Root = null;

            _lodTransform       = null;
            _lodDataAnimWaves   = null;
            _lodDataClipSurface = null;
            _lodDataDynWaves    = null;
            _lodDataFlow        = null;
            _lodDataFoam        = null;
            _lodDataSeaDepths   = null;
            _lodDataShadow      = null;
        }
        void CombinePassPingPong(CommandBuffer buf)
        {
            var       lodCount = OceanRenderer.Instance.CurrentLodCount;
            const int shaderPassCombineIntoAux = 0, shaderPassCopyResultBack = 1;

            // combine waves
            for (int lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--)
            {
                // The per-octave wave buffers
                BindWaveBuffer(_combineMaterial[lodIdx], false);

                // Bind this LOD data (displacements). Option to disable the combine pass - very useful debugging feature.
                if (_shapeCombinePass)
                {
                    BindResultData(_combineMaterial[lodIdx]);
                }
                else
                {
                    BindNull(_combineMaterial[lodIdx]);
                }

                // Dynamic waves
                if (OceanRenderer.Instance._lodDataDynWaves)
                {
                    OceanRenderer.Instance._lodDataDynWaves.BindCopySettings(_combineMaterial[lodIdx]);
                    OceanRenderer.Instance._lodDataDynWaves.BindResultData(_combineMaterial[lodIdx]);
                }
                else
                {
                    LodDataMgrDynWaves.BindNull(_combineMaterial[lodIdx]);
                }

                // Flow
                if (OceanRenderer.Instance._lodDataFlow)
                {
                    OceanRenderer.Instance._lodDataFlow.BindResultData(_combineMaterial[lodIdx]);
                }
                else
                {
                    LodDataMgrFlow.BindNull(_combineMaterial[lodIdx]);
                }

                _combineMaterial[lodIdx].SetInt(sp_LD_SliceIndex, lodIdx);

                // Combine this LOD's waves with waves from the LODs above into auxiliary combine buffer
                buf.SetRenderTarget(_combineBuffer);
                buf.DrawProcedural(Matrix4x4.identity, _combineMaterial[lodIdx].material, shaderPassCombineIntoAux, MeshTopology.Triangles, 3);

                // Copy combine buffer back to lod texture array
                buf.SetRenderTarget(_targets, 0, CubemapFace.Unknown, lodIdx);
                _combineMaterial[lodIdx].SetTexture(Shader.PropertyToID("_CombineBuffer"), _combineBuffer);
                buf.DrawProcedural(Matrix4x4.identity, _combineMaterial[lodIdx].material, shaderPassCopyResultBack, MeshTopology.Triangles, 3);
            }
        }
        public override void BuildCommandBuffer(OceanRenderer ocean, CommandBuffer buf)
        {
            base.BuildCommandBuffer(ocean, buf);

            var lodCount = OceanRenderer.Instance.CurrentLodCount;

            // lod-dependent data
            _filterWavelength._lodCount = lodCount;

            for (int lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--)
            {
                buf.SetRenderTarget(_waveBuffers, 0, CubemapFace.Unknown, lodIdx);
                buf.ClearRenderTarget(false, true, Color.black);

                foreach (var gerstner in _gerstnerComponents)
                {
                    gerstner.BuildCommandBuffer(lodIdx, ocean, buf);
                }

                // draw any data with lod preference
                _filterWavelength._lodIdx           = lodIdx;
                _filterWavelength._lodMaxWavelength = OceanRenderer.Instance._lodTransform.MaxWavelength(lodIdx);
                _filterWavelength._lodMinWavelength = _filterWavelength._lodMaxWavelength / 2f;
                SubmitDrawsFiltered(lodIdx, buf, _filterWavelength);
            }

            int combineShaderKernel         = krnl_ShapeCombine;
            int combineShaderKernel_lastLOD = krnl_ShapeCombine_DISABLE_COMBINE;

            {
                bool isFlowOn     = OceanRenderer.Instance._lodDataFlow != null;
                bool isDynWavesOn = OceanRenderer.Instance._lodDataDynWaves != null;
                // set the shader kernels that we will use.
                if (isFlowOn && isDynWavesOn)
                {
                    combineShaderKernel         = krnl_ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON;
                    combineShaderKernel_lastLOD = krnl_ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE;
                }
                else if (isFlowOn)
                {
                    combineShaderKernel         = krnl_ShapeCombine_FLOW_ON;
                    combineShaderKernel_lastLOD = krnl_ShapeCombine_FLOW_ON_DISABLE_COMBINE;
                }
                else if (isDynWavesOn)
                {
                    combineShaderKernel         = krnl_ShapeCombine_DYNAMIC_WAVE_SIM_ON;
                    combineShaderKernel_lastLOD = krnl_ShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE;
                }
            }

            // combine waves
            for (int lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--)
            {
                int selectedShaderKernel;
                if (lodIdx < lodCount - 1 && _shapeCombinePass)
                {
                    selectedShaderKernel = combineShaderKernel;
                }
                else
                {
                    selectedShaderKernel = combineShaderKernel_lastLOD;
                }

                _combineProperties.Initialise(buf, _combineShader, selectedShaderKernel);

                BindWaveBuffer(_combineProperties);
                BindResultData(_combineProperties);

                // dynamic waves
                if (OceanRenderer.Instance._lodDataDynWaves)
                {
                    OceanRenderer.Instance._lodDataDynWaves.BindCopySettings(_combineProperties);
                    OceanRenderer.Instance._lodDataDynWaves.BindResultData(_combineProperties);
                }
                else
                {
                    LodDataMgrDynWaves.BindNull(_combineProperties);
                }

                // flow
                if (OceanRenderer.Instance._lodDataFlow)
                {
                    OceanRenderer.Instance._lodDataFlow.BindResultData(_combineProperties);
                }
                else
                {
                    LodDataMgrFlow.BindNull(_combineProperties);
                }

                // Set the animated waves texture where the results will be combined.
                _combineProperties.SetTexture(
                    sp_LD_TexArray_AnimatedWaves_Compute,
                    DataTexture
                    );

                _combineProperties.SetFloat(OceanRenderer.sp_LD_SliceIndex, lodIdx);
                _combineProperties.DispatchShader();
            }

            // lod-independent data
            for (int lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--)
            {
                buf.SetRenderTarget(_targets, 0, CubemapFace.Unknown, lodIdx);

                // draw any data that did not express a preference for one lod or another
                SubmitDrawsFiltered(lodIdx, buf, _filterNoLodPreference);
            }
        }
Exemple #5
0
        void LateUpdate()
        {
            if (OceanRenderer.Instance == 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);

            if (minLod == -1)
            {
                // outside all lods, nothing to update!
                return;
            }

            // 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);

            // counting non-existent sims is expensive - stop updating if none found
            if (simsPresent == 0)
            {
                enabled = false;
                return;
            }

            // no sims running - abort. don't bother switching off renderer - camera wont be active
            if (simsActive == 0)
            {
                return;
            }

            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)
            {
                vel = Vector3.zero;
            }

            {
                _sampleFlowHelper.Init(transform.position, _boat.ObjectWidth);
                _sampleFlowHelper.Sample(out var surfaceFlow);
                vel -= new Vector3(surfaceFlow.x, 0, surfaceFlow.y);
            }
            vel.y *= _weightUpDownMul;

            var speedKmh = vel.magnitude * 3.6f;

            if (speedKmh > _teleportSpeed)
            {
                // teleport detected
                vel *= 0f;

                if (_warnOnTeleport)
                {
                    Debug.LogWarning("Teleport detected (speed = " + speedKmh.ToString() + "), velocity discarded.", this);
                }
            }
            else if (speedKmh > _maxSpeed)
            {
                // limit speed to max
                vel *= _maxSpeed / speedKmh;

                if (_warnOnSpeedClamp)
                {
                    Debug.LogWarning("Speed (" + speedKmh.ToString() + ") exceeded max limited, clamped.", this);
                }
            }

            var dt     = 1f / ocean._lodDataDynWaves.Settings._simulationFrequency;
            var weight = _boat.InWater ? 1f / simsActive : 0f;

            _renderer.GetPropertyBlock(_mpb);

            _mpb.SetVector("_Velocity", vel);
            _mpb.SetFloat("_SimDeltaTime", dt);

            // Weighting with this value helps keep ripples consistent for different gravity values
            var gravityMul = Mathf.Sqrt(ocean._lodDataDynWaves.Settings._gravityMultiplier / 25f);

            _mpb.SetFloat("_Weight", weight * gravityMul);

            _renderer.SetPropertyBlock(_mpb);

            _posLast = transform.position;
        }
Exemple #6
0
        void CreateDestroySubSystems()
        {
            {
                if (_lodDataAnimWaves == null)
                {
                    _lodDataAnimWaves = new LodDataMgrAnimWaves(this);
                    _lodDatas.Add(_lodDataAnimWaves);
                }
            }

            if (CreateClipSurfaceData)
            {
                if (_lodDataClipSurface == null)
                {
                    _lodDataClipSurface = new LodDataMgrClipSurface(this);
                    _lodDatas.Add(_lodDataClipSurface);
                }
            }
            else
            {
                if (_lodDataClipSurface != null)
                {
                    _lodDataClipSurface.OnDisable();
                    _lodDatas.Remove(_lodDataClipSurface);
                    _lodDataClipSurface = null;
                }
            }

            if (CreateDynamicWaveSim)
            {
                if (_lodDataDynWaves == null)
                {
                    _lodDataDynWaves = new LodDataMgrDynWaves(this);
                    _lodDatas.Add(_lodDataDynWaves);
                }
            }
            else
            {
                if (_lodDataDynWaves != null)
                {
                    _lodDataDynWaves.OnDisable();
                    _lodDatas.Remove(_lodDataDynWaves);
                    _lodDataDynWaves = null;
                }
            }

            if (CreateFlowSim)
            {
                if (_lodDataFlow == null)
                {
                    _lodDataFlow = new LodDataMgrFlow(this);
                    _lodDatas.Add(_lodDataFlow);
                }

                if (FlowProvider != null && !(FlowProvider is QueryFlow))
                {
                    FlowProvider.CleanUp();
                    FlowProvider = null;
                }
            }
            else
            {
                if (_lodDataFlow != null)
                {
                    _lodDataFlow.OnDisable();
                    _lodDatas.Remove(_lodDataFlow);
                    _lodDataFlow = null;
                }

                if (FlowProvider != null && FlowProvider is QueryFlow)
                {
                    FlowProvider.CleanUp();
                    FlowProvider = null;
                }
            }
            if (FlowProvider == null)
            {
                FlowProvider = _lodDataAnimWaves.Settings.CreateFlowProvider(this);
            }

            if (CreateFoamSim)
            {
                if (_lodDataFoam == null)
                {
                    _lodDataFoam = new LodDataMgrFoam(this);
                    _lodDatas.Add(_lodDataFoam);
                }
            }
            else
            {
                if (_lodDataFoam != null)
                {
                    _lodDataFoam.OnDisable();
                    _lodDatas.Remove(_lodDataFoam);
                    _lodDataFoam = null;
                }
            }

            if (CreateSeaFloorDepthData)
            {
                if (_lodDataSeaDepths == null)
                {
                    _lodDataSeaDepths = new LodDataMgrSeaFloorDepth(this);
                    _lodDatas.Add(_lodDataSeaDepths);
                }
            }
            else
            {
                if (_lodDataSeaDepths != null)
                {
                    _lodDataSeaDepths.OnDisable();
                    _lodDatas.Remove(_lodDataSeaDepths);
                    _lodDataSeaDepths = null;
                }
            }

            if (CreateShadowData)
            {
                if (_lodDataShadow == null)
                {
                    _lodDataShadow = new LodDataMgrShadow(this);
                    _lodDatas.Add(_lodDataShadow);
                }
            }
            else
            {
                if (_lodDataShadow != null)
                {
                    _lodDataShadow.OnDisable();
                    _lodDatas.Remove(_lodDataShadow);
                    _lodDataShadow = null;
                }
            }

            // 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();
            }
        }
Exemple #7
0
        void CombinePassCompute(CommandBuffer buf)
        {
            var lodCount = OceanRenderer.Instance.CurrentLodCount;

            int combineShaderKernel         = krnl_ShapeCombine;
            int combineShaderKernel_lastLOD = krnl_ShapeCombine_DISABLE_COMBINE;

            {
                bool isFlowOn     = OceanRenderer.Instance._lodDataFlow != null;
                bool isDynWavesOn = OceanRenderer.Instance._lodDataDynWaves != null;
                // set the shader kernels that we will use.
                if (isFlowOn && isDynWavesOn)
                {
                    combineShaderKernel         = krnl_ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON;
                    combineShaderKernel_lastLOD = krnl_ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE;
                }
                else if (isFlowOn)
                {
                    combineShaderKernel         = krnl_ShapeCombine_FLOW_ON;
                    combineShaderKernel_lastLOD = krnl_ShapeCombine_FLOW_ON_DISABLE_COMBINE;
                }
                else if (isDynWavesOn)
                {
                    combineShaderKernel         = krnl_ShapeCombine_DYNAMIC_WAVE_SIM_ON;
                    combineShaderKernel_lastLOD = krnl_ShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE;
                }
            }

            // combine waves
            for (int lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--)
            {
                int selectedShaderKernel;
                if (lodIdx < lodCount - 1 && _shapeCombinePass)
                {
                    selectedShaderKernel = combineShaderKernel;
                }
                else
                {
                    selectedShaderKernel = combineShaderKernel_lastLOD;
                }

                _combineProperties.Initialise(buf, _combineShader, selectedShaderKernel);

                // The per-octave wave buffers
                BindWaveBuffer(_combineProperties);
                // Bind this LOD data (displacements)
                Bind(_combineProperties);

                // Dynamic waves
                LodDataMgrDynWaves.Bind(_combineProperties);
                if (OceanRenderer.Instance._lodDataDynWaves != null)
                {
                    OceanRenderer.Instance._lodDataDynWaves.BindCopySettings(_combineProperties);
                }

                // Flow
                LodDataMgrFlow.Bind((_combineProperties));

                // Set the animated waves texture where the results will be combined.
                _combineProperties.SetTexture(
                    sp_LD_TexArray_AnimatedWaves_Compute,
                    DataTexture
                    );

                _combineProperties.SetInt(sp_LD_SliceIndex, lodIdx);

                buf.DispatchCompute(_combineShader, selectedShaderKernel,
                                    OceanRenderer.Instance.LodDataResolution / THREAD_GROUP_SIZE_X,
                                    OceanRenderer.Instance.LodDataResolution / THREAD_GROUP_SIZE_Y,
                                    1);
            }
        }
Exemple #8
0
        void LateUpdate()
        {
            // 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);

            if (minLod == -1)
            {
                // outside all lods, nothing to update!
                return;
            }

            // 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);

            // counting non-existent sims is expensive - stop updating if none found
            if (simsPresent == 0)
            {
                enabled = false;
                return;
            }

            // no sims running - abort. don't bother switching off renderer - camera wont be active
            if (simsActive == 0)
            {
                return;
            }

            var disp = _boat.CalculateDisplacementToObject();

            transform.position = transform.parent.TransformPoint(_localOffset) - disp + _velocityPositionOffset * _boat.Velocity;

            var ocean = OceanRenderer.Instance;

            var rnd = 1f + _noiseAmp * (2f * Mathf.PerlinNoise(_noiseFreq * ocean.CurrentTime, 0.5f) - 1f);
            // feed in water velocity
            var vel = (transform.position - _posLast) / ocean.DeltaTimeDynamics;

            if (ocean.DeltaTimeDynamics < 0.0001f)
            {
                vel = Vector3.zero;
            }

            if (QueryFlow.Instance)
            {
                _sampleFlowHelper.Init(transform.position, _boat.ObjectWidth);
                Vector2 surfaceFlow = Vector2.zero;
                _sampleFlowHelper.Sample(ref surfaceFlow);
                vel -= new Vector3(surfaceFlow.x, 0, surfaceFlow.y);
            }
            vel.y *= _weightUpDownMul;

            var speedKmh = vel.magnitude * 3.6f;

            if (speedKmh > _teleportSpeed)
            {
                // teleport detected
                vel *= 0f;

                if (_warnOnTeleport)
                {
                    Debug.LogWarning("Teleport detected (speed = " + speedKmh.ToString() + "), velocity discarded.", this);
                }
            }
            else if (speedKmh > _maxSpeed)
            {
                // limit speed to max
                vel *= _maxSpeed / speedKmh;

                if (_warnOnSpeedClamp)
                {
                    Debug.LogWarning("Speed (" + speedKmh.ToString() + ") exceeded max limited, clamped.", this);
                }
            }

            float dt; int steps;

            ocean._lodDataDynWaves.GetSimSubstepData(ocean.DeltaTimeDynamics, out steps, out dt);
            float weight = _boat.InWater ? _weight / simsActive : 0f;

            _renderer.GetPropertyBlock(_mpb);

            _mpb.SetVector("_Velocity", vel);
            _mpb.SetFloat("_Weight", weight);
            _mpb.SetFloat("_SimDeltaTime", dt);

            _renderer.SetPropertyBlock(_mpb);

            _posLast = transform.position;
        }
Exemple #9
0
        void CreateDestroyLodDatas()
        {
            {
                if (_lodDataAnimWaves == null)
                {
                    _lodDataAnimWaves = new LodDataMgrAnimWaves(this);
                    _lodDatas.Add(_lodDataAnimWaves);
                }
            }

            if (CreateClipSurfaceData)
            {
                if (_lodDataClipSurface == null)
                {
                    _lodDataClipSurface = new LodDataMgrClipSurface(this);
                    _lodDatas.Add(_lodDataClipSurface);
                }
            }
            else
            {
                if (_lodDataClipSurface != null)
                {
                    _lodDataClipSurface.OnDisable();
                    _lodDatas.Remove(_lodDataClipSurface);
                    _lodDataClipSurface = null;
                }
            }

            if (CreateDynamicWaveSim)
            {
                if (_lodDataDynWaves == null)
                {
                    _lodDataDynWaves = new LodDataMgrDynWaves(this);
                    _lodDatas.Add(_lodDataDynWaves);
                }
            }
            else
            {
                if (_lodDataDynWaves != null)
                {
                    _lodDataDynWaves.OnDisable();
                    _lodDatas.Remove(_lodDataDynWaves);
                    _lodDataDynWaves = null;
                }
            }

            if (CreateFlowSim)
            {
                if (_lodDataFlow == null)
                {
                    _lodDataFlow = new LodDataMgrFlow(this);
                    _lodDatas.Add(_lodDataFlow);
                }
            }
            else
            {
                if (_lodDataFlow != null)
                {
                    _lodDataFlow.OnDisable();
                    _lodDatas.Remove(_lodDataFlow);
                    _lodDataFlow = null;
                }
            }

            if (CreateFoamSim)
            {
                if (_lodDataFoam == null)
                {
                    _lodDataFoam = new LodDataMgrFoam(this);
                    _lodDatas.Add(_lodDataFoam);
                }
            }
            else
            {
                if (_lodDataFoam != null)
                {
                    _lodDataFoam.OnDisable();
                    _lodDatas.Remove(_lodDataFoam);
                    _lodDataFoam = null;
                }
            }

            if (CreateSeaFloorDepthData)
            {
                if (_lodDataSeaDepths == null)
                {
                    _lodDataSeaDepths = new LodDataMgrSeaFloorDepth(this);
                    _lodDatas.Add(_lodDataSeaDepths);
                }
            }
            else
            {
                if (_lodDataSeaDepths != null)
                {
                    _lodDataSeaDepths.OnDisable();
                    _lodDatas.Remove(_lodDataSeaDepths);
                    _lodDataSeaDepths = null;
                }
            }

            if (CreateShadowData)
            {
                if (_lodDataShadow == null)
                {
                    _lodDataShadow = new LodDataMgrShadow(this);
                    _lodDatas.Add(_lodDataShadow);
                }
            }
            else
            {
                if (_lodDataShadow != null)
                {
                    _lodDataShadow.OnDisable();
                    _lodDatas.Remove(_lodDataShadow);
                    _lodDataShadow = null;
                }
            }
        }
Exemple #10
0
        public override void BuildCommandBuffer(OceanRenderer ocean, CommandBuffer buf)
        {
            base.BuildCommandBuffer(ocean, buf);

            var lodCount = OceanRenderer.Instance.CurrentLodCount;

            // lod-dependent data
            for (int lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--)
            {
                buf.SetRenderTarget(_waveBuffers[lodIdx]);
                buf.ClearRenderTarget(false, true, Color.black);

                foreach (var gerstner in _gerstnerComponents)
                {
                    gerstner.BuildCommandBuffer(lodIdx, ocean, buf);
                }

                // draw any data with lod preference
                var        lodMaxWavelength = OceanRenderer.Instance._lods[lodIdx].MaxWavelength();
                var        lodMinWavelength = lodMaxWavelength / 2f;
                DrawFilter filter           = (data) =>
                {
                    var drawOctaveWavelength = (data as RegisterAnimWavesInput).OctaveWavelength;
                    return(lodMinWavelength <= drawOctaveWavelength && drawOctaveWavelength < lodMaxWavelength);
                };
                SubmitDrawsFiltered(lodIdx, buf, filter);
            }

            // combine waves
            for (int lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--)
            {
                // this lod data
                BindWaveBuffer(lodIdx, 0, _combineMaterial[lodIdx], false);

                // combine data from next larger lod into this one
                if (lodIdx < lodCount - 1 && _shapeCombinePass)
                {
                    BindResultData(lodIdx + 1, 1, _combineMaterial[lodIdx]);
                }
                else
                {
                    // this binds black texture
                    BindWaveBuffer(lodIdx, 1, _combineMaterial[lodIdx], true);
                }

                // dynamic waves
                if (OceanRenderer.Instance._lodDataDynWaves)
                {
                    OceanRenderer.Instance._lodDataDynWaves.BindCopySettings(_combineMaterial[lodIdx]);
                    OceanRenderer.Instance._lodDataDynWaves.BindResultData(lodIdx, 0, _combineMaterial[lodIdx]);
                }
                else
                {
                    LodDataMgrDynWaves.BindNull(0, _combineMaterial[lodIdx]);
                }

                // flow
                if (OceanRenderer.Instance._lodDataFlow)
                {
                    OceanRenderer.Instance._lodDataFlow.BindResultData(lodIdx, 0, _combineMaterial[lodIdx]);
                }
                else
                {
                    LodDataMgrFlow.BindNull(0, _combineMaterial[lodIdx]);
                }

                buf.Blit(null, DataTexture(lodIdx), _combineMaterial[lodIdx]);
            }

            // lod-independent data
            for (int lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--)
            {
                buf.SetRenderTarget(DataTexture(lodIdx));

                // draw any data that did not express a preference for one lod or another
                DrawFilter filter = (data) =>
                {
                    return((data as RegisterAnimWavesInput).OctaveWavelength == 0f);
                };
                SubmitDrawsFiltered(lodIdx, buf, filter);
            }
        }
        void LateUpdate()
        {
            // 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);

            if (minLod == -1)
            {
                // outside all lods, nothing to update!
                return;
            }

            // 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);

            // counting non-existent sims is expensive - stop updating if none found
            if (simsPresent == 0)
            {
                enabled = false;
                return;
            }

            // no sims running - abort. don't bother switching off renderer - camera wont be active
            if (simsActive == 0)
            {
                return;
            }

            var disp = _boat.CalculateDisplacementToObject();

            transform.position = transform.parent.TransformPoint(_localOffset) - disp + _velocityPositionOffset * _boat.RB.velocity;

            var rnd = 1f + _noiseAmp * (2f * Mathf.PerlinNoise(_noiseFreq * OceanRenderer.Instance.CurrentTime, 0.5f) - 1f);
            // feed in water velocity
            var vel = (transform.position - _posLast) / Time.deltaTime;

            if (OceanRenderer.Instance._simSettingsFlow != null &&
                OceanRenderer.Instance._simSettingsFlow._readbackData &&
                GPUReadbackFlow.Instance)
            {
                var position     = transform.position;
                var samplingArea = new Rect(position.x, position.z, 0f, 0f);
                GPUReadbackFlow.Instance.GetSamplingData(ref samplingArea, _boat.ObjectWidth, _samplingDataFlow);

                Vector2 surfaceFlow;
                GPUReadbackFlow.Instance.SampleFlow(ref position, _samplingDataFlow, out surfaceFlow);

                vel -= new Vector3(surfaceFlow.x, 0, surfaceFlow.y);

                GPUReadbackFlow.Instance.ReturnSamplingData(_samplingDataFlow);
            }
            vel.y *= _weightUpDownMul;

            var speedKmh = vel.magnitude * 3.6f;

            if (speedKmh > _teleportSpeed)
            {
                // teleport detected
                vel *= 0f;

                if (_warnOnTeleport)
                {
                    Debug.LogWarning("Teleport detected (speed = " + speedKmh.ToString() + "), velocity discarded.", this);
                }
            }
            else if (speedKmh > _maxSpeed)
            {
                // limit speed to max
                vel *= _maxSpeed / speedKmh;

                if (_warnOnSpeedClamp)
                {
                    Debug.LogWarning("Speed (" + speedKmh.ToString() + ") exceeded max limited, clamped.", this);
                }
            }

            float dt; int steps;

            OceanRenderer.Instance._lodDataDynWaves.GetSimSubstepData(Time.deltaTime, out steps, out dt);
            float weight = _boat.InWater ? _weight / simsActive : 0f;

            for (int mati = 0; mati < _dynWavesInput.MaterialCount; mati++)
            {
                var mat = _dynWavesInput.GetMaterial(mati);

                mat.SetVector("_Velocity", vel);
                mat.SetFloat("_Weight", weight);
                mat.SetFloat("_SimDeltaTime", dt);
            }

            _posLast = transform.position;
        }
Exemple #12
0
        public override void BuildCommandBuffer(OceanRenderer ocean, CommandBuffer buf)
        {
            base.BuildCommandBuffer(ocean, buf);

            var lodCount = OceanRenderer.Instance.CurrentLodCount;

            // lod-dependent data
            _filterWavelength._lodCount = lodCount;
            for (int lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--)
            {
                buf.SetRenderTarget(_waveBuffers[lodIdx]);
                buf.ClearRenderTarget(false, true, Color.black);

                foreach (var gerstner in _gerstnerComponents)
                {
                    gerstner.BuildCommandBuffer(lodIdx, ocean, buf);
                }

                // draw any data with lod preference
                _filterWavelength._lodIdx           = lodIdx;
                _filterWavelength._lodMaxWavelength = OceanRenderer.Instance._lods[lodIdx].MaxWavelength();
                _filterWavelength._lodMinWavelength = _filterWavelength._lodMaxWavelength / 2f;
                SubmitDrawsFiltered(lodIdx, buf, _filterWavelength);
            }

            // combine waves
            for (int lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--)
            {
                // this lod data
                BindWaveBuffer(lodIdx, 0, _combineProperties[lodIdx], false);

                // combine data from next larger lod into this one
                if (lodIdx < lodCount - 1 && _shapeCombinePass)
                {
                    BindResultData(lodIdx + 1, 1, _combineProperties[lodIdx]);
                }
                else
                {
                    // this binds black texture
                    BindWaveBuffer(lodIdx, 1, _combineProperties[lodIdx], true);
                }

                // dynamic waves
                if (OceanRenderer.Instance._lodDataDynWaves)
                {
                    OceanRenderer.Instance._lodDataDynWaves.BindCopySettings(_combineProperties[lodIdx]);
                    OceanRenderer.Instance._lodDataDynWaves.BindResultData(lodIdx, 0, _combineProperties[lodIdx]);
                }
                else
                {
                    LodDataMgrDynWaves.BindNull(0, _combineProperties[lodIdx]);
                }

                // flow
                if (OceanRenderer.Instance._lodDataFlow)
                {
                    OceanRenderer.Instance._lodDataFlow.BindResultData(lodIdx, 0, _combineProperties[lodIdx]);
                }
                else
                {
                    LodDataMgrFlow.BindNull(0, _combineProperties[lodIdx]);
                }

                buf.SetRenderTarget(DataTexture(lodIdx));
                buf.DrawProcedural(Matrix4x4.identity, _combineMaterial, 0, MeshTopology.Triangles, 3, 1, _combineProperties[lodIdx].materialPropertyBlock);
            }

            // lod-independent data
            for (int lodIdx = lodCount - 1; lodIdx >= 0; lodIdx--)
            {
                buf.SetRenderTarget(DataTexture(lodIdx));

                // draw any data that did not express a preference for one lod or another
                SubmitDrawsFiltered(lodIdx, buf, _filterNoLodPreference);
            }
        }