Exemple #1
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;
        }
        private void LateUpdate()
        {
            // find which lod this object is overlapping
            var rect = new Rect(transform.position.x, transform.position.z, 0f, 0f);
            var idx  = LodDataMgrAnimWaves.SuggestDataLOD(rect);

            if (idx > -1)
            {
                if (_mpb == null)
                {
                    _mpb = new MaterialPropertyBlock();
                }

                _rend.GetPropertyBlock(_mpb);

                var lodCount = OceanRenderer.Instance.CurrentLodCount;
                var ldaw     = OceanRenderer.Instance._lodDataAnimWaves;
                ldaw.BindResultData(idx, 0, _mpb);
                int idx1 = Mathf.Min(idx + 1, lodCount - 1);
                ldaw.BindResultData(idx1, 1, _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 = idx == 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 = idx == lodCount - 1 && OceanRenderer.Instance.ScaleCouldDecrease;
                float farNormalsWeight      = needToBlendOutNormals ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 1f;
                _mpb.SetVector("_InstanceData", new Vector4(meshScaleLerp, farNormalsWeight, idx));

                _rend.SetPropertyBlock(_mpb);
            }

            LateUpdateBounds();
        }
        // 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);
        }
        private void LateUpdate()
        {
            if (OceanRenderer.Instance == 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);

            if (lodIdx > -1)
            {
                if (_mpb == null)
                {
                    _mpb = new PropertyWrapperMPB();
                }

                _rend.GetPropertyBlock(_mpb.materialPropertyBlock);
                _mpb.SetInt(LodDataMgr.sp_LD_SliceIndex, lodIdx);
                _rend.SetPropertyBlock(_mpb.materialPropertyBlock);
            }

            LateUpdateBounds();
        }
Exemple #5
0
        protected override void BindInputsAndOutputs(PropertyWrapperComputeStandalone wrapper, ComputeBuffer resultsBuffer)
        {
            LodDataMgrAnimWaves.Bind(wrapper);
            ShaderProcessQueries.SetTexture(_kernelHandle, sp_LD_TexArray_AnimatedWaves, OceanRenderer.Instance._lodDataAnimWaves.DataTexture);
            ShaderProcessQueries.SetBuffer(_kernelHandle, sp_ResultDisplacements, resultsBuffer);

            ShaderProcessQueries.SetBuffer(_kernelHandle, OceanRenderer.sp_cascadeData, OceanRenderer.Instance._bufCascadeDataTgt);
        }
        private void LateUpdate()
        {
            if (OceanRenderer.Instance == null)
            {
                return;
            }

            // Prevents possible conflicts since overlapping doesn't work for every case.
            if (_disableClipSurfaceWhenTooFarFromSurface)
            {
                var position = transform.position;
                _sampleHeightHelper.Init(position, 0f);
                float waterHeight = 0f;

                if (_sampleHeightHelper.Sample(ref waterHeight))
                {
                    position.y = waterHeight;
                    _enabled   = Mathf.Abs(_rend.bounds.ClosestPoint(position).y - waterHeight) < 1;
                }
            }
            else
            {
                _enabled = true;
            }

            // find which lod this object is overlapping
            var rect   = new Rect(transform.position.x, transform.position.z, 0f, 0f);
            var lodIdx = LodDataMgrAnimWaves.SuggestDataLOD(rect);

            if (lodIdx > -1)
            {
                if (_mpb == null)
                {
                    _mpb = new PropertyWrapperMPB();
                }

                _rend.GetPropertyBlock(_mpb.materialPropertyBlock);

                var lodCount         = OceanRenderer.Instance.CurrentLodCount;
                var lodDataAnimWaves = OceanRenderer.Instance._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;

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

                _rend.SetPropertyBlock(_mpb.materialPropertyBlock);
            }
        }
