Пример #1
0
        /// <summary>
        /// Called when a compute buffer has been read back from the GPU to the CPU.
        /// </summary>
        void DataArrived(AsyncGPUReadbackRequest req)
        {
            // Can get callbacks after disable, so detect this.
            if (!_queryResults.IsCreated)
            {
                _requests.Clear();
                return;
            }

            // Remove any error requests
            for (int i = _requests.Count - 1; i >= 0; --i)
            {
                if (_requests[i]._request.hasError)
                {
                    _requests.RemoveAt(i);
                    _segmentRegistrarRingBuffer.ReleaseLast();
                }
            }

            // Find the last request that was completed
            var lastDoneIndex = _requests.Count - 1;

            while (lastDoneIndex >= 0 && !_requests[lastDoneIndex]._request.done)
            {
                --lastDoneIndex;
            }

            // If there is a completed request, process it
            if (lastDoneIndex >= 0)
            {
                // Update "last" results
                LodDataMgr.Swap(ref _queryResults, ref _queryResultsLast);
                _queryResultsTimeLast = _queryResultsTime;
                _resultSegmentsLast   = _resultSegments;

                var data = _requests[lastDoneIndex]._request.GetData <Vector3>();
                data.CopyTo(_queryResults);
                _queryResultsTime = _requests[lastDoneIndex]._dataTimestamp;
                _resultSegments   = _requests[lastDoneIndex]._segments;
            }

            // Remove all the requests up to the last completed one
            for (int i = lastDoneIndex; i >= 0; --i)
            {
                _requests.RemoveAt(i);
                _segmentRegistrarRingBuffer.ReleaseLast();
            }
        }
