public override void FrameUpdate(PipelineCamera cam, ref PipelineCommandData data)
        {
            if (data.baseBuffer.clusterCount <= 0)
            {
                return;
            }
            CommandBuffer buffer = data.buffer;

            cullJobHandler.Complete();
            UnsafeUtility.ReleaseGCObject(gcHandler);
            pointLightMaterial.SetBuffer(ShaderIDs.verticesBuffer, sphereBuffer);
            //Un Shadow Point light
            buffer.SetRenderTarget(cam.targets.renderTargetIdentifier, cam.targets.depthIdentifier);
            for (int c = 0; c < unShadowCount; c++)
            {
                var         i     = cullJob.indices[cullJob.length - c];
                MPointLight light = MPointLight.allPointLights[i];
                buffer.SetGlobalVector(ShaderIDs._LightColor, light.color);
                buffer.SetGlobalVector(ShaderIDs._LightPos, new Vector4(light.position.x, light.position.y, light.position.z, light.range));
                buffer.SetGlobalFloat(ShaderIDs._LightIntensity, light.intensity);
                buffer.DrawProceduralIndirect(Matrix4x4.identity, pointLightMaterial, 0, MeshTopology.Triangles, sphereIndirectBuffer, 0);
            }
            //TODO
            if (shadowCount > 0)
            {
                NativeArray <Vector4> positions = new NativeArray <Vector4>(shadowCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                for (int i = 0; i < shadowCount; i++)
                {
                    MPointLight light = MPointLight.allPointLights[cullJob.indices[i]];
                    positions[i] = new Vector4(light.position.x, light.position.y, light.position.z, light.range);
                }
                CubeFunction.UpdateLength(ref cubeBuffer, shadowCount);
                var cullShader = data.resources.pointLightFrustumCulling;
                CubeFunction.SetBuffer(ref cubeBuffer, ref data.baseBuffer, cullShader, buffer);
                CubeFunction.PrepareDispatch(ref cubeBuffer, buffer, cullShader, positions);
                for (int i = 0; i < shadowCount; i++)
                {
                    MPointLight light = MPointLight.allPointLights[cullJob.indices[i]];
                    CubeFunction.DrawShadow(light, buffer, ref cubeBuffer, ref data.baseBuffer, cullShader, i, cubeDepthMaterial);
                    buffer.SetRenderTarget(cam.targets.renderTargetIdentifier, cam.targets.depthIdentifier);
                    buffer.SetGlobalVector(ShaderIDs._LightColor, light.color);
                    buffer.SetGlobalVector(ShaderIDs._LightPos, positions[i]);
                    buffer.SetGlobalFloat(ShaderIDs._LightIntensity, light.intensity);
                    buffer.SetGlobalTexture(ShaderIDs._CubeShadowMap, light.shadowmapTexture);
                    buffer.DrawProceduralIndirect(Matrix4x4.identity, pointLightMaterial, 1, MeshTopology.Triangles, sphereIndirectBuffer, 0);
                }
                positions.Dispose();
            }
            //Shadow Point Light
            indicesArray.Dispose();
            data.ExecuteCommandBuffer();
        }
        public void Execute(int index)
        {
            MPointLight cube = MPointLight.allPointLights[index];

            if (PipelineFunctions.FrustumCulling(cube.position, cube.range, planes))
            {
                if (cube.useShadow)
                {
                    int last = Interlocked.Increment(ref *shadowCount) - 1;
                    indices[last] = index;
                }
                else
                {
                    int last = Interlocked.Increment(ref *unShadowCount) - 1;
                    indices[length - last] = index;
                }
            }
        }
 public virtual void DrawCubeMap(MPointLight lit, ref RenderClusterOptions opts, ref CubeCullingBuffer buffer, int offset)
 {
 }
        public override void DrawCubeMap(MPointLight lit, ref RenderClusterOptions opts, ref CubeCullingBuffer buffer, int offset)
        {
            CommandBuffer cb            = opts.command;
            ComputeShader shader        = opts.cullingShader;
            Material      depthMaterial = opts.proceduralMaterial;

            cb.SetComputeIntParam(shader, ShaderIDs._LightOffset, offset);
            ComputeShaderUtility.Dispatch(shader, cb, CubeFunction.RunFrustumCull, baseBuffer.clusterCount, 256);
            PerspCam cam = new PerspCam();

            cam.aspect        = 1;
            cam.farClipPlane  = lit.range;
            cam.nearClipPlane = 0.3f;
            cam.position      = lit.position;
            cam.fov           = 90f;
            Matrix4x4 vpMatrix;

            cb.SetGlobalVector(ShaderIDs._LightPos, new Vector4(lit.position.x, lit.position.y, lit.position.z, lit.range));
            cb.SetGlobalBuffer(ShaderIDs.verticesBuffer, baseBuffer.verticesBuffer);
            cb.SetGlobalBuffer(ShaderIDs.resultBuffer, baseBuffer.resultBuffer);
            //Forward
            cam.forward  = Vector3.forward;
            cam.up       = Vector3.down;
            cam.right    = Vector3.left;
            cam.position = lit.position;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.NegativeZ);
            cb.ClearRenderTarget(true, true, Color.white);
            cb.SetGlobalMatrix(ShaderIDs._VP, vpMatrix);
            offset = offset * 20;
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset);
            //Back
            cam.forward = Vector3.back;
            cam.up      = Vector3.down;
            cam.right   = Vector3.right;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.PositiveZ);
            cb.ClearRenderTarget(true, true, Color.white);
            cb.SetGlobalMatrix(ShaderIDs._VP, vpMatrix);
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset);
            //Up
            cam.forward = Vector3.up;
            cam.up      = Vector3.back;
            cam.right   = Vector3.right;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.PositiveY);
            cb.ClearRenderTarget(true, true, Color.white);
            cb.SetGlobalMatrix(ShaderIDs._VP, vpMatrix);
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset);
            //Down
            cam.forward = Vector3.down;
            cam.up      = Vector3.forward;
            cam.right   = Vector3.right;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.NegativeY);
            cb.ClearRenderTarget(true, true, Color.white);
            cb.SetGlobalMatrix(ShaderIDs._VP, vpMatrix);
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset);
            //Right
            cam.forward = Vector3.right;
            cam.up      = Vector3.down;
            cam.right   = Vector3.forward;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.PositiveX);
            cb.ClearRenderTarget(true, true, Color.white);
            cb.SetGlobalMatrix(ShaderIDs._VP, vpMatrix);
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset);
            //Left
            cam.forward = Vector3.left;
            cam.up      = Vector3.down;
            cam.right   = Vector3.back;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.NegativeX);
            cb.ClearRenderTarget(true, true, Color.white);
            cb.SetGlobalMatrix(ShaderIDs._VP, vpMatrix);
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset);
        }
        public static void DrawShadow(MPointLight lit, CommandBuffer cb, MaterialPropertyBlock block, ref CubeCullingBuffer buffer, ref PipelineBaseBuffer baseBuffer, ComputeShader shader, int offset, Material depthMaterial)
        {
            cb.SetComputeIntParam(shader, ShaderIDs._LightOffset, offset);
            ComputeShaderUtility.Dispatch(shader, cb, RunFrustumCull, baseBuffer.clusterCount, 64);
            PerspCam cam = new PerspCam();

            cam.aspect        = 1;
            cam.farClipPlane  = lit.range;
            cam.nearClipPlane = 0.3f;
            cam.position      = lit.position;
            cam.fov           = 90f;
            Matrix4x4 vpMatrix;

            block.SetVector(ShaderIDs._LightPos, new Vector4(lit.position.x, lit.position.y, lit.position.z, lit.range));
            PipelineFunctions.SetShaderBuffer(ref baseBuffer, block);
            //Forward
            cam.forward  = Vector3.forward;
            cam.up       = Vector3.down;
            cam.right    = Vector3.left;
            cam.position = lit.position;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.NegativeZ);
            cb.ClearRenderTarget(true, true, Color.white);
            block.SetMatrix(ShaderIDs._VP, vpMatrix);
            offset = offset * 20;
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset, block);
            //Back
            cam.forward = Vector3.back;
            cam.up      = Vector3.down;
            cam.right   = Vector3.right;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.PositiveZ);
            cb.ClearRenderTarget(true, true, Color.white);
            block.SetMatrix(ShaderIDs._VP, vpMatrix);
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset, block);
            //Up
            cam.forward = Vector3.up;
            cam.up      = Vector3.back;
            cam.right   = Vector3.right;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.PositiveY);
            cb.ClearRenderTarget(true, true, Color.white);
            block.SetMatrix(ShaderIDs._VP, vpMatrix);
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset, block);
            //Down
            cam.forward = Vector3.down;
            cam.up      = Vector3.forward;
            cam.right   = Vector3.right;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.NegativeY);
            cb.ClearRenderTarget(true, true, Color.white);
            block.SetMatrix(ShaderIDs._VP, vpMatrix);
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset, block);
            //Right
            cam.forward = Vector3.right;
            cam.up      = Vector3.down;
            cam.right   = Vector3.forward;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.PositiveX);
            cb.ClearRenderTarget(true, true, Color.white);
            block.SetMatrix(ShaderIDs._VP, vpMatrix);
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset, block);
            //Left
            cam.forward = Vector3.left;
            cam.up      = Vector3.down;
            cam.right   = Vector3.back;
            cam.UpdateTRSMatrix();
            cam.UpdateProjectionMatrix();
            vpMatrix = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) * cam.worldToCameraMatrix;
            cb.SetRenderTarget(lit.shadowmapTexture, 0, CubemapFace.NegativeX);
            cb.ClearRenderTarget(true, true, Color.white);
            block.SetMatrix(ShaderIDs._VP, vpMatrix);
            cb.DrawProceduralIndirect(Matrix4x4.identity, depthMaterial, 0, MeshTopology.Triangles, buffer.indirectDrawBuffer, offset, block);
        }