Exemple #7
0
        private void LateUpdate()
        {
#if UNITY_EDITOR
            // We don't run in "prefab scenes", i.e. when editing a prefab. Bail out if prefab scene is detected.
            if (PrefabStageUtility.GetCurrentPrefabStage() != null)
            {
                return;
            }
#endif

            if (OceanRenderer.Instance == null || !ShowEffect())
            {
                _rend.enabled = false;
                return;
            }

            // Pass true in last arg for a crap reason - in edit mode LateUpdate can be called very frequently, and the height sampler mistakenly thinks
            // this is erroneous and complains.
            _sampleWaterHeight.Init(transform.position, 0f, true);
            _sampleWaterHeight.Sample(out var waterHeight);

            float heightOffset = transform.position.y - waterHeight;

            // Disable skirt when camera not close to water. In the first few frames collision may not be avail, in that case no choice
            // but to assume enabled. In the future this could detect if camera is far enough under water, render a simple quad to avoid
            // finding the intersection line.
            _rend.enabled = heightOffset < _maxHeightAboveWater;

            if (_rend.enabled)
            {
                // Only execute when playing to stop CopyPropertiesFromMaterial from corrupting and breaking the material.
                if (!isMeniscus && _copyParamsEachFrame)
                {
                    _rend.material.CopyPropertiesFromMaterial(OceanRenderer.Instance.OceanMaterial);
                }

                // Assign lod0 shape - trivial but bound every frame because lod transform comes from here
                if (_mpb == null)
                {
                    _mpb = new PropertyWrapperMPB();
                }
                _rend.GetPropertyBlock(_mpb.materialPropertyBlock);

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

                LodDataMgrAnimWaves.Bind(_mpb);
                LodDataMgrSeaFloorDepth.Bind(_mpb);
                LodDataMgrShadow.Bind(_mpb);

                _mpb.SetFloat(sp_HeightOffset, heightOffset);

                _rend.SetPropertyBlock(_mpb.materialPropertyBlock);
            }
        }
