private void DrawSpotLight(SpotLight sl, bool renderShadows = false)
        {
            sl.lightDirection.Normalize();

            //lightPosition = camera.Position + (Vector3.Right + Vector3.Down) * 10;
            //spotDirection = camera.Forward;



            //set the G-Buffer parameters
            spotLightEffect.Parameters["colorMap"].SetValue(colorRT);
            spotLightEffect.Parameters["normalMap"].SetValue(normalRT);
            spotLightEffect.Parameters["depthMap"].SetValue(depthRT);
            spotLightEffect.Parameters["transMap"].SetValue(transRT);



            //compute the light world matrix
            //scale according to light radius, and translate it to light position

            Matrix spotMatrix = Matrix.CreateFromQuaternion(QuaternionLookRotation(sl.lightDirection));

            spotMatrix.Translation = sl.lightPosition;
            float  spotAngleRad      = MathHelper.ToRadians(sl.spotAngle);
            float  tan               = (float)Math.Tan(spotAngleRad);
            Matrix sphereWorldMatrix = Matrix.CreateScale(sl.lightRadius * tan, sl.lightRadius * tan, sl.lightRadius) * spotMatrix;
            float  cosSpotAngle      = (float)Math.Cos(spotAngleRad);

            int currentTechnique = 0;

            if (renderShadows)
            {
                GraphicsDevice.SetRenderTarget(null);
                GraphicsDevice.SetRenderTargets(shadowRTColor, shadowRTDepth);
                GraphicsDevice.BlendState          = BlendState.Opaque;
                clearBufferEffect.CurrentTechnique = clearBufferEffect.Techniques[1];
                clearBufferEffect.Techniques[1].Passes[0].Apply();
                quadRenderer.Render(Vector2.One * -1, Vector2.One);

                Matrix spotProj = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(sl.spotAngle * 2), 1, 0.01f * sl.lightRadius, sl.lightRadius);
                Matrix spotView = Matrix.CreateLookAt(sl.lightPosition, sl.lightPosition + sl.lightDirection, Vector3.Up);

                //scene.DrawSceneShadow(inverseTransform, spotProj, currentModel);
                scene.DrawSceneShadow(spotView, spotProj, currentModel, 1);
                GraphicsDevice.SetRenderTarget(null);
                GraphicsDevice.SetRenderTarget(lightRT);
                GraphicsDevice.BlendState        = BlendState.AlphaBlend;
                GraphicsDevice.DepthStencilState = DepthStencilState.None;
                spotLightEffect.Parameters["ShadowInvertViewProjection"].SetValue((spotView * spotProj));
                //spotLightEffect.Parameters["ShadowView"].SetValue((spotView));
                //spotLightEffect.Parameters["ShadowProjection"].SetValue((spotProj));
                spotLightEffect.Parameters["shadowMapColor"].SetValue(shadowRTColor);
                spotLightEffect.Parameters["shadowMapDepth"].SetValue(shadowRTDepth);
                spotLightEffect.Parameters["shadowHalfPixel"].SetValue(shadowHalfPixel);
                currentTechnique = 1;
            }



            spotLightEffect.Parameters["World"].SetValue(sphereWorldMatrix);
            spotLightEffect.Parameters["View"].SetValue(camera.View);
            spotLightEffect.Parameters["Projection"].SetValue(camera.Projection);
            //light position
            spotLightEffect.Parameters["lightPosition"].SetValue(sl.lightPosition);

            //set the color, radius and Intensity
            spotLightEffect.Parameters["Color"].SetValue(sl.lightColor.ToVector3());
            spotLightEffect.Parameters["lightRadius"].SetValue(sl.lightRadius);
            spotLightEffect.Parameters["lightIntensity"].SetValue(sl.lightIntensity);
            spotLightEffect.Parameters["spotDirection"].SetValue(sl.lightDirection);
            spotLightEffect.Parameters["spotLightAngleCosine"].SetValue(cosSpotAngle);
            spotLightEffect.Parameters["spotDecayExponent"].SetValue(10f);

            //parameters for specular computations
            spotLightEffect.Parameters["cameraPosition"].SetValue(camera.Position);
            spotLightEffect.Parameters["InvertViewProjection"].SetValue(Matrix.Invert(camera.View * camera.Projection));
            //size of a halfpixel, for texture coordinates alignment
            spotLightEffect.Parameters["halfPixel"].SetValue(halfPixel);
            //calculate the distance between the camera and light center
            float cameraToCenter = Vector3.Distance(camera.Position, sl.lightPosition);

            //if we are inside the light volume, draw the sphere's inside face
            if (cameraToCenter < sl.lightRadius)
            {
                GraphicsDevice.RasterizerState = RasterizerState.CullClockwise;
            }
            else
            {
                GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
            }

            //            GraphicsDevice.DepthStencilState = DepthStencilState.None;
            spotLightEffect.CurrentTechnique = spotLightEffect.Techniques[currentTechnique];
            spotLightEffect.Techniques[currentTechnique].Passes[0].Apply();
            foreach (ModelMesh mesh in spotModel.Meshes)
            {
                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                {
                    GraphicsDevice.Indices = meshPart.IndexBuffer;
                    GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer);

                    GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount);
                }
            }

            GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
            //            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
        }
        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            if (showStuff)
            {
                for (int i = pointList.GetLength(0) - 1; i > 0; i--)
                {
                    pointList[i].Position.Y = pointList[i - 1].Position.Y;
                }
            }
            KeyboardState hit = new KeyboardState();

            hit = Keyboard.GetState();
            int previousModel = currentModel;
            int previousRes   = currentRes;

            if (hit.IsKeyDown(Keys.Multiply) && previousState.IsKeyUp(Keys.Multiply) && currentModel < 6)
            {
                currentModel++;
            }
            if (hit.IsKeyDown(Keys.Divide) && previousState.IsKeyUp(Keys.Divide) && currentModel > 4)
            {
                currentModel--;
            }
            //if (hit.IsKeyDown(Keys.Add) && previousState.IsKeyUp(Keys.Add))
            //    n++;
            //if (hit.IsKeyDown(Keys.Subtract) && previousState.IsKeyUp(Keys.Subtract) && n > 0)
            //    n--;

            if (hit.IsKeyDown(Keys.D1) && previousState.IsKeyUp(Keys.D1))
            {
                currentRes = 1;
                LoadContent();
            }
            if (hit.IsKeyDown(Keys.D2) && previousState.IsKeyUp(Keys.D2))
            {
                currentRes = 2;
                LoadContent();
            }
            if (hit.IsKeyDown(Keys.D3) && previousState.IsKeyUp(Keys.D3))
            {
                currentRes = 3;
                LoadContent();
            }
            if (hit.IsKeyDown(Keys.T) && previousState.IsKeyUp(Keys.T))
            {
                showStuff = !showStuff;
            }
            if (hit.IsKeyDown(Keys.Y) && previousState.IsKeyUp(Keys.Y))
            {
                lastRT = previewRT;
            }
            if (hit.IsKeyDown(Keys.U) && previousState.IsKeyUp(Keys.U))
            {
                lastRT = colorRT;
            }
            if (hit.IsKeyDown(Keys.I) && previousState.IsKeyUp(Keys.I))
            {
                lastRT = normalRT;
            }
            if (hit.IsKeyDown(Keys.O) && previousState.IsKeyUp(Keys.O))
            {
                lastRT = lightRT;
            }
            if (hit.IsKeyDown(Keys.P) && previousState.IsKeyUp(Keys.P))
            {
                lastRT = shadowRTColor;
            }
            //if (hit.IsKeyDown(Keys.L) && previousState.IsKeyUp(Keys.L))
            //{
            //    lastRT = shadowRTDepth;
            //}
            if (hit.IsKeyDown(Keys.M) && previousState.IsKeyUp(Keys.M))
            {
                lastRT = depthRT;
            }
            if (hit.IsKeyDown(Keys.LeftAlt) && hit.IsKeyDown(Keys.N) && previousState.IsKeyUp(Keys.N))
            {
                if (spotLights.Count > 0)
                {
                    spotLights.RemoveAt(spotLights.Count - 1);
                }
            }
            else if (hit.IsKeyDown(Keys.N) && previousState.IsKeyUp(Keys.N))
            {
                SpotLight spot = new SpotLight()
                {
                    lightPosition  = camera.Position,
                    lightColor     = colors[spotLights.Count % 10],
                    lightRadius    = 500,
                    lightIntensity = 2,
                    lightDirection = camera.Forward,
                    spotAngle      = 15,
                    decay          = 10
                };
                spotLights.Add(spot);
            }
            if (hit.IsKeyDown(Keys.B) && previousState.IsKeyUp(Keys.B))
            {
                spotLights.Clear();
            }
            if (hit.IsKeyDown(Keys.V) && previousState.IsKeyUp(Keys.V))
            {
                doShadows = !doShadows;
            }
            if (hit.IsKeyDown(Keys.RightShift) && previousState.IsKeyUp(Keys.RightShift))
            {
                if (shadowRes * 2 <= 4096)
                {
                    shadowRes *= 2;
                    LoadContent();
                }
            }
            if (hit.IsKeyDown(Keys.RightControl) && previousState.IsKeyUp(Keys.RightControl))
            {
                if (shadowRes / 2 >= 128)
                {
                    shadowRes /= 2;
                    LoadContent();
                }
            }
            if (hit.IsKeyDown(Keys.K) || previousRes != currentRes || previousModel != currentModel)
            {
                framesTime = 0;
                frameCount = 0;
            }

            if (hit.IsKeyDown(Keys.H) && previousState.IsKeyUp(Keys.H))
            {
                vScale -= 0.01f;
            }
            if (hit.IsKeyDown(Keys.J) && previousState.IsKeyUp(Keys.J))
            {
                vScale += 0.01f;
            }
            if (hit.IsKeyDown(Keys.G) && previousState.IsKeyUp(Keys.G))
            {
                vScale = 0f;
            }
            previousState = hit;
            base.Update(gameTime);
            double prevDur = hpt.Duration;

            hpt.Stop();
            double nowDur = hpt.Duration;

            timeSinceLastUpdate = nowDur - prevDur;
        }
        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
            hpt.Start();
            hpt.Stop();
            camera                = new Camera(Game);
            camera.CameraArc      = -30;
            camera.CameraDistance = 50;
            quadRenderer          = new QuadRenderComponent(Game);
            Game.Components.Add(camera);
            Game.Components.Add(quadRenderer);
            previousState = Keyboard.GetState();

            spotLights = new List <SpotLight>();

            { // graph code
                int n = 300;
                //GeneratePoints generates a random graph, implementation irrelevant
                pointList = new VertexPositionColor[n];
                int height = 300;
                int minY   = 0;
                for (int i = 0; i < n; i++)
                {
                    pointList[i] = new VertexPositionColor()
                    {
                        Position = new Vector3(i * 10, 0, 0), Color = Color.Red
                    }
                }
                ;

                //links the points into a list
                lineListIndices = new short[(n * 2) - 2];
                for (int i = 0; i < n - 1; i++)
                {
                    lineListIndices[i * 2]       = (short)(i);
                    lineListIndices[(i * 2) + 1] = (short)(i + 1);
                }

                worldMatrix      = Matrix.Identity;
                viewMatrix       = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up);
                projectionMatrix = Matrix.CreateOrthographicOffCenter(0, (float)GraphicsDevice.Viewport.Width, 0, (float)GraphicsDevice.Viewport.Height, 1.0f, 1000.0f);

                basicEffect            = new BasicEffect(GraphicsDevice);
                basicEffect.World      = worldMatrix;
                basicEffect.View       = viewMatrix;
                basicEffect.Projection = projectionMatrix;

                basicEffect.VertexColorEnabled = true; //important for color
            }

            SpotLight spot = new SpotLight()
            {
                lightPosition  = new Vector3(371, 290, -120),
                lightColor     = Color.White,
                lightRadius    = 500,
                lightIntensity = 2,
                lightDirection = new Vector3(-371, -290, 120),
                spotAngle      = 15,
                decay          = 1
            };

            spotLights.Add(spot);
            spot = new SpotLight()
            {
                lightPosition  = new Vector3(-120, 290, 371),
                lightColor     = Color.White,
                lightRadius    = 500,
                lightIntensity = 2,
                lightDirection = new Vector3(120, -260, -371),
                spotAngle      = 15,
                decay          = 10
            };
            spotLights.Add(spot);
        }