예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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;
                }
            }
        }
예제 #4
0
        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);
        }