BoundingRect[] DetectFingersFromImage(Canvas canvas, Texture2D image)
        {
            GraphicsDevice device = canvas.GetDevice();
            DepthStencilBuffer dsOld = device.DepthStencilBuffer;
            device.DepthStencilBuffer = canvas.GetDepthStencil();
            device.SetRenderTarget(0, dsChain[0]);
            canvas.DrawImage(image, Vector2.One * -1, Vector2.One, (int)ImageParameters.FlipY);
            device.SetRenderTarget(0, null);

            downsampleMaxLumShader.SetupShader(canvas);
            for(int i = 1; i < dsChain.Length; i++)
            {
                device.Textures[0] = dsChain[i-1].GetTexture();
                Vector2 invRes = Vector2.One / new Vector2(dsChain[i-1].Width, dsChain[i-1].Height);
                device.SetVertexShaderConstant(CanvasShaderConstants.VC_INVTEXRES, invRes);
                device.SetPixelShaderConstant(0, invRes);
                device.SetRenderTarget(0, dsChain[i]);
                CanvasPrimitives.Quad.Render(canvas);
                device.SetRenderTarget(0, null);
            }

            biasLumShader.SetupShader(canvas);
            int idx = dsChain.Length - 1;
            device.Textures[0] = dsChain[idx].GetTexture();
            Vector2 iRes = Vector2.One / new Vector2(dsChain[idx].Width, dsChain[idx].Height);
            device.SetVertexShaderConstant(CanvasShaderConstants.VC_INVTEXRES, iRes);
            device.SetRenderTarget(0, dsChain[idx]);
            CanvasPrimitives.Quad.Render(canvas);
            device.SetRenderTarget(0, null);

            device.DepthStencilBuffer = dsOld;

            return FloodFillBounds(dsChain[idx].GetTexture());
        }
        public void CompositeFinalImage(Canvas canvas)
        {
            BoundingRect[] drawRects = GetCameraDrawBoxes();

            GraphicsDevice device = canvas.GetDevice();
            DepthStencilBuffer dsOld = device.DepthStencilBuffer;
            device.DepthStencilBuffer = canvas.GetDepthStencil();
            device.SetRenderTarget(0, renderTarget);

            canvas.DrawImage(cameraAImage, drawRects[0].Min, drawRects[0].Max, (int)(ImageParameters.FlipY));
            canvas.DrawImage(cameraBImage, drawRects[1].Min, drawRects[1].Max, (int)(ImageParameters.FlipY));

            device.RenderState.AlphaBlendEnable = true;
            device.RenderState.SourceBlend = Blend.SourceAlpha;
            device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;

            canvas.DrawImage(renderLayerA.GetImage(), drawRects[0].Min, drawRects[0].Max);
            canvas.DrawImage(renderLayerB.GetImage(), drawRects[1].Min, drawRects[1].Max);

            device.SetRenderTarget(0, null);
            device.DepthStencilBuffer = dsOld;

            //RenderMatrixStyle(canvas);
            //RenderEdgesStyle(canvas);
            //CanvasPrimitives.Quad.SetPositions(Vector2.One * -2, Vector2.One);

            device.RenderState.DepthBufferEnable = false;
            device.RenderState.DepthBufferWriteEnable = false;
            canvas.DrawImage(renderTarget.GetTexture());
            /*
            CanvasPrimitives.Quad.SetPositions(Vector2.One * -1, Vector2.One);
            device.RenderState.DepthBufferEnable = true;
            device.RenderState.DepthBufferWriteEnable = true;
            render3D.SetupShader(canvas);
            Matrix scaleMat = Matrix.CreateScale(0.05f);
            device.SetVertexShaderConstant(CanvasShaderConstants.VC_MODELVIEW, virtualCameraA.ViewProjection);
            for (int i = 0; i < detectionPoints.Length; i++)
            {
                device.SetPixelShaderConstant(0, fingerColors[i % fingerColors.Length].ToVector4());
                scaleMat.Translation = detectionPoints[i].Center;
                device.SetVertexShaderConstant(CanvasShaderConstants.VC_WORLD, scaleMat);
                CanvasPrimitives.Quad.Render(canvas);
            }
            */
        }