Esempio n. 1
0
        protected override void SetAdditionalSimParams(IPropertyWrapper simMaterial)
        {
            base.SetAdditionalSimParams(simMaterial);

            simMaterial.SetFloat(sp_Damping, Settings._damping);
            simMaterial.SetFloat(sp_Gravity, OceanRenderer.Instance.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)
            {
                OceanRenderer.Instance._lodDataSeaDepths.BindResultData(simMaterial);
            }
            else
            {
                LodDataMgrSeaFloorDepth.BindNull(simMaterial);
            }

            if (OceanRenderer.Instance._lodDataFlow != null)
            {
                OceanRenderer.Instance._lodDataFlow.BindResultData(simMaterial);
            }
            else
            {
                LodDataMgrFlow.BindNull(simMaterial);
            }
        }
        protected override void SetAdditionalSimParams(int lodIdx, IPropertyWrapper simMaterial)
        {
            base.SetAdditionalSimParams(lodIdx, 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
            OceanRenderer.Instance._lodDataAnimWaves.BindResultData(lodIdx, 1, simMaterial);

            // assign sea floor depth - to slot 1 current frame data
            if (OceanRenderer.Instance._lodDataSeaDepths)
            {
                OceanRenderer.Instance._lodDataSeaDepths.BindResultData(lodIdx, 1, simMaterial);
            }
            else
            {
                LodDataMgrSeaFloorDepth.BindNull(1, simMaterial);
            }

            // assign flow - to slot 1 current frame data
            if (OceanRenderer.Instance._lodDataFlow)
            {
                OceanRenderer.Instance._lodDataFlow.BindResultData(lodIdx, 1, simMaterial);
            }
            else
            {
                LodDataMgrFlow.BindNull(1, simMaterial);
            }
        }
        protected override void SetAdditionalSimParams(int lodIdx, Material simMaterial)
        {
            base.SetAdditionalSimParams(lodIdx, simMaterial);

            simMaterial.SetFloat("_Damping", Settings._damping);
            simMaterial.SetFloat("_Gravity", OceanRenderer.Instance.Gravity);

            float laplacianKernelAngle = _rotateLaplacian ? Mathf.PI * 2f * Random.value : 0f;

            simMaterial.SetVector("_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._createSeaFloorDepthData)
            {
                OceanRenderer.Instance._lodDataSeaDepths.BindResultData(lodIdx, 1, simMaterial);
            }
            else
            {
                LodDataMgrSeaFloorDepth.BindNull(1, simMaterial);
            }

            if (OceanRenderer.Instance._createFlowSim)
            {
                OceanRenderer.Instance._lodDataFlow.BindResultData(lodIdx, 1, simMaterial);
            }
            else
            {
                LodDataMgrFlow.BindNull(1, simMaterial);
            }
        }
Esempio n. 4
0
        private void LateUpdate()
        {
            if (OceanRenderer.Instance == null)
            {
                _rend.enabled = false;
                return;
            }

            float heightOffset = OceanRenderer.Instance.ViewerHeightAboveWater;

            // 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)
            {
                if (_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);
                OceanRenderer.Instance._lodDataAnimWaves.BindResultData(_mpb);

                if (OceanRenderer.Instance._lodDataSeaDepths)
                {
                    OceanRenderer.Instance._lodDataSeaDepths.BindResultData(_mpb);
                }
                else
                {
                    LodDataMgrSeaFloorDepth.BindNull(_mpb);
                }

                if (OceanRenderer.Instance._lodDataShadow)
                {
                    OceanRenderer.Instance._lodDataShadow.BindResultData(_mpb);
                }
                else
                {
                    LodDataMgrShadow.BindNull(_mpb);
                }

                _mpb.SetFloat(sp_HeightOffset, heightOffset);

                _mpb.SetVector(sp_InstanceData, new Vector4(OceanRenderer.Instance.ViewerAltitudeLevelAlpha, 0f, 0f, OceanRenderer.Instance.CurrentLodCount));

                _rend.SetPropertyBlock(_mpb.materialPropertyBlock);
            }
        }
Esempio n. 5
0
        private void LateUpdate()
        {
            if (OceanRenderer.Instance == null)
            {
                _rend.enabled = false;
                return;
            }

            float heightOffset = OceanRenderer.Instance.ViewerHeightAboveWater;


            if (_rend.enabled)
            {
                //if (_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 MaterialPropertyBlock();
                }
                _rend.GetPropertyBlock(_mpb);

                // Underwater rendering uses displacements for intersecting the waves with the near plane, and ocean depth/shadows for ScatterColour()
                OceanRenderer.Instance._lodDataAnimWaves.BindResultData(0, 0, _mpb);

                if (OceanRenderer.Instance._lodDataSeaDepths)
                {
                    OceanRenderer.Instance._lodDataSeaDepths.BindResultData(0, 0, _mpb);
                }
                else
                {
                    LodDataMgrSeaFloorDepth.BindNull(0, _mpb);
                }

                if (OceanRenderer.Instance._lodDataShadow)
                {
                    OceanRenderer.Instance._lodDataShadow.BindResultData(0, 0, _mpb);
                }
                else
                {
                    LodDataMgrShadow.BindNull(0, _mpb);
                }

                _mpb.SetFloat("_HeightOffset", heightOffset);

                _rend.SetPropertyBlock(_mpb);
            }
        }
        private void LateUpdate()
        {
            float heightOffset = OceanRenderer.Instance.ViewerHeightAboveWater;

            // 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)
            {
                if (_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 MaterialPropertyBlock();
                }
                _rend.GetPropertyBlock(_mpb);

                // Underwater rendering uses displacements for intersecting the waves with the near plane, and ocean depth/shadows for ScatterColour()
                OceanRenderer.Instance._lodDataAnimWaves.BindResultData(0, 0, _mpb);

                if (OceanRenderer.Instance._createSeaFloorDepthData)
                {
                    OceanRenderer.Instance._lodDataSeaDepths.BindResultData(0, 0, _mpb);
                }
                else
                {
                    LodDataMgrSeaFloorDepth.BindNull(0, _mpb);
                }

                if (OceanRenderer.Instance._createShadowData)
                {
                    OceanRenderer.Instance._lodDataShadow.BindResultData(0, 0, _mpb);
                }
                else
                {
                    LodDataMgrShadow.BindNull(0, _mpb);
                }

                _mpb.SetFloat("_HeightOffset", heightOffset);

                _rend.SetPropertyBlock(_mpb);
            }
        }
Esempio n. 7
0
        // Called when visible to a camera
        void OnWillRenderObject()
        {
            if (OceanRenderer.Instance == null || Rend == null)
            {
                return;
            }

            // check if built-in pipeline being used
            if (Camera.current != null)
            {
                _currentCamera = Camera.current;
            }

            // 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)
            {
                Rend.sharedMaterial = OceanRenderer.Instance.OceanMaterial;
            }

            // per instance data

            if (_mpb == null)
            {
                _mpb = new PropertyWrapperMPB();
            }
            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;

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

            _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 gridSizeGeo        = scale_pow_2 / (0.25f * _lodDataResolution / _geoDownSampleFactor);
            var gridSizeLodData    = gridSizeGeo / _geoDownSampleFactor;
            var mul                = 1.875f; // fudge 1
            var pow                = 1.4f;   // fudge 2
            var normalScrollSpeed0 = Mathf.Pow(Mathf.Log(1f + 2f * gridSizeLodData) * mul, pow);
            var normalScrollSpeed1 = Mathf.Pow(Mathf.Log(1f + 4f * gridSizeLodData) * mul, pow);

            _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;

            _mpb.SetInt(LodDataMgr.sp_LD_SliceIndex, _lodIndex);
            if (ldaws != null)
            {
                ldaws.BindResultData(_mpb);
            }
            if (ldflow != null)
            {
                ldflow.BindResultData(_mpb);
            }
            else
            {
                LodDataMgrFlow.BindNull(_mpb);
            }
            if (ldfoam != null)
            {
                ldfoam.BindResultData(_mpb);
            }
            else
            {
                LodDataMgrFoam.BindNull(_mpb);
            }
            if (ldsds != null)
            {
                ldsds.BindResultData(_mpb);
            }
            else
            {
                LodDataMgrSeaFloorDepth.BindNull(_mpb);
            }
            if (ldclip != null)
            {
                ldclip.BindResultData(_mpb);
            }
            else
            {
                LodDataMgrClipSurface.BindNull(_mpb);
            }
            if (ldshadows != null)
            {
                ldshadows.BindResultData(_mpb);
            }
            else
            {
                LodDataMgrShadow.BindNull(_mpb);
            }

            var reflTex = PreparedReflections.GetRenderTexture(_currentCamera.GetHashCode());

            if (reflTex)
            {
                _mpb.SetTexture(sp_ReflectionTex, reflTex);
            }
            else
            {
                _mpb.SetTexture(sp_ReflectionTex, Texture2D.blackTexture);
            }

            // Hack - due to SV_IsFrontFace occasionally coming through as true for back faces,
            // 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;

            _mpb.SetFloat(sp_ForceUnderwater, heightOffset < -2f ? 1f : 0f);

            Rend.SetPropertyBlock(_mpb.materialPropertyBlock);
        }
Esempio n. 8
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)
            {
                _rend.enabled = false;
                return;
            }

            float waterHeight = OceanRenderer.Instance.SeaLevel;
            // 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(ref 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)
            {
                if (_copyParamsEachFrame)
                {
                    _rend.sharedMaterial.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);
                OceanRenderer.Instance._lodDataAnimWaves.BindResultData(_mpb);

                if (OceanRenderer.Instance._lodDataSeaDepths != null)
                {
                    OceanRenderer.Instance._lodDataSeaDepths.BindResultData(_mpb);
                }
                else
                {
                    LodDataMgrSeaFloorDepth.BindNull(_mpb);
                }

                if (OceanRenderer.Instance._lodDataShadow != null)
                {
                    OceanRenderer.Instance._lodDataShadow.BindResultData(_mpb);
                }
                else
                {
                    LodDataMgrShadow.BindNull(_mpb);
                }

                _mpb.SetFloat(sp_HeightOffset, heightOffset);

                _mpb.SetVector(OceanChunkRenderer.sp_InstanceData, new Vector3(OceanRenderer.Instance.ViewerAltitudeLevelAlpha, 0f, 0f));

                _rend.SetPropertyBlock(_mpb.materialPropertyBlock);
            }
        }
Esempio n. 9
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(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);
                OceanRenderer.Instance._lodDataAnimWaves.BindResultData(mat);

                if (OceanRenderer.Instance._lodDataSeaDepths != null)
                {
                    OceanRenderer.Instance._lodDataSeaDepths.BindResultData(mat, false);
                }
                else
                {
                    LodDataMgrSeaFloorDepth.BindNull(mat, false);
                }

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

            batch.HasWaves = true;
        }