private void PrepareLightsGBuffer(Scene scene) { _graphicsDevice.SetRenderTargets(_lightNormalTarget, _lightDepthTarget); _graphicsDevice.Clear(Color.White); _graphicsDevice.DepthStencilState = DepthStencilState.Default; _graphicsDevice.BlendState = BlendState.Opaque; _lightDepthNormalEffect.Parameters["View"].SetValue(scene.CameraManager.Camera.View); _lightDepthNormalEffect.Parameters["Projection"].SetValue(scene.CameraManager.Camera.Projection); // draw all objects that should be lit by a point light foreach (IDrawable item in scene.Unlayered) item.Draw(_lightDepthNormalEffect); foreach (Layer layer in scene.Layers) foreach (IDrawable item in layer.Drawables) item.Draw(_lightDepthNormalEffect); }
private void PrepareShadowDepthBuffer(Scene scene) { // make sure that there is only one shadow casting light if (scene.ShadowCastingLights.Count > 1) throw new ArgumentException( "SimpleSceneRenderer cannot render scenes that have more than one shadow casting light."); _graphicsDevice.SetRenderTarget(_shadowDepthTarget); _graphicsDevice.Clear(Color.White); _graphicsDevice.BlendState = BlendState.Opaque; if (scene.ShadowCastingLights.Count == 0) return; Light shadowCaster = scene.ShadowCastingLights.First(); Matrix shadowView = Matrix.CreateLookAt(shadowCaster.Position, shadowCaster.Direction, Vector3.Up); Matrix shadowProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 1, ShadowNearPlane, ShadowFarPlane); _shadowDepthEffect.Parameters["View"].SetValue(shadowView); _shadowDepthEffect.Parameters["Projection"].SetValue(shadowProjection); _graphicsDevice.RasterizerState = RasterizerState.CullNone; _graphicsDevice.DepthStencilState = DepthStencilState.None; // draw all objects that cast shadows foreach (IDrawable item in scene.Unlayered) item.Draw(_shadowDepthEffect); foreach (Layer layer in scene.Layers) foreach (IDrawable item in layer.Drawables) item.Draw(_shadowDepthEffect); }
private void DrawPointLights(Scene scene) { Matrix viewProjection = scene.CameraManager.Camera.View*scene.CameraManager.Camera.Projection; Matrix invViewProjection = Matrix.Invert(viewProjection); _lightPointEffect.Parameters["InvViewProjection"].SetValue(invViewProjection); _graphicsDevice.SetRenderTarget(_lightPointTarget); _graphicsDevice.Clear(Color.Black); _graphicsDevice.BlendState = BlendState.Additive; _graphicsDevice.DepthStencilState = DepthStencilState.None; _lightPointEffect.Parameters["DepthTexture"].SetValue(_lightDepthTarget); _lightPointEffect.Parameters["NormalTexture"].SetValue(_lightNormalTarget); // draw a sphere for each point light in the scene foreach (Light light in scene.SimpleLights) { if (light.Type != LightType.Point) throw new ArgumentException("SimpleSceneRenderer can only render point lights."); Matrix wvp = Matrix.CreateScale(light.Attenuation)*Matrix.CreateTranslation(light.Position)* viewProjection; _lightPointEffect.Parameters["WorldViewProjection"].SetValue(wvp); _lightPointEffect.Parameters["CameraPosition"].SetValue(scene.CameraManager.Camera.Position); _lightPointEffect.Parameters["LightColor"].SetValue(light.Color.ToVector3()); _lightPointEffect.Parameters["LightPosition"].SetValue(light.Position); _lightPointEffect.Parameters["LightAttenuation"].SetValue(light.Attenuation); float dist = Vector3.Distance(scene.CameraManager.Camera.Position, light.Position); if (dist < light.Attenuation) _graphicsDevice.RasterizerState = RasterizerState.CullClockwise; _pointLightSphere.Meshes[0].Draw(); _graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; } }
private void DrawGeometry(Scene scene) { _graphicsDevice.BlendState = BlendState.Opaque; _graphicsDevice.DepthStencilState = DepthStencilState.Default; _graphicsDevice.SetRenderTarget(_sceneRenderTarget); _graphicsDevice.Clear(Color.Gray); _graphicsDevice.BlendState = BlendState.AlphaBlend; _graphicsDevice.RasterizerState = RasterizerState.CullNone; _sceneRenderEffect.Parameters["LightTexture"].SetValue(_lightPointTarget); _sceneRenderEffect.Parameters["AmbientColor"].SetValue(scene.Ambient.ToVector3()); _sceneRenderEffect.Parameters["View"].SetValue(scene.CameraManager.Camera.View); _sceneRenderEffect.Parameters["Projection"].SetValue(scene.CameraManager.Camera.Projection); if (RenderShadows && scene.ShadowCastingLights.Count != 0) { // TODO: use the matrices that have already been computed Light shadowCaster = scene.ShadowCastingLights.First(); Matrix shadowView = Matrix.CreateLookAt(shadowCaster.Position, shadowCaster.Direction, Vector3.Up); Matrix shadowProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 1, ShadowNearPlane, ShadowFarPlane); _sceneRenderEffect.Parameters["ShadowView"].SetValue(shadowView); _sceneRenderEffect.Parameters["ShadowProjection"].SetValue(shadowProjection); _sceneRenderEffect.Parameters["ShadowLightPosition"].SetValue(shadowCaster.Position); _sceneRenderEffect.Parameters["ShadowMap"].SetValue(_shadowDepthTarget); } // draw the non-layered geometry first (Z-buffer enabled) _graphicsDevice.DepthStencilState = DepthStencilState.Default; foreach (IDrawable item in scene.Unlayered) item.Draw(_sceneRenderEffect); // draw the layered geometry (back-to-front order, Z-buffer read-only) _graphicsDevice.DepthStencilState = DepthStencilState.DepthRead; foreach (Layer layer in scene.Layers) foreach (IDrawable item in layer.Drawables) item.Draw(_sceneRenderEffect); }
private RenderTarget2D DoPostprocessing(Scene scene) { RenderTarget2D current = _sceneRenderTarget; foreach (Postprocess p in scene.Postprocesses) { current = current == _sceneRenderTarget ? _postprocessRenderTarget : _sceneRenderTarget; _graphicsDevice.SetRenderTarget(current); p.Apply(); } // return the render target with the final scene return current; }
public void Render(Scene scene) { // Step 1: shadow depth buffer if (RenderShadows) PrepareShadowDepthBuffer(scene); // Step 2: point lights G-buffer (depth and normals) PrepareLightsGBuffer(scene); // Step 3: draw the point lights DrawPointLights(scene); // Step 4: draw the geometry (combining it with the lighting data) // Revert the blending and depth render states DrawGeometry(scene); // Step 5: do the postprocessing RenderTarget2D finalImage = DoPostprocessing(scene); // Step 6: blit the final image _graphicsDevice.SetRenderTarget(null); _spriteBatch.Begin(0, BlendState.Opaque, null, null, null, null); _spriteBatch.Draw(finalImage, new Rectangle(0, 0, _viewWidth, _viewHeight), Color.White); _spriteBatch.End(); }
/// <summary> /// Load graphics content for the game. /// </summary> public override void Activate(bool instancePreserved) { if (instancePreserved) { return; } if (_content == null) { _content = new ContentManager(ScreenManager.Game.Services, "Content"); } _sceneRenderer = new SimpleSceneRenderer(ScreenManager.GraphicsDevice, _content) { RenderShadows = false }; var pp = ScreenManager.GraphicsDevice.PresentationParameters; var aspectRatio = pp.BackBufferWidth/(float) pp.BackBufferHeight; _camera = new FreeCamera(SCENE_CENTER, MathHelper.ToRadians(45), aspectRatio, 0.1f, 1000.0f); _cameraManager = new CameraManager(_camera); _scene = new Scene {CameraManager = _cameraManager, Ambient = new Color(0.7f, 0.7f, 0.7f)}; var dirLight = new Light(LightType.Directional, Color.Red) { Direction = new Vector3(0.45f, -0.15f, 0.875f), Position = new Vector3(5.6f, 7.6f, 12.0f) }; _scene.ShadowCastingLights.Add(dirLight); InitializeScene(); // add the debug puzzleboard control int boardMargin = 15; int boardWidth = (pp.BackBufferWidth - 3*boardMargin)/3; int boardHeight = 5*boardWidth/7; var finder = new BoardLayoutFinder(); ProcessLayouts(finder); var board1 = new PuzzleBoard(6, 5) {Player = _player1}; board1.Randomize(); _puzzleBoard1 = new PuzzleBoardWidget(this, _content, new Point(boardMargin, boardMargin), new Point(boardWidth, boardHeight)); _puzzleBoard1.LayoutFinder = finder; _puzzleBoard1.Board = board1; _puzzleBoard1.LayoutAccepted += LayoutAccepted; var board2 = new PuzzleBoard(6, 5); board2.Player = _player2; board2.Randomize(); _puzzleBoard2 = new PuzzleBoardWidget(this, _content, new Point(pp.BackBufferWidth - boardWidth - 2*boardMargin, boardMargin), new Point(boardWidth, boardHeight)); _puzzleBoard2.LayoutFinder = finder; _puzzleBoard2.Board = board2; _puzzleBoard2.LayoutAccepted += LayoutAccepted; //_particleManager = new ParticleManager((Game)ScreenManager.Game); //_particleManager.AddSystem<DustParticleSystem>(DUST_PARTICLE_SYSTEM, 10, player1.InitialPosition.Z + 0.1f); // once the load has finished, we use ResetElapsedTime to tell the game's // timing mechanism that we have just finished a very long frame, and that // it should not try to catch up. ScreenManager.Game.ResetElapsedTime(); }