示例#1
0
        protected override void InitData()
        {
            base.InitData();

            _combineProperties = new PropertyWrapperMaterial[OceanRenderer.Instance.CurrentLodCount];
            for (int i = 0; i < _combineProperties.Length; i++)
            {
                _combineProperties[i] = new PropertyWrapperMaterial(
                    new Material(Shader.Find("Hidden/Crest/Simulation/Combine Animated Wave LODs"))
                    );
            }

            Debug.Assert(SystemInfo.SupportsRenderTextureFormat(TextureFormat), "The graphics device does not support the render texture format " + TextureFormat.ToString());

            int resolution = OceanRenderer.Instance.LodDataResolution;
            var desc       = new RenderTextureDescriptor(resolution, resolution, TextureFormat, 0);

            _waveBuffers = new RenderTexture[OceanRenderer.Instance.CurrentLodCount];
            for (int i = 0; i < _waveBuffers.Length; i++)
            {
                _waveBuffers[i]              = new RenderTexture(desc);
                _waveBuffers[i].wrapMode     = TextureWrapMode.Clamp;
                _waveBuffers[i].antiAliasing = 1;
                _waveBuffers[i].filterMode   = FilterMode.Bilinear;
                _waveBuffers[i].anisoLevel   = 0;
                _waveBuffers[i].useMipMap    = false;
                _waveBuffers[i].name         = "WaveBuffer_" + i + "_1";
            }
        }
        public override void Start()
        {
            base.Start();

            {
                _renderMaterial = new PropertyWrapperMaterial[OceanRenderer.Instance.CurrentLodCount];
                var shader = Shader.Find("Hidden/Crest/Simulation/Update Shadow");
                for (int i = 0; i < _renderMaterial.Length; i++)
                {
                    _renderMaterial[i] = new PropertyWrapperMaterial(shader);
                }
            }

#if UNITY_EDITOR
            if (OceanRenderer.Instance.OceanMaterial != null &&
                OceanRenderer.Instance.OceanMaterial.HasProperty(MATERIAL_KEYWORD_PROPERTY) &&
                !OceanRenderer.Instance.OceanMaterial.IsKeywordEnabled(MATERIAL_KEYWORD))
            {
                Debug.LogWarning(ERROR_MATERIAL_KEYWORD_MISSING + " " + ERROR_MATERIAL_KEYWORD_MISSING_FIX, _ocean);
            }
#endif

            // Enable sample shadows custom pass.
            SampleShadows.Enable();
        }
        protected override void SetAdditionalSimParams(int lodIdx, PropertyWrapperMaterial simMaterial)
        {
            base.SetAdditionalSimParams(lodIdx, simMaterial);

            simMaterial.SetFloat(sp_Damping, Settings._damping);
            simMaterial.SetFloat(sp_Gravity, OceanRenderer.Instance.Gravity);

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

            if (OceanRenderer.Instance._lodDataFlow)
            {
                OceanRenderer.Instance._lodDataFlow.BindResultData(lodIdx, 1, simMaterial);
            }
            else
            {
                LodDataMgrFlow.BindNull(1, simMaterial);
            }
        }
示例#4
0
        void InitMaterials()
        {
            foreach (var child in transform)
            {
                Destroy((child as Transform).gameObject);
            }

            // num octaves plus one, because there is an additional last bucket for large wavelengths
            _materials = new PropertyWrapperMaterial[OceanRenderer.Instance.CurrentLodCount];
            _drawLOD   = new bool[_materials.Length];

            for (int i = 0; i < _materials.Length; i++)
            {
                _materials[i] = new PropertyWrapperMaterial(new Material(_waveShader));
                if (_directTowardsPoint)
                {
                    _materials[i].material.EnableKeyword(DIRECT_TOWARDS_POINT_KEYWORD);
                }
                _drawLOD[i] = false;
            }

            _materialBigWaveTransition = new PropertyWrapperMaterial(new Material(_waveShader));
            if (_directTowardsPoint)
            {
                _materialBigWaveTransition.material.EnableKeyword(DIRECT_TOWARDS_POINT_KEYWORD);
            }
            _drawLODTransitionWaves = false;
        }
