public void RenderEffect(Renderer renderer, GraphicsDevice device)
        {
            RenderTarget2D half0 = renderer.HalfDepth;
            //render to a half-res buffer
            device.SetRenderTarget(half0);

            Apply();

            device.BlendState = BlendState.Opaque;
            device.DepthStencilState = DepthStencilState.None;
            _quadRenderer.RenderQuad(device, -Vector2.One, Vector2.One);
        }
        public void Init(ContentManager contentManager, Renderer renderer)
        {
            try
            {
                _effect = contentManager.Load<Effect>("shaders/DownsampleDepth");
                ExtractParameters();
                Vector2 pixelSize = new Vector2(1.0f / (float)renderer.DepthBuffer.Width, 1.0f / (float)renderer.DepthBuffer.Height);
                PixelSize.SetValue(pixelSize);
                HalfPixel.SetValue(pixelSize * 0.5f);
                DepthBuffer.SetValue(renderer.DepthBuffer);

            }
            catch (Exception ex)
            {
                Console.WriteLine("Error loading downsample depth efect: " + ex.ToString());
            }
        }
 public ShadowRenderer(Renderer renderer)
 {
     //create the render targets
     for (int i = 0; i < NUM_SPOT_SHADOWS; i++)
     {
         SpotShadowMapEntry entry = new SpotShadowMapEntry();
         //we store the linear depth, in a float render target. We need also the HW zbuffer
         entry.Texture = new RenderTarget2D(renderer.GraphicsDevice, SPOT_SHADOW_RESOLUTION,
                                            SPOT_SHADOW_RESOLUTION, false, SurfaceFormat.Single,
                                            DepthFormat.Depth24Stencil8, 0, RenderTargetUsage.DiscardContents);
         entry.LightViewProjection = Matrix.Identity;
         _spotShadowMaps.Add(entry);
     }
     for (int i = 0; i < NUM_CSM_SHADOWS; i++)
     {
         CascadeShadowMapEntry entry = new CascadeShadowMapEntry();
         entry.Texture = new RenderTarget2D(renderer.GraphicsDevice, CASCADE_SHADOW_RESOLUTION * NUM_CSM_SPLITS,
                                            CASCADE_SHADOW_RESOLUTION, false, SurfaceFormat.Single,
                                            DepthFormat.Depth24Stencil8, 0, RenderTargetUsage.DiscardContents);
         _cascadeShadowMaps.Add(entry);
     }
 }
        public void GenerateShadowTextureDirectionalLight(Renderer renderer, object[] meshes, object[] InstancedMeshes, Light light, CascadeShadowMapEntry cascadeShadowMap, Camera.Camera camera)
        {
            //bind the render target
            renderer.GraphicsDevice.SetRenderTarget(cascadeShadowMap.Texture);
            //clear it to white, ie, far far away
            renderer.GraphicsDevice.Clear(Color.White);
            renderer.GraphicsDevice.BlendState = BlendState.Opaque;
            renderer.GraphicsDevice.DepthStencilState = DepthStencilState.Default;

            // Get the corners of the frustum
            camera.Frustum.GetCorners(frustumCornersWS);
            Matrix eyeTransform = camera.View;
            Vector3.Transform(frustumCornersWS, ref eyeTransform, frustumCornersVS);

            float near = camera.NearPlane, far = MathHelper.Min(camera.FarPlane, light.ShadowDistance);

            splitDepthsTmp[0] = near;
            splitDepthsTmp[NUM_CSM_SPLITS] = far;

            //compute each distance the way you like...
            for (int i = 1; i < splitDepthsTmp.Length - 1; i++)
                splitDepthsTmp[i] = near + (far - near) * (float)Math.Pow((i / (float)NUM_CSM_SPLITS), 3);

            Viewport splitViewport = new Viewport();
            Vector3 lightDir = -Vector3.Normalize(light.Transform.Forward);

            BoundingFrustum frustum = new BoundingFrustum(Matrix.Identity);

            for (int i = 0; i < NUM_CSM_SPLITS; i++)
            {
                cascadeShadowMap.LightClipPlanes[i].X = -splitDepthsTmp[i];
                cascadeShadowMap.LightClipPlanes[i].Y = -splitDepthsTmp[i + 1];

                cascadeShadowMap.LightViewProjectionMatrices[i] = CreateLightViewProjectionMatrix(lightDir, far, camera, splitDepthsTmp[i], splitDepthsTmp[i + 1], i);
                Matrix viewProj = cascadeShadowMap.LightViewProjectionMatrices[i];

                // Set the viewport for the current split
                splitViewport.MinDepth = 0;
                splitViewport.MaxDepth = 1;
                splitViewport.Width = CASCADE_SHADOW_RESOLUTION;
                splitViewport.Height = CASCADE_SHADOW_RESOLUTION;
                splitViewport.X = i * CASCADE_SHADOW_RESOLUTION;
                splitViewport.Y = 0;
                renderer.GraphicsDevice.Viewport = splitViewport;

                frustum.Matrix = viewProj;

                foreach (object mesh in meshes)
                {
                    if (mesh is List<Models>)
                        for (int index = 0; index < ((List<Models>)mesh).Count; index++)
                        {
                            Models m = ((List<Models>)mesh)[index];
                            //cull meshes outside the light volume
                         //   if (!frustum.Intersects(m.BoundingSphere))
                         //       continue;

                            //render it
                            m.RenderShadowMap(ref viewProj, renderer.GraphicsDevice);
                        }
                    if (mesh is Models)
                    {
                        //cull meshes outside the light volume
                       // if (!frustum.Intersects(((Models)mesh).BoundingSphere))
                        //    continue;

                        //render it
                        ((Models)mesh).RenderShadowMap(ref viewProj, renderer.GraphicsDevice);
                    }
                    if (mesh is CarPlayer)
                    {
                        ((CarPlayer)mesh).RenderShadowMap(ref viewProj, renderer.GraphicsDevice);
                    }
                    if (mesh is Terrain.Terrain)
                    {
                        for (int index = 0; index < ((Terrain.Terrain)mesh).QuadTrees.Count; index++)
                        {
                            //cull meshes outside the light volume
                          //  if (!frustum.Intersects(((Terrain.Terrain)mesh).QuadTrees[index].BoundingSphere))
                          //      continue;

                            //render it
                            ((Terrain.Terrain)mesh).QuadTrees[index].RenderShadowMap(ref viewProj, renderer.GraphicsDevice);
                        }

                    }
                }
                foreach (object mesh in InstancedMeshes)
                {
                    if (mesh is Billboards.Billboard)
                    {
                        ((Billboards.Billboard)mesh).TreePreDraw();

                        for (int lod = 0; lod < ((Billboards.Billboard)mesh).LOD; lod++)
                            if (((Billboards.Billboard)mesh).instanceTransforms[lod].Length != 0)
                                ((Billboards.Billboard)mesh).trunck[lod][0].RenderShadowMap(ref viewProj, renderer.GraphicsDevice);

                        if (((Billboards.Billboard)mesh).Leaves)
                            for (int tree = 0; tree < ((Billboards.Billboard)mesh).NoTrees; tree++)
                            {
                                if (((Billboards.Billboard)mesh).LeavesAreVisible[tree])
                                    for (int j = 0; j < ((Billboards.Billboard)mesh).NoLeaves; j++)
                                    {
                                        ((Billboards.Billboard)mesh).leaves[tree][j].UpdateTransformationMatrix(((Billboards.Billboard)mesh).instanceTransforms1[tree]);
                                        if (j == 0)
                                            ((Billboards.Billboard)mesh).leaves[tree][j].RenderShadowMap(ref viewProj, renderer.GraphicsDevice);
                                    }
                            }
                    }
                }
            }
        }
        public void GenerateShadowTextureSpotLight(Renderer renderer, object[] meshes, object[] InstancedMeshes, Light light, SpotShadowMapEntry shadowMap)
        {
            //bind the render target
            renderer.GraphicsDevice.SetRenderTarget(shadowMap.Texture);
            //clear it to white, ie, far far away
            renderer.GraphicsDevice.Clear(Color.White);
            renderer.GraphicsDevice.BlendState = BlendState.Opaque;
            renderer.GraphicsDevice.DepthStencilState = DepthStencilState.Default;

            Matrix viewProj = light.ViewProjection;
            shadowMap.LightViewProjection = viewProj;

            BoundingFrustum frustum = light.Frustum;

            foreach (object mesh in meshes)
            {
                if (mesh is List<Models>)
                    for (int index = 0; index < ((List<Models>)mesh).Count; index++)
                    {
                        Models m = ((List<Models>)mesh)[index];
                        //cull meshes outside the light volume
                        //   if (!frustum.Intersects(m.BoundingSphere))
                        //       continue;

                        //render it
                        m.RenderShadowMap(ref viewProj, renderer.GraphicsDevice);
                    }
                if (mesh is Models)
                {
                    //cull meshes outside the light volume
                    // if (!frustum.Intersects(((Models)mesh).BoundingSphere))
                    //    continue;

                    //render it
                    ((Models)mesh).RenderShadowMap(ref viewProj, renderer.GraphicsDevice);
                }
                if (mesh is CarPlayer)
                {
                    ((CarPlayer)mesh).RenderShadowMap(ref viewProj, renderer.GraphicsDevice);
                }
                if (mesh is Terrain.Terrain)
                {
                    for (int index = 0; index < ((Terrain.Terrain)mesh).QuadTrees.Count; index++)
                    {
                        //cull meshes outside the light volume
                        //  if (!frustum.Intersects(((Terrain.Terrain)mesh).QuadTrees[index].BoundingSphere))
                        //      continue;

                        //render it
                        ((Terrain.Terrain)mesh).QuadTrees[index].RenderShadowMap(ref viewProj, renderer.GraphicsDevice);
                    }

                }
            }
            foreach (object mesh in InstancedMeshes)
            {
                if (mesh is Billboards.Billboard)
                {
                    ((Billboards.Billboard)mesh).TreePreDraw();

                    for (int lod = 0; lod < ((Billboards.Billboard)mesh).LOD; lod++)
                        if (((Billboards.Billboard)mesh).instanceTransforms[lod].Length != 0)
                            ((Billboards.Billboard)mesh).trunck[lod][0].RenderShadowMap(ref viewProj, renderer.GraphicsDevice);

                    if (((Billboards.Billboard)mesh).Leaves)
                        for (int tree = 0; tree < ((Billboards.Billboard)mesh).NoTrees; tree++)
                        {
                            if (((Billboards.Billboard)mesh).LeavesAreVisible[tree])
                                for (int j = 0; j < ((Billboards.Billboard)mesh).NoLeaves; j++)
                                {
                                    ((Billboards.Billboard)mesh).leaves[tree][j].UpdateTransformationMatrix(((Billboards.Billboard)mesh).instanceTransforms1[tree]);
                                    if (j == 0)
                                        ((Billboards.Billboard)mesh).leaves[tree][j].RenderShadowMap(ref viewProj, renderer.GraphicsDevice);
                                }
                        }
                }
            }
        }
        public void RenderPostFx(Renderer renderer, GraphicsDevice device, RenderTarget2D srcTarget, RenderTarget2D dstTarget)
        {
            RenderTarget2D quarter0 = renderer.QuarterBuffer0;
            RenderTarget2D quarter1 = renderer.QuarterBuffer1;
            RenderTarget2D halfDepth = renderer.GetDownsampledDepth();

            _effect.CurrentTechnique = _effect.Techniques[0];
            device.BlendState = BlendState.Opaque;
            device.DepthStencilState = DepthStencilState.None;
            device.RasterizerState = RasterizerState.CullNone;

            //render to a half-res buffer
            device.SetRenderTarget(quarter0);
            _parameterColorBuffer.SetValue(srcTarget);
            _parameterHalfDepthTexture.SetValue(halfDepth);
            _parameterTextureAspectRatio.SetValue(srcTarget.Height / (float)srcTarget.Width);
            // Convert to rgb first, so we have linear filtering
            _effect.CurrentTechnique = _effect.Techniques[0];

            Vector2 pixelSize = new Vector2(1.0f / (float)srcTarget.Width, 1.0f / (float)srcTarget.Height);
            _parameterPixelSize.SetValue(pixelSize);
            _parameterHalfPixel.SetValue(pixelSize * 0.5f);

            _effect.CurrentTechnique.Passes[0].Apply();
            _quadRenderer.RenderQuad(device, -Vector2.One, Vector2.One);

            pixelSize = new Vector2(1.0f / (float)quarter0.Width, 1.0f / (float)quarter0.Height);
            _parameterPixelSize.SetValue(pixelSize);
            _parameterHalfPixel.SetValue(pixelSize * 0.5f);
            _effect.CurrentTechnique = _effect.Techniques[1];

            device.SetRenderTarget(quarter1);
            _parameterRGBShaftTexture.SetValue(quarter0);

            _effect.CurrentTechnique.Passes[0].Apply();
            _quadRenderer.RenderQuad(device, -Vector2.One, Vector2.One);

            device.SetRenderTarget(dstTarget);

            pixelSize = new Vector2(1.0f / (float)srcTarget.Width, 1.0f / (float)srcTarget.Height);
            _parameterPixelSize.SetValue(pixelSize);
            _parameterHalfPixel.SetValue(pixelSize * 0.5f);

            device.RasterizerState = RasterizerState.CullNone;
            device.DepthStencilState = DepthStencilState.None;

            device.BlendState = BlendState.Opaque;

            _parameterRGBShaftTexture.SetValue(quarter1);
            _effect.CurrentTechnique = _effect.Techniques[2];
            _effect.CurrentTechnique.Passes[0].Apply();
            _quadRenderer.RenderQuad(device, -Vector2.One, Vector2.One);
            device.SetRenderTarget(null);
        }
        /// <summary>
        /// Initialize the effect. Loads the shader file, extract the parameters, apply
        /// the default values
        /// </summary>
        /// <param name="contentManager"></param>
        /// <param name="renderer"></param>
        public void Init(ContentManager contentManager, Renderer renderer)
        {
            _quadRenderer = new QuadRenderer();
            try
            {
                _effect = contentManager.Load<Effect>("Shaders/LightShaft");
                ExtractParameters();

            }
            catch (Exception ex)
            {
                Console.WriteLine("Error loading bloom depth effect: " + ex.ToString());
            }
        }