public static DepthReadback GetDepthReadback(RenderContext context)
            {
                var           sceneCameraRenderer = context.Tags.Get(SceneCameraRenderer.Current);
                DepthReadback depthReadBack;

                for (int i = 0; i < sceneCameraRenderer.PostRenderers.Count; i++)
                {
                    depthReadBack = sceneCameraRenderer.PostRenderers[i] as DepthReadback;
                    if (depthReadBack != null)
                    {
                        return(depthReadBack);
                    }
                }

                depthReadBack = new DepthReadback();
                sceneCameraRenderer.PostRenderers.Add(depthReadBack);
                return(depthReadBack);
            }
            public static DepthReadback GetDepthReadback(RenderContext context)
            {
                var sceneCameraRenderer = context.Tags.Get(SceneCameraRenderer.Current);
                DepthReadback depthReadBack;
                for (int i = 0; i < sceneCameraRenderer.PostRenderers.Count; i++)
                {
                    depthReadBack = sceneCameraRenderer.PostRenderers[i] as DepthReadback;
                    if (depthReadBack != null)
                    {
                        return depthReadBack;
                    }
                }

                depthReadBack = new DepthReadback();
                sceneCameraRenderer.PostRenderers.Add(depthReadBack);
                return depthReadBack;
            }
        private Vector2 ComputeCascadeSplits(RenderContext context, ShadowMapRenderer shadowContext, ref LightShadowMapTexture lightShadowMap)
        {
            var shadow = (LightDirectionalShadowMap)lightShadowMap.Shadow;

            var cameraNear  = shadowContext.Camera.NearClipPlane;
            var cameraFar   = shadowContext.Camera.FarClipPlane;
            var cameraRange = cameraFar - cameraNear;

            var minDistance = cameraNear + LightDirectionalShadowMap.DepthRangeParameters.DefaultMinDistance;
            var maxDistance = cameraNear + LightDirectionalShadowMap.DepthRangeParameters.DefaultMaxDistance;

            if (shadow.DepthRange.IsAutomatic)
            {
                var depthReadBack = DepthReadback.GetDepthReadback(context);
                if (depthReadBack.IsResultAvailable)
                {
                    var depthMinMax = depthReadBack.DepthMinMax;

                    minDistance = ToLinearDepth(depthMinMax.X, ref shadowContext.Camera.ProjectionMatrix);
                    // Reserve 1/3 of the guard distance for the min distance
                    minDistance = Math.Max(cameraNear, minDistance - shadow.DepthRange.GuardDistance / 3);

                    // Reserve 2/3 of the guard distance for the max distance
                    var guardMaxDistance = minDistance + shadow.DepthRange.GuardDistance * 2 / 3;
                    maxDistance = ToLinearDepth(depthMinMax.Y, ref shadowContext.Camera.ProjectionMatrix);
                    maxDistance = Math.Max(maxDistance, guardMaxDistance);
                }
            }
            else
            {
                minDistance = cameraNear + shadow.DepthRange.ManualMinDistance;
                maxDistance = cameraNear + shadow.DepthRange.ManualMaxDistance;
            }

            var manualPartitionMode      = shadow.PartitionMode as LightDirectionalShadowMap.PartitionManual;
            var logarithmicPartitionMode = shadow.PartitionMode as LightDirectionalShadowMap.PartitionLogarithmic;

            if (logarithmicPartitionMode != null)
            {
                var minZ = minDistance;
                var maxZ = maxDistance;

                var range    = maxZ - minZ;
                var ratio    = maxZ / minZ;
                var logRatio = MathUtil.Clamp(1.0f - logarithmicPartitionMode.PSSMFactor, 0.0f, 1.0f);

                for (int cascadeLevel = 0; cascadeLevel < lightShadowMap.CascadeCount; ++cascadeLevel)
                {
                    // Compute cascade split (between znear and zfar)
                    float distrib  = (float)(cascadeLevel + 1) / lightShadowMap.CascadeCount;
                    float logZ     = (float)(minZ * Math.Pow(ratio, distrib));
                    float uniformZ = minZ + range * distrib;
                    float distance = MathUtil.Lerp(uniformZ, logZ, logRatio);
                    cascadeSplitRatios[cascadeLevel] = distance;
                }
            }
            else if (manualPartitionMode != null)
            {
                if (lightShadowMap.CascadeCount == 1)
                {
                    cascadeSplitRatios[0] = minDistance + manualPartitionMode.SplitDistance1 * maxDistance;
                }
                else if (lightShadowMap.CascadeCount == 2)
                {
                    cascadeSplitRatios[0] = minDistance + manualPartitionMode.SplitDistance1 * maxDistance;
                    cascadeSplitRatios[1] = minDistance + manualPartitionMode.SplitDistance3 * maxDistance;
                }
                else if (lightShadowMap.CascadeCount == 4)
                {
                    cascadeSplitRatios[0] = minDistance + manualPartitionMode.SplitDistance0 * maxDistance;
                    cascadeSplitRatios[1] = minDistance + manualPartitionMode.SplitDistance1 * maxDistance;
                    cascadeSplitRatios[2] = minDistance + manualPartitionMode.SplitDistance2 * maxDistance;
                    cascadeSplitRatios[3] = minDistance + manualPartitionMode.SplitDistance3 * maxDistance;
                }
            }

            // Convert distance splits to ratios cascade in the range [0, 1]
            for (int i = 0; i < cascadeSplitRatios.Length; i++)
            {
                cascadeSplitRatios[i] = (cascadeSplitRatios[i] - cameraNear) / cameraRange;
            }

            return(new Vector2(minDistance, maxDistance));
        }