示例#5
0
        protected override void InitData()
        {
            base.InitData();

            // Setup the RenderTexture and compute shader for combining
            // different animated wave LODs. As we use a single texture array
            // for all LODs, we employ a compute shader as only they can
            // read and write to the same texture.
            _combineShader    = Resources.Load <ComputeShader>(ShaderName);
            krnl_ShapeCombine = _combineShader.FindKernel("ShapeCombine");
            krnl_ShapeCombine_DISABLE_COMBINE                             = _combineShader.FindKernel("ShapeCombine_DISABLE_COMBINE");
            krnl_ShapeCombine_FLOW_ON                                     = _combineShader.FindKernel("ShapeCombine_FLOW_ON");
            krnl_ShapeCombine_FLOW_ON_DISABLE_COMBINE                     = _combineShader.FindKernel("ShapeCombine_FLOW_ON_DISABLE_COMBINE");
            krnl_ShapeCombine_DYNAMIC_WAVE_SIM_ON                         = _combineShader.FindKernel("ShapeCombine_DYNAMIC_WAVE_SIM_ON");
            krnl_ShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE         = _combineShader.FindKernel("ShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE");
            krnl_ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON                 = _combineShader.FindKernel("ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON");
            krnl_ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE = _combineShader.FindKernel("ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE");
            _combineProperties = new PropertyWrapperCompute();

            int resolution = OceanRenderer.Instance.LodDataResolution;
            var desc       = new RenderTextureDescriptor(resolution, resolution, TextureFormat, 0);

            _waveBuffers = CreateLodDataTextures(desc, "WaveBuffer", false);

            _combineBuffer = CreateCombineBuffer(desc);

            var combineShader = Shader.Find("Hidden/Crest/Simulation/Combine Animated Wave LODs");

            _combineMaterial = new PropertyWrapperMaterial[OceanRenderer.Instance.CurrentLodCount];
            for (int i = 0; i < _combineMaterial.Length; i++)
            {
                var mat = new Material(combineShader);
                _combineMaterial[i] = new PropertyWrapperMaterial(mat);
            }
        }
