public static void Initialize(GameContext context) { ScreenBuffer = RenderTargetFactory.Create(context.Graphics.GraphicsDevice, context.Window.ClientBounds.Width, context.Window.ClientBounds.Height); DepthBuffer = RenderTargetFactory.Create(context.Graphics.GraphicsDevice, context.Window.ClientBounds.Width, context.Window.ClientBounds.Height); // Forcibly clear the targets to make them transparent. Under at least Linux, // the textures aren't initialized to anything, so they contain garbage graphics // data. context.Graphics.GraphicsDevice.SetRenderTarget(ScreenBuffer); context.Graphics.GraphicsDevice.Clear(Color.Transparent); context.Graphics.GraphicsDevice.SetRenderTarget(DepthBuffer); context.Graphics.GraphicsDevice.Clear(Color.Transparent); context.Graphics.GraphicsDevice.SetRenderTarget(null); }
public GraphicsContext(Lazy <IFileStore> files, IInputContext input) { var deviceManager = new DeviceManager(); DeviceManager = deviceManager; TextureResourceManager = new TextureResourceManager(deviceManager, files); TextureSamplerManager = new TextureSamplerManager(deviceManager); MaterialManager = new MaterialManager(this); BlendStateManager = new BlendStateManager(deviceManager); RasterizerStateManager = new RasterizerStateManager(deviceManager); RenderTargetFactory = new RenderTargetFactory(this, input); VertexBufferManagerFactory = new VertexBufferManagerFactory(deviceManager); IndexBufferManagerFactory = new IndexBufferManagerFactory(deviceManager); ConstantBufferManagerFactory = new ConstantBufferManagerFactory(deviceManager); }
private static void RenderTilesToTexture(RenderTask task, GameTime gt, GameContext context) { /* Our world is laid out in memory in terms of X / Y, but * we are rendering isometric, which means that the rendering * order for tiles must be like so: * * North * 1 3 5 9 13 19 25 * 2 6 10 14 20 26 32 * 4 8 15 21 27 33 37 * East 7 12 18 28 34 38 42 West * 11 17 24 31 39 43 45 * 16 23 30 36 41 46 48 * 22 29 35 40 44 47 49 * South * * We also need to account for situations where the user rotates * the isometric view. */ /* * North * 0 0.5 1 1.5 2 2.5 3 * -0.5 0 0.5 1 1.5 2 2.5 * -1 -0.5 0 0.5 1 1.5 2 * East -1.5 -1 -0.5 0 0.5 1 1.5 West * -2 -1.5 -1 -0.5 0 0.5 1 * -2.5 -2 -1.5 -1 -0.5 0 0.5 * -3 -2.5 -2 -1.5 -1 -0.5 0 * South * * v = (x - y) / 2.0 */ int DEBUG_ZOFFSET = 0;//TileIsometricifier.TILE_CUBE_HEIGHT * Settings.ChunkDepth - 200; if (m_CurrentRenderState == null) { RenderState rs = new RenderState(); rs.ZTop = Chunk.Depth; rs.ZBottom = 0; rs.ChunkTarget = RenderTargetFactory.Create( m_GraphicsDevice, TileIsometricifier.TILE_TOP_WIDTH * Chunk.Width, TileIsometricifier.TILE_TOP_HEIGHT * Chunk.Width + TileIsometricifier.TILE_CUBE_HEIGHT * Chunk.Depth + TileIsometricifier.CHUNK_HEIGHT_ALLOWANCE, true, SurfaceFormat.Bgra5551, DepthFormat.None); rs.ChunkDepthMap = RenderTargetFactory.Create( m_GraphicsDevice, TileIsometricifier.TILE_TOP_WIDTH * Chunk.Width, TileIsometricifier.TILE_TOP_HEIGHT * Chunk.Width + TileIsometricifier.TILE_CUBE_HEIGHT * Chunk.Depth + TileIsometricifier.CHUNK_HEIGHT_ALLOWANCE, true, SurfaceFormat.Bgra5551, DepthFormat.None); FilteredConsole.WriteLine(FilterCategory.GraphicsMemoryUsage, "Allocated textures for chunk " + task.Chunk.X + ", " + task.Chunk.Y + ", " + task.Chunk.Z + "."); m_GraphicsDevice.SetRenderTarget(rs.ChunkTarget); if (FilteredFeatures.IsEnabled(Feature.DebugChunkBackground)) { Color c = new Color( (float)m_DebugRandomizer.NextDouble(), (float)m_DebugRandomizer.NextDouble(), (float)m_DebugRandomizer.NextDouble() ); m_GraphicsDevice.Clear(ClearOptions.Target, c, 1.0f, 0); } else { m_GraphicsDevice.Clear(ClearOptions.Target, Color.Transparent, 1.0f, 0); } rs.ChunkDepthMapCleared = false; rs.SpriteBatch = new SpriteBatch(m_GraphicsDevice); rs.CurrentZ = rs.ZBottom; rs.RenderTask = task; rs.CellRenderOrder = GetCellRenderOrder(RenderToNE); rs.RenderMode = 0; m_CurrentRenderState = rs; } if (m_CurrentRenderState.RenderMode == 0 /* chunk texture */) { m_GraphicsDevice.SetRenderTarget(m_CurrentRenderState.ChunkTarget); m_CurrentRenderState.SpriteBatch.Begin(SpriteSortMode.Immediate, null); int count = 0; int zcount = 0; while (m_CurrentRenderState.CurrentZ < m_CurrentRenderState.ZTop && gt.ElapsedGameTime.TotalMilliseconds < Performance.RENDERING_MILLISECONDS) { int z = m_CurrentRenderState.CurrentZ; int rcx = TileIsometricifier.TILE_TOP_WIDTH * Chunk.Width / 2 - TileIsometricifier.TILE_TOP_WIDTH / 2; int rcy = TileIsometricifier.TILE_CUBE_HEIGHT * Chunk.Depth + TileIsometricifier.TILE_TOP_HEIGHT * Chunk.Width / 2 - DEBUG_ZOFFSET; int rw = TileIsometricifier.TILE_TOP_WIDTH; int rh = TileIsometricifier.TILE_TOP_HEIGHT / 2; for (int i = 0; i < m_CurrentRenderState.CellRenderOrder.Length; i++) { // Calculate the X / Y of the tile in the grid. int x = m_CurrentRenderState.CellRenderOrder[i] % RenderWidth; int y = m_CurrentRenderState.CellRenderOrder[i] / RenderWidth; // Calculate the render position on screen. int rx = rcx + (int)((x - y) / 2.0 * rw); int ry = rcy + (x + y) * rh - (rh / 2 * (RenderWidth + RenderHeight)) - (z * TileIsometricifier.TILE_CUBE_HEIGHT); Block b = task.Chunk.m_Blocks[x, y, z]; if (b == null) { if (FilteredFeatures.IsEnabled(Feature.DebugChunkTiles)) { m_CurrentRenderState.SpriteBatch.Draw( task.Textures["tiles.grass"], new Vector2(rx, ry), Color.White ); } continue; } Tile t = b.Tile; if (t.Image == null) { if (FilteredFeatures.IsEnabled(Feature.DebugChunkTiles)) { m_CurrentRenderState.SpriteBatch.Draw( task.Textures["tiles.dirt"], new Vector2(rx, ry), Color.White ); } continue; } Color col = new Color(1f, 1f, 1f, 1f).ToPremultiplied(); if (task.Chunk.X == 0 && task.Chunk.Y == 0 && x == 0 && y == 0) { col = new Color(1f, 0f, 0f, 1f).ToPremultiplied(); } if (FilteredFeatures.IsEnabled(Feature.DebugChunkTiles)) { m_CurrentRenderState.SpriteBatch.Draw( task.Textures[t.Image], new Vector2(rx, ry), col ); } if (FilteredFeatures.IsEnabled(Feature.RenderCellTops)) { m_CurrentRenderState.SpriteBatch.Draw( task.Textures[t.Image + ".isometric.top"], new Rectangle(rx, ry, TileIsometricifier.TILE_TOP_WIDTH, TileIsometricifier.TILE_TOP_HEIGHT), null, col, 0, new Vector2(0, 0), SpriteEffects.None, 0 // TODO: Use this to correct rendering artifacts. ); } if (FilteredFeatures.IsEnabled(Feature.RenderCellSides)) { m_CurrentRenderState.SpriteBatch.Draw( task.Textures[t.Image + ".isometric.sideL"], new Rectangle(rx, ry + TileIsometricifier.TILE_TOP_HEIGHT / 2, TileIsometricifier.TILE_SIDE_WIDTH, TileIsometricifier.TILE_SIDE_HEIGHT), null, col, 0, new Vector2(0, 0), SpriteEffects.None, 0 // TODO: Use this to correct rendering artifacts. ); m_CurrentRenderState.SpriteBatch.Draw( task.Textures[t.Image + ".isometric.sideR"], new Rectangle(rx + TileIsometricifier.TILE_TOP_WIDTH / 2, ry + TileIsometricifier.TILE_TOP_HEIGHT / 2, TileIsometricifier.TILE_SIDE_WIDTH, TileIsometricifier.TILE_SIDE_HEIGHT), null, col, 0, new Vector2(0, 0), SpriteEffects.None, 0 // TODO: Use this to correct rendering artifacts. ); } count++; } m_CurrentRenderState.CurrentZ++; zcount++; } FilteredConsole.WriteLine(FilterCategory.OptimizationTiming, "Rendered " + zcount + " levels, " + count + " cells to texture target in " + gt.ElapsedGameTime.Milliseconds + "ms."); m_CurrentRenderState.SpriteBatch.End(); m_GraphicsDevice.SetRenderTarget(null); } else if (m_CurrentRenderState.RenderMode == 1 /* depth map */ && FilteredFeatures.IsEnabled(Feature.IsometricOcclusion)) { m_GraphicsDevice.SetRenderTarget(m_CurrentRenderState.ChunkDepthMap); if (!m_CurrentRenderState.ChunkDepthMapCleared) { m_CurrentRenderState.SpriteBatch.Begin(SpriteSortMode.Immediate, null); m_GraphicsDevice.Clear(ClearOptions.Target, Color.Transparent, 1.0f, 0); m_CurrentRenderState.SpriteBatch.End(); m_CurrentRenderState.ChunkDepthMapCleared = true; } BlendState bs = new BlendState(); bs.AlphaBlendFunction = BlendFunction.Max; bs.AlphaSourceBlend = Blend.One; bs.AlphaDestinationBlend = Blend.One; bs.ColorBlendFunction = BlendFunction.Max; bs.ColorSourceBlend = Blend.One; bs.ColorDestinationBlend = Blend.One; m_CurrentRenderState.SpriteBatch.Begin(SpriteSortMode.Immediate, bs, null, null, null, context.Effects["IsometricDepthMap"]); context.Effects["IsometricDepthMap"].Parameters["RotationMode"].SetValue(RenderToNE); context.Effects["IsometricDepthMap"].CurrentTechnique.Passes[0].Apply(); int count = 0; int zcount = 0; while (m_CurrentRenderState.CurrentZ < m_CurrentRenderState.ZTop && gt.ElapsedGameTime.TotalMilliseconds < Performance.RENDERING_MILLISECONDS) { int z = m_CurrentRenderState.CurrentZ; int rcx = TileIsometricifier.TILE_TOP_WIDTH * Chunk.Width / 2 - TileIsometricifier.TILE_TOP_WIDTH / 2; int rcy = TileIsometricifier.TILE_CUBE_HEIGHT * Chunk.Depth + TileIsometricifier.TILE_TOP_HEIGHT * Chunk.Width / 2 - DEBUG_ZOFFSET; int rw = TileIsometricifier.TILE_TOP_WIDTH; int rh = TileIsometricifier.TILE_TOP_HEIGHT / 2; for (int i = 0; i < m_CurrentRenderState.CellRenderOrder.Length; i++) { // Calculate the X / Y of the tile in the grid. int x = m_CurrentRenderState.CellRenderOrder[i] % RenderWidth; int y = m_CurrentRenderState.CellRenderOrder[i] / RenderWidth; // Calculate the "depth" of the tile. int depth = x + y + z; // Calculate the render position on screen. int rx = rcx + (int)((x - y) / 2.0 * rw); int ry = rcy + (x + y) * rh - (rh / 2 * (RenderWidth + RenderHeight)) - (z * TileIsometricifier.TILE_CUBE_HEIGHT); Block b = task.Chunk.m_Blocks[x, y, z]; if (b == null) { continue; } Tile t = b.Tile; if (t.Image == null) { continue; } context.Effects["IsometricDepthMap"].Parameters["CellDepth"].SetValue((float)Math.Min(depth / 255f, 1.0f)); context.Effects["IsometricDepthMap"].CurrentTechnique.Passes[0].Apply(); m_CurrentRenderState.SpriteBatch.Draw( task.Textures[t.Image + ".isometric.top"], new Rectangle(rx, ry, TileIsometricifier.TILE_TOP_WIDTH, TileIsometricifier.TILE_TOP_HEIGHT), null, Color.White, 0, new Vector2(0, 0), SpriteEffects.None, 0 ); m_CurrentRenderState.SpriteBatch.Draw( task.Textures[t.Image + ".isometric.sideL"], new Rectangle(rx, ry + 12, TileIsometricifier.TILE_SIDE_WIDTH, TileIsometricifier.TILE_SIDE_HEIGHT), null, Color.White, 0, new Vector2(0, 0), SpriteEffects.None, 0 ); m_CurrentRenderState.SpriteBatch.Draw( task.Textures[t.Image + ".isometric.sideR"], new Rectangle(rx + 16, ry + 12, TileIsometricifier.TILE_SIDE_WIDTH, TileIsometricifier.TILE_SIDE_HEIGHT), null, Color.White, 0, new Vector2(0, 0), SpriteEffects.None, 0 ); count++; } m_CurrentRenderState.CurrentZ++; zcount++; } FilteredConsole.WriteLine(FilterCategory.OptimizationTiming, "Rendered " + zcount + " levels, " + count + " cells to texture target in " + gt.ElapsedGameTime.TotalMilliseconds + "ms."); m_CurrentRenderState.SpriteBatch.End(); m_GraphicsDevice.SetRenderTarget(null); } if (m_CurrentRenderState.CurrentZ == m_CurrentRenderState.ZTop) { if (m_CurrentRenderState.RenderMode < 1) { m_CurrentRenderState.CurrentZ = m_CurrentRenderState.ZBottom; m_CurrentRenderState.RenderMode++; } else { m_CurrentRenderState.RenderTask.Result = m_CurrentRenderState.ChunkTarget; m_CurrentRenderState.RenderTask.DepthMap = m_CurrentRenderState.ChunkDepthMap; m_CurrentRenderState.RenderTask.HasResult = true; m_CurrentRenderState = null; } } }
public static void Isometricify(string name, GameContext context) { Texture2D original = context.Textures[name]; #region Top Tile Generation // First rotate. int rotSize = (int)Math.Sqrt(Math.Pow(original.Width, 2) + Math.Pow(original.Height, 2)); RenderTarget2D rotatedTarget = RenderTargetFactory.Create( context.Graphics.GraphicsDevice, 31, 31, true, context.Graphics.GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24); context.Graphics.GraphicsDevice.SetRenderTarget(rotatedTarget); context.Graphics.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Transparent, 1.0f, 0); context.SpriteBatch.Begin(); context.SpriteBatch.Draw( original, new Rectangle(0, 0, rotSize, rotSize), null, Color.White, MathHelper.ToRadians(45), //new Vector2(TILE_LEFT, TILE_TOP), new Vector2(-8, 8), SpriteEffects.None, 0); context.SpriteBatch.End(); context.Graphics.GraphicsDevice.SetRenderTarget(null); // Then squash. RenderTarget2D squashedTarget = RenderTargetFactory.Create( context.Graphics.GraphicsDevice, TILE_TOP_WIDTH, TILE_TOP_HEIGHT, true, context.Graphics.GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24); context.Graphics.GraphicsDevice.SetRenderTarget(squashedTarget); context.Graphics.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Transparent, 1.0f, 0); context.SpriteBatch.Begin(); context.SpriteBatch.Draw( rotatedTarget, new Rectangle(0, 0, TILE_TOP_WIDTH, TILE_TOP_HEIGHT), new Rectangle(0, 0, rotatedTarget.Width, rotatedTarget.Height), Color.White ); context.SpriteBatch.End(); context.Graphics.GraphicsDevice.SetRenderTarget(null); #endregion #region Side Tile Generation // Skew with matrix. Matrix m = Matrix.Identity; m.M11 = 1.0f; m.M12 = 0.7f; m.M21 = 0.0f; m.M22 = 1.0f; RenderTarget2D shearedLeftTarget = RenderTargetFactory.Create( context.Graphics.GraphicsDevice, TILE_SIDE_WIDTH, TILE_SIDE_HEIGHT, true, context.Graphics.GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24); context.Graphics.GraphicsDevice.SetRenderTarget(shearedLeftTarget); context.Graphics.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Transparent, 1.0f, 0); context.SpriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, null, m); context.SpriteBatch.Draw( original, new Rectangle(0, 0, original.Width * SKEW_SCALE, original.Height * SKEW_SCALE), null, new Color(63, 63, 63) ); context.SpriteBatch.End(); context.Graphics.GraphicsDevice.SetRenderTarget(null); // Skew with matrix. m = Matrix.Identity; m.M11 = 1.0f; m.M12 = -0.7f; m.M21 = 0.0f; m.M22 = 1.0f; RenderTarget2D shearedRightTarget = RenderTargetFactory.Create( context.Graphics.GraphicsDevice, TILE_SIDE_WIDTH, TILE_SIDE_HEIGHT, true, context.Graphics.GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24); context.Graphics.GraphicsDevice.SetRenderTarget(shearedRightTarget); context.Graphics.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Transparent, 1.0f, 0); context.SpriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, null, m); context.SpriteBatch.Draw( original, new Rectangle(0, (int)(original.Height * SKEW_MAGIC), original.Width * SKEW_SCALE, original.Height * SKEW_SCALE), null, new Color(127, 127, 127) ); context.SpriteBatch.End(); context.Graphics.GraphicsDevice.SetRenderTarget(null); #endregion context.Textures.Add(name + ".isometric.top", squashedTarget); context.Textures.Add(name + ".isometric.sideL", shearedLeftTarget); context.Textures.Add(name + ".isometric.sideR", shearedRightTarget); }