Пример #1
0
        protected virtual void BindData(IPropertyWrapper properties, Texture applyData, bool blendOut, ref LodTransform.RenderData[] renderData, bool sourceLod = false)
        {
            if (applyData)
            {
                properties.SetTexture(GetParamIdSampler(sourceLod), applyData);
            }

            var lt = OceanRenderer.Instance._lodTransform;

            for (int lodIdx = 0; lodIdx < OceanRenderer.Instance.CurrentLodCount; lodIdx++)
            {
                // NOTE: gets zeroed by unity, see https://www.alanzucconi.com/2016/10/24/arrays-shaders-unity-5-4/
                _BindData_paramIdPosScales[lodIdx] = new Vector4(
                    renderData[lodIdx]._posSnapped.x, renderData[lodIdx]._posSnapped.z,
                    OceanRenderer.Instance.CalcLodScale(lodIdx), 0f);
                _BindData_paramIdOceans[lodIdx] = new Vector4(renderData[lodIdx]._texelWidth, renderData[lodIdx]._textureRes, 1f, 1f / renderData[lodIdx]._textureRes);
            }

            // Duplicate the last element as the shader accesses element {slice index + 1] in a few situations. This way going
            // off the end of this parameter is the same as going off the end of the texture array with our clamped sampler.
            _BindData_paramIdPosScales[OceanRenderer.Instance.CurrentLodCount] = _BindData_paramIdPosScales[OceanRenderer.Instance.CurrentLodCount - 1];
            _BindData_paramIdOceans[OceanRenderer.Instance.CurrentLodCount]    = _BindData_paramIdOceans[OceanRenderer.Instance.CurrentLodCount - 1];

            properties.SetVectorArray(LodTransform.ParamIdPosScale(sourceLod), _BindData_paramIdPosScales);
            properties.SetVectorArray(LodTransform.ParamIdOcean(sourceLod), _BindData_paramIdOceans);
        }
Пример #2
0
        protected virtual void BindData(IPropertyWrapper properties, Texture applyData, bool blendOut, ref LodTransform.RenderData[] renderData, bool sourceLod = false)
        {
            if (applyData)
            {
                properties.SetTexture(GetParamIdSampler(sourceLod), applyData);
            }

            var lt = OceanRenderer.Instance._lodTransform;

            for (int lodIdx = 0; lodIdx < OceanRenderer.Instance.CurrentLodCount; lodIdx++)
            {
                // NOTE: gets zeroed by unity, see https://www.alanzucconi.com/2016/10/24/arrays-shaders-unity-5-4/
                _BindData_paramIdPosScales[lodIdx] = new Vector4(renderData[lodIdx]._posSnapped.x, renderData[lodIdx]._posSnapped.z, lt.GetLodTransform(lodIdx).lossyScale.x, 0);
                _BindData_paramIdOceans[lodIdx]    = new Vector4(renderData[lodIdx]._texelWidth, renderData[lodIdx]._textureRes, 1f, 1f / renderData[lodIdx]._textureRes);
            }
            properties.SetVectorArray(LodTransform.ParamIdPosScale(sourceLod), _BindData_paramIdPosScales);
            properties.SetVectorArray(LodTransform.ParamIdOcean(sourceLod), _BindData_paramIdOceans);
        }
        protected override void BindData(IPropertyWrapper properties, Texture applyData, bool blendOut, ref LodTransform.RenderData[] renderData, bool sourceLod = false)
        {
            base.BindData(properties, applyData, blendOut, ref renderData, sourceLod);

            var lt = OceanRenderer.Instance._lodTransform;

            for (int lodIdx = 0; lodIdx < OceanRenderer.Instance.CurrentLodCount; lodIdx++)
            {
                // need to blend out shape if this is the largest lod, and the ocean might get scaled down later (so the largest lod will disappear)
                bool  needToBlendOutShape = lodIdx == OceanRenderer.Instance.CurrentLodCount - 1 && OceanRenderer.Instance.ScaleCouldDecrease && blendOut;
                float shapeWeight         = needToBlendOutShape ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 1f;
                _BindData_paramIdOceans[lodIdx] = new Vector4(
                    lt._renderData[lodIdx]._texelWidth,
                    lt._renderData[lodIdx]._textureRes, shapeWeight,
                    1f / lt._renderData[lodIdx]._textureRes);
            }
            properties.SetVectorArray(LodTransform.ParamIdOcean(sourceLod), _BindData_paramIdOceans);
        }
Пример #4
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);
        }