示例#6
0
        protected override void SetAdditionalSimParams(int lodIdx, PropertyWrapperMaterial 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 Start()
        {
            base.Start();

            {
                _renderMaterial = new PropertyWrapperMaterial[OceanRenderer.Instance.CurrentLodCount];
                var shader = Shader.Find("Hidden/Crest/Simulation/Update Shadow");
                for (int i = 0; i < _renderMaterial.Length; i++)
                {
                    _renderMaterial[i] = new PropertyWrapperMaterial(shader);
                }
            }

            _cameraMain = Camera.main;
            if (_cameraMain == null)
            {
                var viewpoint = OceanRenderer.Instance.Viewpoint;
                _cameraMain = viewpoint != null?viewpoint.GetComponent <Camera>() : null;

                if (_cameraMain == null)
                {
                    Debug.LogError("Could not find main camera, disabling shadow data", this);
                    enabled = false;
                    return;
                }
            }

#if UNITY_EDITOR
            if (!OceanRenderer.Instance.OceanMaterial.IsKeywordEnabled("_SHADOWS_ON"))
            {
                Debug.LogWarning("Shadowing is not enabled on the current ocean material and will not be visible.", this);
            }
#endif
        }
        public void BindSourceData(int lodIdx, int shapeSlot, PropertyWrapperMaterial properties, bool paramsOnly, bool usePrevTransform)
        {
            var rd = usePrevTransform ?
                     OceanRenderer.Instance._lods[lodIdx]._renderDataPrevFrame.Validate(BuildCommandBufferBase._lastUpdateFrame - Time.frameCount, this)
                : OceanRenderer.Instance._lods[lodIdx]._renderData.Validate(0, this);

            BindData(lodIdx, shapeSlot, properties, paramsOnly ? Texture2D.blackTexture : (Texture)_sources[lodIdx], true, ref rd);
        }
 public void Draw(CommandBuffer buf, float weight, int isTransition, int lodIdx)
 {
     if (Enabled && weight > 0f)
     {
         PropertyWrapperMaterial mat = GetMaterial(isTransition);
         mat.SetFloat(RegisterLodDataInputBase.sp_Weight, weight);
         buf.DrawRenderer(_rend, mat.material);
     }
 }
示例#10
0
 public void Draw(CommandBuffer buf, float weight, int isTransition)
 {
     if (Enabled && weight > 0f)
     {
         PropertyWrapperMaterial mat = GetMaterial(isTransition);
         mat.SetFloat(RegisterLodDataInputBase.sp_Weight, weight);
         buf.DrawMesh(RasterMesh(), Matrix4x4.identity, mat.material);
     }
 }
示例#11
0
        public override void Start()
        {
            base.Start();

#if UNITY_2018
            Debug.LogError("Shadowing not enabled on preview versions of URP. Upgrade to 2019 is required.", this);
#endif
            {
                _renderMaterial = new PropertyWrapperMaterial[OceanRenderer.Instance.CurrentLodCount];
                var shader = Shader.Find("Hidden/Crest/Simulation/Update Shadow");
                for (int i = 0; i < _renderMaterial.Length; i++)
                {
                    _renderMaterial[i] = new PropertyWrapperMaterial(shader);
                }
            }

            if (!SampleShadows.Created
#if UNITY_EDITOR
                // Not excited about this but it seems that the SampleShadows may not be immediately created when in edit mode. TODO - detect directly on render
                // pipeline renderer asset?
                && UnityEditor.EditorApplication.isPlaying
#endif
                )
            {
                Debug.LogError("To support shadowing, a Custom renderer must be configured on the pipeline asset, and this custom renderer data must have the Sample Shadows feature added.", GraphicsSettings.renderPipelineAsset);
            }

            _cameraMain = Camera.main;
            if (_cameraMain == null)
            {
                var viewpoint = OceanRenderer.Instance.Viewpoint;
                _cameraMain = viewpoint != null?viewpoint.GetComponent <Camera>() : null;

                if (_cameraMain == null)
                {
                    Debug.LogError("Could not find main camera, disabling shadow data", _ocean);
                    enabled = false;
                    return;
                }
            }

#if UNITY_EDITOR
            if (!OceanRenderer.Instance.OceanMaterial.IsKeywordEnabled("_SHADOWS_ON"))
            {
                Debug.LogWarning("Shadowing is not enabled on the current ocean material and will not be visible.", _ocean);
            }
#endif

            var asset = GraphicsSettings.renderPipelineAsset as UniversalRenderPipelineAsset;
            if (asset && asset.shadowCascadeOption == ShadowCascadesOption.NoCascades)
            {
                Debug.LogError("Crest shadowing requires shadow cascades to be enabled on the pipeline asset.", asset);
                enabled = false;
                return;
            }
        }
示例#12
0
            public void Draw(CommandBuffer buf, float weight, int isTransition, int lodIdx)
            {
                HasWaves = false;
                _gerstner.UpdateBatch(this, _batchIndex);

                if (HasWaves && weight > 0f)
                {
                    PropertyWrapperMaterial mat = GetMaterial(isTransition);
                    mat.SetFloat(RegisterLodDataInputBase.sp_Weight, weight);
                    buf.DrawRenderer(_rend, mat.material);
                }
            }
        void CreateMaterials(int lodCount)
        {
            _renderSimMaterial = new PropertyWrapperMaterial[MAX_SIM_STEPS, lodCount];
            var shader = Shader.Find(ShaderSim);

            for (int stepi = 0; stepi < MAX_SIM_STEPS; stepi++)
            {
                for (int i = 0; i < lodCount; i++)
                {
                    _renderSimMaterial[stepi, i] = new PropertyWrapperMaterial(shader);
                }
            }
        }
示例#14
0
        protected override void InitData()
        {
            base.InitData();

            // Setup the RenderTexture and compute shader for combining
            // different animated wave LODs. As we use a single texture array
            // for all LODs, we employ a compute shader as only they can
            // read and write to the same texture.

            int resolution = OceanRenderer.Instance.LodDataResolution;
            var desc       = new RenderTextureDescriptor(resolution, resolution, CompatibleTextureFormat, 0);

            _waveBuffers = CreateLodDataTextures(desc, "WaveBuffer", false);

            _combineBuffer = CreateCombineBuffer(desc);

            // Combine graphics shader - for 'ping pong' approach (legacy hardware)
            var combineShaderNameGraphics = "Hidden/Crest/Simulation/Combine Animated Wave LODs";
            var combineShaderGraphics     = Shader.Find(combineShaderNameGraphics);

            Debug.Assert(combineShaderGraphics != null,
                         $"Could not load shader {combineShaderNameGraphics}. Try right clicking the Crest folder in the Project view and selecting Reimport, and checking for errors.",
                         OceanRenderer.Instance);
            if (combineShaderGraphics != null)
            {
                _combineMaterial = new PropertyWrapperMaterial[OceanRenderer.Instance.CurrentLodCount];
                for (int i = 0; i < _combineMaterial.Length; i++)
                {
                    var mat = new Material(combineShaderGraphics);
                    _combineMaterial[i] = new PropertyWrapperMaterial(mat);
                }
            }

            // Combine compute shader - modern hardware
            _combineShader = ComputeShaderHelpers.LoadShader(ShaderName);
            if (_combineShader == null)
            {
                enabled = false;
                return;
            }
            krnl_ShapeCombine = _combineShader.FindKernel("ShapeCombine");
            krnl_ShapeCombine_DISABLE_COMBINE                             = _combineShader.FindKernel("ShapeCombine_DISABLE_COMBINE");
            krnl_ShapeCombine_FLOW_ON                                     = _combineShader.FindKernel("ShapeCombine_FLOW_ON");
            krnl_ShapeCombine_FLOW_ON_DISABLE_COMBINE                     = _combineShader.FindKernel("ShapeCombine_FLOW_ON_DISABLE_COMBINE");
            krnl_ShapeCombine_DYNAMIC_WAVE_SIM_ON                         = _combineShader.FindKernel("ShapeCombine_DYNAMIC_WAVE_SIM_ON");
            krnl_ShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE         = _combineShader.FindKernel("ShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE");
            krnl_ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON                 = _combineShader.FindKernel("ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON");
            krnl_ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE = _combineShader.FindKernel("ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE");
            _combineProperties = new PropertyWrapperCompute();
        }
示例#15
0
            public GerstnerBatch(Shader gerstnerShader, bool directTowardsPoint)
            {
                _materials = new PropertyWrapperMaterial[]
                {
                    new PropertyWrapperMaterial(new Material(gerstnerShader)),
                    new PropertyWrapperMaterial(new Material(gerstnerShader))
                };

                if (directTowardsPoint)
                {
                    _materials[0].material.EnableKeyword(DIRECT_TOWARDS_POINT_KEYWORD);
                    _materials[1].material.EnableKeyword(DIRECT_TOWARDS_POINT_KEYWORD);
                }
            }
示例#16
0
        void SetupUnderwaterEffect()
        {
            if (_underwaterEffectMaterial?.material == null)
            {
                _underwaterEffectMaterial = new PropertyWrapperMaterial(SHADER_UNDERWATER_EFFECT);
            }

            if (_underwaterEffectCommandBuffer == null)
            {
                _underwaterEffectCommandBuffer = new CommandBuffer()
                {
                    name = "Underwater Pass",
                };
            }
        }
示例#17
0
        void SetupOceanMask()
        {
            if (_oceanMaskMaterial?.material == null)
            {
                _oceanMaskMaterial = new PropertyWrapperMaterial(SHADER_OCEAN_MASK);
            }

            if (_oceanMaskCommandBuffer == null)
            {
                _oceanMaskCommandBuffer = new CommandBuffer()
                {
                    name = "Ocean Mask",
                };
            }
        }
            public GerstnerBatch(MeshRenderer rend, bool directTowardsPoint)
            {
                _materials = new PropertyWrapperMaterial[]
                {
                    new PropertyWrapperMaterial(new Material(rend.sharedMaterial ?? rend.material)),
                    new PropertyWrapperMaterial(new Material(rend.sharedMaterial ?? rend.material))
                };

                if (directTowardsPoint)
                {
                    _materials[0].material.EnableKeyword(DIRECT_TOWARDS_POINT_KEYWORD);
                    _materials[1].material.EnableKeyword(DIRECT_TOWARDS_POINT_KEYWORD);
                }

                _rend = rend;
            }
示例#19
0
        public override void Start()
        {
            base.Start();

            {
                _renderMaterial = new PropertyWrapperMaterial[OceanRenderer.Instance.CurrentLodCount];
                var shader = Shader.Find("Hidden/Crest/Simulation/Update Shadow");
                for (int i = 0; i < _renderMaterial.Length; i++)
                {
                    _renderMaterial[i] = new PropertyWrapperMaterial(shader);
                }
            }

            // Enable sample shadows custom pass.
            SampleShadows.Enable();
        }
示例#20
0
        protected override void Start()
        {
            base.Start();

#if UNITY_2018
            Debug.LogError("Shadowing not enabled on preview versions of LWRP. Upgrade to 2019 is required.", this);
#endif
            {
                _renderMaterial = new PropertyWrapperMaterial[OceanRenderer.Instance.CurrentLodCount];
                var shader = Shader.Find("Hidden/Crest/Simulation/Update Shadow");
                for (int i = 0; i < _renderMaterial.Length; i++)
                {
                    _renderMaterial[i] = new PropertyWrapperMaterial(shader);
                }
            }

            if (!SampleShadows.Created)
            {
                Debug.LogError("To support shadowing, a Custom renderer must be configured on the pipeline asset, and this custom renderer data must have the Sample Shadows feature added.", GraphicsSettings.renderPipelineAsset);
            }

            _cameraMain = Camera.main;
            if (_cameraMain == null)
            {
                var viewpoint = OceanRenderer.Instance.Viewpoint;
                _cameraMain = viewpoint != null?viewpoint.GetComponent <Camera>() : null;

                if (_cameraMain == null)
                {
                    Debug.LogError("Could not find main camera, disabling shadow data", this);
                    enabled = false;
                    return;
                }
            }

#if UNITY_EDITOR
            if (!OceanRenderer.Instance.OceanMaterial.IsKeywordEnabled("_SHADOWS_ON"))
            {
                Debug.LogWarning("Shadowing is not enabled on the current ocean material and will not be visible.", this);
            }
#endif
        }
示例#21
0
            public GerstnerBatch(ShapeGerstnerBatched gerstner, int batchIndex, MeshRenderer rend, bool directTowardsPoint)
            {
                _gerstner   = gerstner;
                _batchIndex = batchIndex;

                _materials = new PropertyWrapperMaterial[]
                {
                    new PropertyWrapperMaterial(new Material(rend.sharedMaterial ?? rend.material)),
                    new PropertyWrapperMaterial(new Material(rend.sharedMaterial ?? rend.material))
                };

                if (directTowardsPoint)
                {
                    _materials[0].material.EnableKeyword(DIRECT_TOWARDS_POINT_KEYWORD);
                    _materials[1].material.EnableKeyword(DIRECT_TOWARDS_POINT_KEYWORD);
                }

                _rend = rend;

                Enabled = true;
            }
示例#22
0
            public GerstnerBatch(ShapeGerstnerBatched gerstner, int batchIndex, MeshRenderer rend, bool directTowardsPoint)
            {
                _gerstner   = gerstner;
                _batchIndex = batchIndex;

                _materials = new PropertyWrapperMaterial[]
                {
                    new PropertyWrapperMaterial(new Material(rend.sharedMaterial ?? rend.material)),
                    new PropertyWrapperMaterial(new Material(rend.sharedMaterial ?? rend.material))
                };

                if (directTowardsPoint)
                {
                    _materials[0].material.EnableKeyword(DIRECT_TOWARDS_POINT_KEYWORD);
                    _materials[1].material.EnableKeyword(DIRECT_TOWARDS_POINT_KEYWORD);
                }

                _rend = rend;

                // Enabled stays true, because we don't sort the waves into buckets until Draw time, so we don't know if something should
                // be drawn in advance.
                Enabled = true;
            }
        private void LateUpdate()
        {
            // find which lod this object is overlapping
            var rect = new Rect(transform.position.x, transform.position.z, 0f, 0f);
            var idx  = WaveDataCam.SuggestCollisionLOD(rect);

            if (idx > -1)
            {
                var pwm  = new PropertyWrapperMaterial(_mat);
                var wdcs = OceanRenderer.Instance.Builder._shapeWDCs;
                wdcs[idx].ApplyMaterialParams(0, pwm);
                int idx1 = Mathf.Min(idx + 1, wdcs.Length - 1);
                wdcs[idx1].ApplyMaterialParams(1, pwm);

                // 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 == wdcs.Length - 1 && OceanRenderer.Instance.ScaleCouldDecrease;
                float farNormalsWeight      = needToBlendOutNormals ? OceanRenderer.Instance.ViewerAltitudeLevelAlpha : 1f;
                pwm.SetVector("_InstanceData", new Vector4(meshScaleLerp, farNormalsWeight, idx));
            }
        }
 /// <summary>
 /// Set any sim-specific shader params.
 /// </summary>
 protected virtual void SetAdditionalSimParams(int lodIdx, PropertyWrapperMaterial simMaterial)
 {
 }
        public void BindSourceData(int lodIdx, int slot, PropertyWrapperMaterial simMaterial, bool paramsOnly)
        {
            var rd = OceanRenderer.Instance._lods[lodIdx]._renderDataPrevFrame.Validate(BuildCommandBufferBase._lastUpdateFrame - Time.frameCount, this);

            BindData(lodIdx, slot, simMaterial, paramsOnly ? Texture2D.blackTexture : (_sources[lodIdx] as Texture), true, ref rd);
        }
        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();
            }
        }
 public void BindCopySettings(PropertyWrapperMaterial target)
 {
     target.SetFloat(sp_HorizDisplace, Settings._horizDisplace);
     target.SetFloat(sp_DisplaceClamp, Settings._displaceClamp);
 }