Exemple #8
0
        private void LateUpdate()
        {
            if (OceanRenderer.Instance == 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);

            if (lodIdx > -1)
            {
                if (_mpb == null)
                {
                    _mpb = new PropertyWrapperMPB();
                }

                _rend.GetPropertyBlock(_mpb.materialPropertyBlock);

                var lodCount         = OceanRenderer.Instance.CurrentLodCount;
                var lodDataAnimWaves = OceanRenderer.Instance._lodDataAnimWaves;
                _mpb.SetInt(LodDataMgr.sp_LD_SliceIndex, lodIdx);
                lodDataAnimWaves.BindResultData(_mpb);
                var lodDataClipSurface = OceanRenderer.Instance._lodDataClipSurface;
                if (lodDataClipSurface != null)
                {
                    lodDataClipSurface.BindResultData(_mpb);
                }
                else
                {
                    LodDataMgrClipSurface.BindNull(_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;

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

                _rend.SetPropertyBlock(_mpb.materialPropertyBlock);
            }

            LateUpdateBounds();
        }
        protected override void SetAdditionalSimParams(IPropertyWrapper simMaterial)
        {
            base.SetAdditionalSimParams(simMaterial);

            simMaterial.SetFloat(sp_FoamFadeRate, Settings._foamFadeRate);
            simMaterial.SetFloat(sp_WaveFoamStrength, Settings._waveFoamStrength);
            simMaterial.SetFloat(sp_WaveFoamCoverage, Settings._waveFoamCoverage);
            simMaterial.SetFloat(sp_ShorelineFoamMaxDepth, Settings._shorelineFoamMaxDepth);
            simMaterial.SetFloat(sp_ShorelineFoamStrength, Settings._shorelineFoamStrength);

            // assign animated waves - to slot 1 current frame data
            LodDataMgrAnimWaves.Bind(simMaterial);

            // assign sea floor depth - to slot 1 current frame data
            LodDataMgrSeaFloorDepth.Bind(simMaterial);

            // assign flow - to slot 1 current frame data
            LodDataMgrFlow.Bind(simMaterial);
        }
        private void LateUpdate()
        {
            if (OceanRenderer.Instance == null || _renderer == null)
            {
                return;
            }

            // Prevents possible conflicts since overlapping doesn't work for every case.
            if (_disableClipSurfaceWhenTooFarFromSurface)
            {
                var position = transform.position;
                _sampleHeightHelper.Init(position, 0f);

                if (_sampleHeightHelper.Sample(out float waterHeight))
                {
                    position.y = waterHeight;
                    _enabled   = Mathf.Abs(_renderer.bounds.ClosestPoint(position).y - waterHeight) < 1;
                }
            }
            else
            {
                _enabled = true;
            }

            // find which lod this object is overlapping
            var rect   = new Rect(transform.position.x, transform.position.z, 0f, 0f);
            var lodIdx = LodDataMgrAnimWaves.SuggestDataLOD(rect);

            if (lodIdx > -1)
            {
                if (_mpb == null)
                {
                    _mpb = new PropertyWrapperMPB();
                }

                _renderer.GetPropertyBlock(_mpb.materialPropertyBlock);

                _mpb.SetInt(LodDataMgr.sp_LD_SliceIndex, lodIdx);
                _mpb.SetInt(sp_DisplacementSamplingIterations, (int)_animatedWavesDisplacementSamplingIterations);

                _renderer.SetPropertyBlock(_mpb.materialPropertyBlock);
            }
        }
Exemple #11
0
        /// <summary>
        /// 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.
        /// </summary>
        void UpdateBatch(int lodIdx, int firstComponent, int lastComponentNonInc, GerstnerBatch batch)
        {
            batch.HasWaves = false;

            int numComponents = lastComponentNonInc - firstComponent;
            int numInBatch    = 0;
            int dropped       = 0;

            float twopi        = 2f * Mathf.PI;
            float one_over_2pi = 1f / twopi;

            // register any nonzero components
            for (int i = 0; i < numComponents; i++)
            {
                float wl = _wavelengths[firstComponent + i];

                // compute amp - contains logic for shifting wave components between last two LODs...
                float amp = _amplitudes[firstComponent + i];

                if (amp >= 0.001f)
                {
                    if (numInBatch < BATCH_SIZE)
                    {
                        int vi = numInBatch / 4;
                        int ei = numInBatch - vi * 4;

                        UpdateBatchScratchData._twoPiOverWavelengthsBatch[vi][ei] = 2f * Mathf.PI / wl;
                        UpdateBatchScratchData._ampsBatch[vi][ei] = amp;

                        float chopScale = _spectrum._chopScales[(firstComponent + i) / _componentsPerOctave];
                        UpdateBatchScratchData._chopAmpsBatch[vi][ei] = -chopScale * _spectrum._chop * amp;

                        float angle = Mathf.Deg2Rad * (_windDirectionAngle + _angleDegs[firstComponent + i]);
                        UpdateBatchScratchData._waveDirXBatch[vi][ei] = Mathf.Cos(angle);
                        UpdateBatchScratchData._waveDirZBatch[vi][ei] = Mathf.Sin(angle);

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

                        numInBatch++;
                    }
                    else
                    {
                        dropped++;
                    }
                }
            }

            if (dropped > 0)
            {
                Debug.LogWarning(string.Format("Gerstner LOD{0}: Batch limit reached, dropped {1} wavelengths. To support bigger batch sizes, see the comment around the BATCH_SIZE declaration.", lodIdx, dropped), this);
                numComponents = BATCH_SIZE;
            }

            if (numInBatch == 0)
            {
                // no waves to draw - abort
                return;
            }

            // if we did not fill the batch, put a terminator signal after the last position
            if (numInBatch < BATCH_SIZE)
            {
                int vi_last = numInBatch / 4;
                int ei_last = numInBatch - vi_last * 4;

                for (int vi = vi_last; vi < BATCH_SIZE / 4; vi++)
                {
                    for (int ei = ei_last; ei < 4; ei++)
                    {
                        UpdateBatchScratchData._twoPiOverWavelengthsBatch[vi][ei] = 1f; // wary of NaNs
                        UpdateBatchScratchData._ampsBatch[vi][ei]     = 0f;
                        UpdateBatchScratchData._waveDirXBatch[vi][ei] = 0f;
                        UpdateBatchScratchData._waveDirZBatch[vi][ei] = 0f;
                        UpdateBatchScratchData._phasesBatch[vi][ei]   = 0f;
                        UpdateBatchScratchData._chopAmpsBatch[vi][ei] = 0f;
                    }

                    ei_last = 0;
                }
            }

            // apply the data to the shape property
            for (int i = 0; i < 2; i++)
            {
                var mat = batch.GetMaterial(i);
                mat.SetVectorArray(sp_TwoPiOverWavelengths, UpdateBatchScratchData._twoPiOverWavelengthsBatch);
                mat.SetVectorArray(sp_Amplitudes, UpdateBatchScratchData._ampsBatch);
                mat.SetVectorArray(sp_WaveDirX, UpdateBatchScratchData._waveDirXBatch);
                mat.SetVectorArray(sp_WaveDirZ, UpdateBatchScratchData._waveDirZBatch);
                mat.SetVectorArray(sp_Phases, UpdateBatchScratchData._phasesBatch);
                mat.SetVectorArray(sp_ChopAmps, UpdateBatchScratchData._chopAmpsBatch);
                mat.SetFloat(sp_NumInBatch, numInBatch);
                mat.SetFloat(LodDataMgrAnimWaves.sp_AttenuationInShallows, OceanRenderer.Instance._lodDataAnimWaves.Settings.AttenuationInShallows);

                int numVecs = (numInBatch + 3) / 4;
                mat.SetInt(sp_NumWaveVecs, numVecs);
                mat.SetInt(LodDataMgr.sp_LD_SliceIndex, lodIdx - i);

                LodDataMgrAnimWaves.Bind(mat);
                LodDataMgrSeaFloorDepth.Bind(mat);

                if (_directTowardsPoint)
                {
                    mat.SetVector(sp_TargetPointData, new Vector4(_pointPositionXZ.x, _pointPositionXZ.y, _pointRadii.x, _pointRadii.y));
                }
            }

            batch.HasWaves = true;
        }
Exemple #12
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 #13
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 #14
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();
            }
        }
        internal static void UpdatePostProcessMaterial(
            RenderTexture source,
            Camera camera,
            PropertyWrapperMaterial underwaterPostProcessMaterialWrapper,
            UnderwaterSphericalHarmonicsData sphericalHarmonicsData,
            bool isMeniscusEnabled,
            bool copyParamsFromOceanMaterial,
            bool debugViewPostProcessMask,
            float horizonSafetyMarginMultiplier,
            float farPlaneMultiplier,
            int dataSliceOffset
            )
        {
            Material underwaterPostProcessMaterial = underwaterPostProcessMaterialWrapper.material;

            if (copyParamsFromOceanMaterial)
            {
                // Measured this at approx 0.05ms on dell laptop
                underwaterPostProcessMaterial.CopyPropertiesFromMaterial(OceanRenderer.Instance.OceanMaterial);
            }

            // Enable/Disable meniscus.
            if (isMeniscusEnabled)
            {
                underwaterPostProcessMaterial.EnableKeyword("CREST_MENISCUS");
            }
            else
            {
                underwaterPostProcessMaterial.DisableKeyword("CREST_MENISCUS");
            }

            // Enabling/disabling keywords each frame don't seem to have large measurable overhead
            if (debugViewPostProcessMask)
            {
                underwaterPostProcessMaterial.EnableKeyword(DEBUG_VIEW_OCEAN_MASK);
            }
            else
            {
                underwaterPostProcessMaterial.DisableKeyword(DEBUG_VIEW_OCEAN_MASK);
            }

            underwaterPostProcessMaterial.SetFloat(LodDataMgr.sp_LD_SliceIndex, 0);
            underwaterPostProcessMaterial.SetVector(sp_InstanceData, new Vector4(OceanRenderer.Instance.ViewerAltitudeLevelAlpha, 0f, 0f, OceanRenderer.Instance.CurrentLodCount));

            LodDataMgrAnimWaves.Bind(underwaterPostProcessMaterialWrapper);
            LodDataMgrSeaFloorDepth.Bind(underwaterPostProcessMaterialWrapper);
            LodDataMgrShadow.Bind(underwaterPostProcessMaterialWrapper);

            float seaLevel = OceanRenderer.Instance.SeaLevel;

            {
                // We only apply the horizon safety margin multiplier to horizon if and only if
                // concrete height of the camera relative to the water and the height of the camera
                // relative to the sea-level are the same. This ensures that in incredibly turbulent
                // water - if in doubt - use the neutral horizon.
                float seaLevelHeightDifference = camera.transform.position.y - seaLevel;
                if (seaLevelHeightDifference >= 0.0f ^ OceanRenderer.Instance.ViewerHeightAboveWater >= 0.0f)
                {
                    horizonSafetyMarginMultiplier = 0.0f;
                }
            }
            {
                underwaterPostProcessMaterial.SetFloat(sp_OceanHeight, seaLevel);
                underwaterPostProcessMaterial.SetInt(sp_DataSliceOffset, dataSliceOffset);

                float maxOceanVerticalDisplacement = OceanRenderer.Instance.MaxVertDisplacement * 0.5f;
                float cameraYPosition = camera.transform.position.y;
                float nearPlaneFrustumWorldHeight;
                {
                    float current = camera.ViewportToWorldPoint(new Vector3(0f, 0f, camera.nearClipPlane)).y;
                    float maxY = current, minY = current;

                    current = camera.ViewportToWorldPoint(new Vector3(0f, 1f, camera.nearClipPlane)).y;
                    maxY    = Mathf.Max(maxY, current);
                    minY    = Mathf.Min(minY, current);

                    current = camera.ViewportToWorldPoint(new Vector3(1f, 0f, camera.nearClipPlane)).y;
                    maxY    = Mathf.Max(maxY, current);
                    minY    = Mathf.Min(minY, current);

                    current = camera.ViewportToWorldPoint(new Vector3(1f, 1f, camera.nearClipPlane)).y;
                    maxY    = Mathf.Max(maxY, current);
                    minY    = Mathf.Min(minY, current);

                    nearPlaneFrustumWorldHeight = maxY - minY;
                }
                // We don't both setting the horizon value if we know we are going to be having to apply the post-processing
                // effect full-screen anyway.
                bool forceFullShader = (cameraYPosition + nearPlaneFrustumWorldHeight + maxOceanVerticalDisplacement) <= seaLevel;
                underwaterPostProcessMaterial.SetFloat(sp_OceanHeight, seaLevel);
                if (forceFullShader)
                {
                    underwaterPostProcessMaterial.EnableKeyword(FULL_SCREEN_EFFECT);
                }
                else
                {
                    underwaterPostProcessMaterial.DisableKeyword(FULL_SCREEN_EFFECT);
                }
            }

            // Have to set these explicitly as the built-in transforms aren't in world-space for the blit function
            if (XRHelpers.IsSinglePass)
            {
                XRHelpers.SetViewProjectionMatrices(camera);

                Matrix4x4 cameraProjectionMatrix = camera.projectionMatrix;

                camera.projectionMatrix = XRHelpers.LeftEyeProjectionMatrix;

                var inverseViewProjectionMatrix = (XRHelpers.LeftEyeProjectionMatrix * camera.worldToCameraMatrix).inverse;
                underwaterPostProcessMaterial.SetMatrix(sp_InvViewProjection, inverseViewProjectionMatrix);

                {
                    GetHorizonPosNormal(camera, Camera.MonoOrStereoscopicEye.Left, seaLevel, horizonSafetyMarginMultiplier, farPlaneMultiplier, out Vector2 pos, out Vector2 normal);
                    underwaterPostProcessMaterial.SetVector(sp_HorizonPosNormal, new Vector4(pos.x, pos.y, normal.x, normal.y));
                }

                camera.projectionMatrix = XRHelpers.RightEyeProjectionMatrix;

                var inverseViewProjectionMatrixRightEye = (XRHelpers.RightEyeProjectionMatrix * camera.worldToCameraMatrix).inverse;
                underwaterPostProcessMaterial.SetMatrix(sp_InvViewProjectionRight, inverseViewProjectionMatrixRightEye);

                {
                    GetHorizonPosNormal(camera, Camera.MonoOrStereoscopicEye.Right, seaLevel, horizonSafetyMarginMultiplier, farPlaneMultiplier, out Vector2 pos, out Vector2 normal);
                    underwaterPostProcessMaterial.SetVector(sp_HorizonPosNormalRight, new Vector4(pos.x, pos.y, normal.x, normal.y));
                }

                // Revert to original matrix. Not sure if we need to do this.
                camera.projectionMatrix = cameraProjectionMatrix;
            }
            else
            {
                if (XRHelpers.IsNewSDKRunning)
                {
                    XRHelpers.SetViewProjectionMatrices(camera);
                }

                var inverseViewProjectionMatrix = (camera.projectionMatrix * camera.worldToCameraMatrix).inverse;
                underwaterPostProcessMaterial.SetMatrix(sp_InvViewProjection, inverseViewProjectionMatrix);

                {
                    GetHorizonPosNormal(camera, Camera.MonoOrStereoscopicEye.Mono, seaLevel, horizonSafetyMarginMultiplier, farPlaneMultiplier, out Vector2 pos, out Vector2 normal);
                    underwaterPostProcessMaterial.SetVector(sp_HorizonPosNormal, new Vector4(pos.x, pos.y, normal.x, normal.y));
                }
            }

            // Not sure why we need to do this - blit should set it...?
            underwaterPostProcessMaterial.SetTexture(sp_MainTex, source);

            // Compute ambient lighting SH
            {
                // We could pass in a renderer which would prime this lookup. However it doesnt make sense to use an existing render
                // at different position, as this would then thrash it and negate the priming functionality. We could create a dummy invis GO
                // with a dummy Renderer which might be enoguh, but this is hacky enough that we'll wait for it to become a problem
                // rather than add a pre-emptive hack.

                UnityEngine.Profiling.Profiler.BeginSample("Underwater sample spherical harmonics");

                LightProbes.GetInterpolatedProbe(OceanRenderer.Instance.ViewCamera.transform.position, null, out SphericalHarmonicsL2 sphericalHarmonicsL2);
                sphericalHarmonicsL2.Evaluate(sphericalHarmonicsData._shDirections, sphericalHarmonicsData._ambientLighting);
                underwaterPostProcessMaterial.SetVector(sp_AmbientLighting, sphericalHarmonicsData._ambientLighting[0]);

                UnityEngine.Profiling.Profiler.EndSample();
            }
        }
Exemple #16
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;
        }
        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;
        }