Пример #2
0
        public void PopulateCache()
        {
            if (_type == OceanDepthCacheType.Baked)
            {
                return;
            }

            var layerMask  = 0;
            var errorShown = false;

            foreach (var layer in _layerNames)
            {
                if (string.IsNullOrEmpty(layer))
                {
                    Debug.LogError("OceanDepthCache: An empty layer name was provided. Please provide a valid layer name. Click this message to highlight the cache in question.", this);
                    errorShown = true;
                    continue;
                }

                int layerIdx = LayerMask.NameToLayer(layer);
                if (layerIdx == -1)
                {
                    Debug.LogError("OceanDepthCache: Invalid layer specified: \"" + layer +
                                   "\". Please add this layer to the project by putting the name in an empty layer slot in Edit/Project Settings/Tags and Layers. Click this message to highlight the cache in question.", this);

                    errorShown = true;
                }
                else
                {
                    layerMask = layerMask | (1 << layerIdx);
                }
            }

            if (layerMask == 0)
            {
                if (!errorShown)
                {
                    Debug.LogError("No valid layers for populating depth cache, aborting. Click this message to highlight the cache in question.", this);
                }

                return;
            }

#if UNITY_EDITOR
            if (_type == OceanDepthCacheType.Realtime && _checkTerrainDrawInstancedOption)
            {
                // This issue only affects the built-in render pipeline. Issue 158: https://github.com/crest-ocean/crest/issues/158

                var terrains = FindObjectsOfType <Terrain>();
                foreach (var terrain in terrains)
                {
                    var mask = (int)Mathf.Pow(2f, terrain.gameObject.layer);

                    if ((mask & layerMask) == 0)
                    {
                        continue;
                    }

                    if (terrain.drawInstanced)
                    {
                        Debug.LogError($"Terrain {terrain.gameObject.name} has 'Draw Instanced' enabled. This terrain will not populate into the depth cache and therefore will not contribute to shorelines and shallow water. This option must be disabled on the terrain when the depth cache is populated (but can be enabled afterwards).", terrain);
                    }
                }
            }
#endif

            if (_depthCacheTexture == null)
            {
                RenderTextureFormat fmt;
                if (_generateSDF)
                {
                    fmt = RenderTextureFormat.RGHalf;
                }
                else
                {
#if UNITY_EDITOR_WIN
                    fmt = RenderTextureFormat.DefaultHDR;
#else
                    fmt = RenderTextureFormat.RHalf;
#endif
                }

                Debug.Assert(SystemInfo.SupportsRenderTextureFormat(fmt), "The graphics device does not support the render texture format " + fmt.ToString());
                _depthCacheTexture                   = new RenderTexture(_resolution, _resolution, 0);
                _depthCacheTexture.name              = gameObject.name + "_oceanDepth";
                _depthCacheTexture.format            = fmt;
                _depthCacheTexture.useMipMap         = false;
                _depthCacheTexture.anisoLevel        = 0;
                _depthCacheTexture.enableRandomWrite = _generateSDF;
                _depthCacheTexture.Create();
            }

            if (_depthCacheCamera == null)
            {
                _depthCacheCamera = GenerateCacheCamera(
                    layerMask,
                    _generateSDF ? "DepthSdfCam" : "DepthCacheCam",
                    _cameraMaxTerrainHeight,
                    transform,
                    _depthCacheTexture,
                    _hideDepthCacheCam
                    );
            }


            // Make sure this global is set - I found this was necessary to set it here. However this can cause glitchiness in editor
            // as it messes with this global vector, so only do it if not in edit mode
#if UNITY_EDITOR
            if (EditorApplication.isPlaying)
#endif
            {
                // Shader needs sea level to determine water depth
                var centerPoint = Vector3.zero;
                if (OceanRenderer.Instance != null)
                {
                    centerPoint.y = OceanRenderer.Instance.Root.position.y;
                }
                else
                {
                    centerPoint.y = transform.position.y;
                }

                Shader.SetGlobalVector("_OceanCenterPosWorld", centerPoint);
            }

            _depthCacheCamera.RenderWithShader(Shader.Find("Crest/Inputs/Depth/Ocean Depth From Geometry"), null);

            if (_generateSDF)
            {
                RenderTextureFormat fmt = RenderTextureFormat.RGHalf;
                RenderTexture       voronoiPingPongTexture0 = new RenderTexture(_resolution, _resolution, 0);
                voronoiPingPongTexture0.name              = gameObject.name + "_voronoiPingPong0";
                voronoiPingPongTexture0.format            = fmt;
                voronoiPingPongTexture0.useMipMap         = false;
                voronoiPingPongTexture0.anisoLevel        = 0;
                voronoiPingPongTexture0.enableRandomWrite = true;
                voronoiPingPongTexture0.Create();

                RenderTexture voronoiPingPongTexture1 = new RenderTexture(_resolution, _resolution, 0);
                voronoiPingPongTexture1.name              = gameObject.name + "_voronoiPingPong1";
                voronoiPingPongTexture1.format            = fmt;
                voronoiPingPongTexture1.useMipMap         = false;
                voronoiPingPongTexture1.anisoLevel        = 0;
                voronoiPingPongTexture1.enableRandomWrite = true;
                voronoiPingPongTexture1.Create();

                using (CommandBuffer jumpFloodCommandBuffer = new CommandBuffer())
                {
                    var  cameraToWorldMatrix     = _depthCacheCamera.cameraToWorldMatrix;
                    var  projectionMatrix        = _depthCacheCamera.projectionMatrix;
                    var  projectionToWorldMatrix = cameraToWorldMatrix * projectionMatrix.inverse;
                    uint textureDimension        = (uint)voronoiPingPongTexture0.width;
                    {
                        ComputeShader initJumpFloodShader = ComputeShaderHelpers.LoadShader("SdfInitJumpFlood");
                        int           initJumpFloodKernel = initJumpFloodShader.FindKernel("SdfInitJumpFlood");
                        jumpFloodCommandBuffer.SetComputeTextureParam(initJumpFloodShader, initJumpFloodKernel, sp_FromTexture, _depthCacheTexture);
                        jumpFloodCommandBuffer.SetComputeTextureParam(initJumpFloodShader, initJumpFloodKernel, sp_ToTexture, voronoiPingPongTexture0);
                        jumpFloodCommandBuffer.SetComputeIntParam(initJumpFloodShader, sp_textureDimension, (int)textureDimension);
                        jumpFloodCommandBuffer.SetComputeMatrixParam(initJumpFloodShader, sp_projectionToWorld, projectionToWorldMatrix);
                        jumpFloodCommandBuffer.DispatchCompute(
                            initJumpFloodShader,
                            initJumpFloodKernel,
                            _depthCacheTexture.width / 8,
                            _depthCacheTexture.height / 8,
                            1
                            );
                    }
                    ComputeShader jumpFloodShader = ComputeShaderHelpers.LoadShader("SdfJumpFlood");
                    int           jumpFloodKernel = jumpFloodShader.FindKernel("SdfJumpFlood");

                    ComputeShader sdfGradientShader = ComputeShaderHelpers.LoadShader("SdfApply");
                    int           sdfKernel         = sdfGradientShader.FindKernel("SdfApply");


                    jumpFloodCommandBuffer.name = "Jump Flood";
                    for (uint jumpSize = (uint)textureDimension / 2; jumpSize > 0; jumpSize /= 2)
                    {
                        ApplyJumpFlood(
                            jumpFloodCommandBuffer, jumpFloodShader, jumpFloodKernel,
                            sp_jumpSize, jumpSize,
                            sp_textureDimension, textureDimension,
                            sp_projectionToWorld, projectionToWorldMatrix,
                            sp_FromTexture, voronoiPingPongTexture0,
                            sp_ToTexture, voronoiPingPongTexture1
                            );
                        LodDataMgr.Swap(ref voronoiPingPongTexture1, ref voronoiPingPongTexture0);
                    }

                    for (uint roundNum = 0; roundNum < _additionalJumpFloodRounds; roundNum++)
                    {
                        uint jumpSize = (uint)1 << (int)roundNum;
                        ApplyJumpFlood(
                            jumpFloodCommandBuffer, jumpFloodShader, jumpFloodKernel,
                            sp_jumpSize, jumpSize,
                            sp_textureDimension, textureDimension,
                            sp_projectionToWorld, projectionToWorldMatrix,
                            sp_FromTexture, voronoiPingPongTexture0,
                            sp_ToTexture, voronoiPingPongTexture1
                            );
                        LodDataMgr.Swap(ref voronoiPingPongTexture1, ref voronoiPingPongTexture0);
                    }

                    jumpFloodCommandBuffer.SetComputeTextureParam(sdfGradientShader, sdfKernel, sp_FromTexture, voronoiPingPongTexture0);
                    jumpFloodCommandBuffer.SetComputeTextureParam(sdfGradientShader, sdfKernel, sp_ToTexture, _depthCacheTexture);
                    jumpFloodCommandBuffer.SetComputeIntParam(sdfGradientShader, sp_textureDimension, (int)textureDimension);
                    jumpFloodCommandBuffer.SetComputeMatrixParam(sdfGradientShader, sp_projectionToWorld, projectionToWorldMatrix);
                    jumpFloodCommandBuffer.DispatchCompute(
                        sdfGradientShader,
                        sdfKernel,
                        voronoiPingPongTexture0.width / 8,
                        voronoiPingPongTexture0.height / 8,
                        1
                        );
                    Graphics.ExecuteCommandBuffer(jumpFloodCommandBuffer);
                }
                DrawCacheQuad(ref _drawDepthCacheQuad, "SDFCache_", OceanDepthCacheType.Baked, _type == OceanDepthCacheType.Baked ? (Texture)_savedCache : _depthCacheTexture);

                voronoiPingPongTexture0.DiscardContents();
                voronoiPingPongTexture1.DiscardContents();
            }
            else
            {
                DrawCacheQuad(ref _drawDepthCacheQuad, "DepthCache_", _type, _type == OceanDepthCacheType.Baked ? (Texture)_savedCache : _depthCacheTexture);
            }
        }