Example #1
0
        /// <summary>
        /// Render the current scene. The culling will be performed inside this method,
        /// because we need all meshes here to compute the shadow maps.
        /// </summary>
        /// <param name="camera">Current camera</param>
        /// <param name="visibleLights"></param>
        /// <param name="meshes">All meshes</param>
        /// <param name="sceneGraph"></param>
        /// <param name="particleSystems"></param>
        /// <param name="gameTime"></param>
        /// <param name="lights">Visible lights</param>
        /// <returns></returns>
        public RenderTarget2D RenderScene(Camera camera, BaseSceneGraph sceneGraph)
        {
            InstancingGroupManager.Reset();

            sceneGraph.DoPreFrameWork(camera.Frustum);


            _depthDownsampledThisFrame = false;
            _currentCamera             = camera;


            //compute the frustum corners for this camera
            ComputeFrustumCorners(camera);

            //this resets the free shadow maps
            _shadowRenderer.InitFrame();



            _visibleLights.Clear();
            sceneGraph.GetVisibleLights(camera.Frustum, _visibleLights);
            //sort lights, choose the shadow casters
            BuildLightEntries(camera);
            SelectShadowCasters();

            //generate all shadow maps
            GenerateShadows(camera, sceneGraph);


            //first of all, we must bind our GBuffer and reset all states
            GraphicsDevice.SetRenderTargets(_gBufferBinding);

            GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Stencil, Color.Black, 1.0f, 0);
            GraphicsDevice.BlendState        = BlendState.Opaque;
            GraphicsDevice.DepthStencilState = DepthStencilState.None;
            GraphicsDevice.RasterizerState   = RasterizerState.CullNone;

            //bind the effect that outputs the default GBuffer values
            _clearGBuffer.CurrentTechnique.Passes[0].Apply();
            //draw a full screen quad for clearing our GBuffer
            _quadRenderer.RenderQuad(GraphicsDevice, -Vector2.One, Vector2.One);

            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.RasterizerState   = RasterizerState.CullCounterClockwise;

            //select the visible meshes
            CullVisibleMeshes(camera, sceneGraph);

            //now, render them to the G-Buffer
            RenderToGbuffer(camera);

            //resolve our GBuffer and render the lights
            //clear the light buffer with black
            GraphicsDevice.SetRenderTargets(_lightAccumBinding);
            //dont be fooled by Color.Black, as its alpha is 255 (or 1.0f)
            GraphicsDevice.Clear(new Color(0, 0, 0, 0));

            //dont use depth/stencil test...we dont have a depth buffer, anyway
            GraphicsDevice.DepthStencilState = DepthStencilState.None;
            GraphicsDevice.RasterizerState   = RasterizerState.CullCounterClockwise;

            //draw using additive blending.
            //At first I was using BlendState.additive, but it seems to use alpha channel for modulation,
            //and as we use alpha channel as the specular intensity, we have to create our own blend state here

            GraphicsDevice.BlendState = _lightAddBlendState;

            RenderLights(camera);

            //reconstruct each object shading, using the light texture as input (and another specific parameters too)
            GraphicsDevice.SetRenderTarget(_outputTexture);
            GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Stencil | ClearOptions.Target, Color.Black, 1.0f, 0);
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState        = BlendState.Opaque;
            GraphicsDevice.RasterizerState   = RasterizerState.CullCounterClockwise;

            //reconstruct the shading, using the already culled list
            ReconstructShading(camera);
            //render objects that doesn't need the lightbuffer information, such as skyboxes, pure reflective meshes, etc
            DrawOpaqueObjects(camera);
            //draw objects with transparency
            DrawBlendObjects(camera);

            //draw SSAO texture. It's not correct to do it here, because ideally the SSAO should affect only
            //the ambient light, but it looks good this way

            //unbind our final buffer and return it
            GraphicsDevice.SetRenderTarget(null);

            return(_outputTexture);
        }