public static void ApplySliceTransform(ref ShadowSliceData shadowSliceData, int atlasWidth, int atlasHeight)
        {
            Matrix4x4 sliceTransform     = Matrix4x4.identity;
            float     oneOverAtlasWidth  = 1.0f / atlasWidth;
            float     oneOverAtlasHeight = 1.0f / atlasHeight;

            sliceTransform.m00 = shadowSliceData.resolution * oneOverAtlasWidth;
            sliceTransform.m11 = shadowSliceData.resolution * oneOverAtlasHeight;
            sliceTransform.m03 = shadowSliceData.offsetX * oneOverAtlasWidth;
            sliceTransform.m13 = shadowSliceData.offsetY * oneOverAtlasHeight;

            // Apply shadow slice scale and offset
            shadowSliceData.shadowTransform = sliceTransform * shadowSliceData.shadowTransform;
        }
        public static void RenderShadowSlice(CommandBuffer cmd, ref ScriptableRenderContext context,
                                             ref ShadowSliceData shadowSliceData, ref ShadowDrawingSettings settings,
                                             Matrix4x4 proj, Matrix4x4 view)
        {
            cmd.SetViewport(new Rect(shadowSliceData.offsetX, shadowSliceData.offsetY, shadowSliceData.resolution, shadowSliceData.resolution));
            cmd.EnableScissorRect(new Rect(shadowSliceData.offsetX + 4, shadowSliceData.offsetY + 4, shadowSliceData.resolution - 8, shadowSliceData.resolution - 8));

            cmd.SetViewProjectionMatrices(view, proj);
            context.ExecuteCommandBuffer(cmd);
            cmd.Clear();
            context.DrawShadows(ref settings);
            cmd.DisableScissorRect();
            context.ExecuteCommandBuffer(cmd);
            cmd.Clear();
        }
        public static bool ExtractDirectionalLightMatrix(ref CullingResults cullResults, ref ShadowData shadowData, int shadowLightIndex, int cascadeIndex, int shadowmapWidth, int shadowmapHeight, int shadowResolution, float shadowNearPlane, out Vector4 cascadeSplitDistance, out ShadowSliceData shadowSliceData, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix, Bounds bounds)
        {
            ShadowSplitData splitData;
            bool            success = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex,
                                                                                                       cascadeIndex, shadowData.mainLightShadowCascadesCount, shadowData.mainLightShadowCascadesSplit, shadowResolution, shadowNearPlane, out viewMatrix, out projMatrix,
                                                                                                       out splitData);

            cascadeSplitDistance       = splitData.cullingSphere;
            shadowSliceData.offsetX    = (cascadeIndex % 2) * shadowResolution;
            shadowSliceData.offsetY    = (cascadeIndex / 2) * shadowResolution;
            shadowSliceData.resolution = shadowResolution;
            shadowSliceData.viewMatrix = viewMatrix;

            Bounds    lightViewBounts  = TransformBounds(viewMatrix, bounds);
            Matrix4x4 tight_projMatrix = ProjMatFromBounds(lightViewBounts, projMatrix);//tight aabb

            tight_projMatrix.SetRow(2, projMatrix.GetRow(2));
            shadowSliceData.projectionMatrix = tight_projMatrix;
            shadowSliceData.shadowTransform  = GetShadowTransform(tight_projMatrix, viewMatrix);

            // If we have shadow cascades baked into the atlas we bake cascade transform
            // in each shadow matrix to save shader ALU and L/S
            if (shadowData.mainLightShadowCascadesCount > 1)
            {
                ApplySliceTransform(ref shadowSliceData, shadowmapWidth, shadowmapHeight);
            }

            return(success);
        }