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); }
/// <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); }