void InitBatches()
        {
            if (_waveShader == null)
            {
                _waveShader = Shader.Find("Crest/Inputs/Animated Waves/Gerstner Batch");
                Debug.Assert(_waveShader, "Could not load Gerstner wave shader, make sure it is packaged in the build.");
                if (_waveShader == null)
                {
                    return;
                }
            }

            _batches = new GerstnerBatch[LodDataMgr.MAX_LOD_COUNT];
            for (int i = 0; i < _batches.Length; i++)
            {
                _batches[i] = new GerstnerBatch(_waveShader, _directTowardsPoint);
            }

            // Submit draws to create the Gerstner waves. LODs from 0 to N-2 render the Gerstner waves from their lod. Additionally, any waves
            // in the biggest lod, or too big for the biggest lod, are rendered into both of the last two LODs N-1 and N-2, as this allows us to
            // move these waves between LODs without pops when the camera changes heights and the LODs need to change scale.

            var registered = RegisterLodDataInputBase.GetRegistrar(typeof(LodDataMgrAnimWaves));

            foreach (var batch in _batches)
            {
                registered.Add(batch);
            }
        }
示例#2
0
        void UpdateBatch(GerstnerBatch batch, int batchIdx)
        {
#if UNITY_EDITOR
            if (_spectrum == null)
            {
                return;
            }
#endif

            // Default to disabling all batches
            batch.HasWaves = false;

            if (OceanRenderer.Instance == null)
            {
                return;
            }

            UpdateData();

            if (_wavelengths.Length == 0)
            {
                return;
            }

            int lodIdx = Mathf.Min(batchIdx, OceanRenderer.Instance.CurrentLodCount - 1);

            int componentIdx = 0;

            // seek forward to first wavelength that is big enough to render into current LODs
            float minWl = OceanRenderer.Instance._lodTransform.MaxWavelength(batchIdx) / 2f;
            while (componentIdx < _wavelengths.Length && _wavelengths[componentIdx] < minWl)
            {
                componentIdx++;
            }

            // Assemble wavelengths into current batch
            int startCompIdx = componentIdx;
            while (componentIdx < _wavelengths.Length && _wavelengths[componentIdx] < 2f * minWl)
            {
                componentIdx++;
            }

            // One or more wavelengths - update the batch
            if (componentIdx > startCompIdx)
            {
                //Debug.Log($"Batch {batch}, lodIdx {lodIdx}, range: {minWl} -> {2f * minWl}, indices: {startCompIdx} -> {componentIdx}");
                UpdateBatch(lodIdx, startCompIdx, componentIdx, batch);
            }
        }
示例#3
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;
        }
