Exemplo n.º 1
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>
        int UpdateBatch(int lodIdx, int firstComponent, int lastComponentNonInc, IPropertyWrapper property)
        {
            int numComponents = lastComponentNonInc - firstComponent;
            int numInBatch    = 0;
            int dropped       = 0;

            float twopi                           = 2f * Mathf.PI;
            float one_over_2pi                    = 1f / twopi;
            float minWavelengthThisBatch          = OceanRenderer.Instance._lods[lodIdx].MaxWavelength() / 2f;
            float maxWavelengthCurrentlyRendering = OceanRenderer.Instance._lods[OceanRenderer.Instance.CurrentLodCount - 1].MaxWavelength();
            float viewerAltitudeLevelAlpha        = OceanRenderer.Instance.ViewerAltitudeLevelAlpha;

            // 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];
                bool  renderingIntoLastTwoLods = minWavelengthThisBatch * 4.01f > maxWavelengthCurrentlyRendering;
                // no special weighting needed for any lods except the last 2
                if (renderingIntoLastTwoLods)
                {
                    bool renderingIntoLastLod = minWavelengthThisBatch * 2.01f > maxWavelengthCurrentlyRendering;
                    if (renderingIntoLastLod)
                    {
                        // example: fade out the last lod as viewer drops in altitude, so there is no pop when the lod chain shifts in scale
                        amp *= viewerAltitudeLevelAlpha;
                    }
                    else
                    {
                        // rendering to second-to-last lod. nothing required unless we are dealing with large wavelengths, which we want to transition into
                        // this second-to-last lod when the viewer drops in altitude, ready for a seamless transition when the lod chain shifts in scale
                        amp *= (wl < 2f * minWavelengthThisBatch) ? 1f : 1f - viewerAltitudeLevelAlpha;
                    }
                }

                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 * (OceanRenderer.Instance._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(numInBatch);
            }

            // 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
            property.SetVectorArray(sp_TwoPiOverWavelengths, UpdateBatchScratchData._twoPiOverWavelengthsBatch);
            property.SetVectorArray(sp_Amplitudes, UpdateBatchScratchData._ampsBatch);
            property.SetVectorArray(sp_WaveDirX, UpdateBatchScratchData._waveDirXBatch);
            property.SetVectorArray(sp_WaveDirZ, UpdateBatchScratchData._waveDirZBatch);
            property.SetVectorArray(sp_Phases, UpdateBatchScratchData._phasesBatch);
            property.SetVectorArray(sp_ChopAmps, UpdateBatchScratchData._chopAmpsBatch);
            property.SetFloat(sp_NumInBatch, numInBatch);
            property.SetFloat(sp_AttenuationInShallows, OceanRenderer.Instance._simSettingsAnimatedWaves.AttenuationInShallows);

            int numVecs = (numInBatch + 3) / 4;

            property.SetInt(sp_NumWaveVecs, numVecs);
            OceanRenderer.Instance._lodDataAnimWaves.BindResultData(lodIdx, 0, property);

            if (OceanRenderer.Instance._lodDataSeaDepths)
            {
                OceanRenderer.Instance._lodDataSeaDepths.BindResultData(lodIdx, 0, property, false);
            }

            return(numInBatch);
        }