示例#4
0
        void InitBatches()
        {
            // Get the wave
            MeshRenderer rend = GetComponent <MeshRenderer>();

            if (_mode == GerstnerMode.Geometry)
            {
                rend.enabled = false;
#if UNITY_EDITOR
                // Cleanup render proxy used for global mode after switching.
                if (_renderProxy != null)
                {
                    DestroyImmediate(_renderProxy);
                }
#endif
            }
            else if (_mode == GerstnerMode.Global)
            {
                // Create render proxy only if we don't already have one.
                if (_renderProxy == null)
                {
                    // Create a proxy MeshRenderer to feed the rendering
                    _renderProxy = GameObject.CreatePrimitive(PrimitiveType.Quad);
#if UNITY_EDITOR
                    DestroyImmediate(_renderProxy.GetComponent <Collider>());
#else
                    Destroy(_renderProxy.GetComponent <Collider>());
#endif
                    _renderProxy.hideFlags        = HideFlags.HideAndDontSave;
                    _renderProxy.transform.parent = transform;
                    rend         = _renderProxy.GetComponent <MeshRenderer>();
                    rend.enabled = false;
                    var waveShader = Shader.Find("Hidden/Crest/Inputs/Animated Waves/Gerstner Batch Global");
                    Debug.Assert(waveShader, "Could not load Gerstner wave shader, make sure it is packaged in the build.");
                    if (waveShader == null)
                    {
                        enabled = false;
                        return;
                    }

                    rend.material = new Material(waveShader);
                }
                else
                {
                    rend = _renderProxy.GetComponent <MeshRenderer>();
                }
            }

            var registered = RegisterLodDataInputBase.GetRegistrar(typeof(LodDataMgrAnimWaves));

#if UNITY_EDITOR
            // Unregister after switching modes in the editor.
            if (_batches != null)
            {
                foreach (var batch in _batches)
                {
                    registered.Remove(batch);
                }
            }
#endif

            _batches = new GerstnerBatch[LodDataMgr.MAX_LOD_COUNT];
            for (int i = 0; i < _batches.Length; i++)
            {
                _batches[i] = new GerstnerBatch(this, i, rend, _directTowardsPoint);
            }

            // Submit draws to create the Gerstner waves. LODs from 0 to N-2 render the Gerstner waves from their lod. Additionally, any waves
            // in the biggest lod, or too big for the biggest lod, are rendered into both of the last two LODs N-1 and N-2, as this allows us to
            // move these waves between LODs without pops when the camera changes heights and the LODs need to change scale.

            foreach (var batch in _batches)
            {
                registered.Add(0, batch);
            }
        }
        void InitBatches()
        {
            // Get the wave
            MeshRenderer rend = null;

            if (_mode == GerstnerMode.Geometry)
            {
                rend = GetComponent <MeshRenderer>();

                if (!rend)
                {
                    Debug.LogError($"Gerstner input '{gameObject.name}' has Mode set to Geometry, but no MeshRenderer component is attached. Please attach a MeshRenderer to provide the geometry for rendering the Gerstner waves.", this);
                    enabled = false;
                    return;
                }
                if (!rend.sharedMaterial)
                {
                    Debug.LogError($"Gerstner input '{gameObject.name}' has Mode set to Geometry, but the geometry has no material assigned. Please assign a material that uses one of the Gerstner input shaders.", this);
                    enabled = false;
                    return;
                }

                rend.enabled = false;
            }
            else if (_mode == GerstnerMode.Global)
            {
                if (GetComponent <MeshRenderer>() != null)
                {
                    Debug.LogWarning($"Gerstner input '{gameObject.name}' has MeshRenderer component that will be ignored because the Mode is set to Global.", this);
                }

                // Create a proxy MeshRenderer to feed the rendering
                var renderProxy = GameObject.CreatePrimitive(PrimitiveType.Quad);
                Destroy(renderProxy.GetComponent <Collider>());
                renderProxy.hideFlags        = HideFlags.HideAndDontSave;
                renderProxy.transform.parent = transform;
                rend         = renderProxy.GetComponent <MeshRenderer>();
                rend.enabled = false;

                var waveShader = Shader.Find("Hidden/Crest/Inputs/Animated Waves/Gerstner Batch Global");
                Debug.Assert(waveShader, "Could not load Gerstner wave shader, make sure it is packaged in the build.");
                if (waveShader == null)
                {
                    enabled = false;
                    return;
                }

                rend.material = new Material(waveShader);
            }

            _batches = new GerstnerBatch[LodDataMgr.MAX_LOD_COUNT];
            for (int i = 0; i < _batches.Length; i++)
            {
                _batches[i] = new GerstnerBatch(rend, _directTowardsPoint);
            }

            // Submit draws to create the Gerstner waves. LODs from 0 to N-2 render the Gerstner waves from their lod. Additionally, any waves
            // in the biggest lod, or too big for the biggest lod, are rendered into both of the last two LODs N-1 and N-2, as this allows us to
            // move these waves between LODs without pops when the camera changes heights and the LODs need to change scale.

            var registered = RegisterLodDataInputBase.GetRegistrar(typeof(LodDataMgrAnimWaves));

            foreach (var batch in _batches)
            {
                registered.Add(0, batch);
            }
        }