2
\$\begingroup\$

I want to render big, izometric 2d map (using ortho projection). I am using OpenTK and aiming for OpenGL 3.3. Perfect option would be to draw 512x512 map of tiles, which is 262144 blocks -> 524288 triangles. The map is divided into chunks, mostly static but animations would be nice. I was trying to do this in some ways already:

1. Using Geometry Shader to generate chunk. I know its not what GS is for, but it seems to be fast. And it was. Problem is, that i have to send all blocks data to GPU every frame, becouse there is no way I can think of to buffer this on GPU (Uniform Buffers have very restricted limits for reasons I dont understand so I can't use it). That created a bottleneck on dedicated GPUs, althought with integrated GPUs for obvious reasons it worked well.

2. Calculating position of every block once, store it on VBO (UVs and Vertices) and than draw with BindVertexArray and DrawArrays. The problem was for 256x256 map integrated GPU was using >1500 MB for some reason and was giving me Out of memory. Same for 512x512 with dedicated. According with my calculations it should take only 4 MB (524288 floats) but it didn't. Even for small numbers like 144x144 blocks it was drawing with ~20FPS...

3. (Done only early, with MonoGame) Render each Chunk to texture (what with FBO on OpenGL?) and than draw needed textures to the screen. But that is ridiculous memory wise and wont work for higher textures resolution.

At this moment Im out of ideas, searching web didnt get me any reasonable solution. I wanted to see how its done in OpenTTD since its open source (its doing exactly what I need), but I have not understand much from its bizzare and complicated code.


As requested, code to point 2 is included.

NChunk objects keept in flat array "chunks".

private static float[] VDataBlock = new float[] {
                -1.0f,  0.0f, // 0
                 1.0f,  1.0f, // 2
                 1.0f, -1.0f, // 4
                 3.0f,  0.0f  // 6
            };   


public class NChunk
        {
            public float[] vertices = new float[CHUNK_SIZE * CHUNK_SIZE * 8];
            public float[] UVs = new float[CHUNK_SIZE * CHUNK_SIZE * 8];
            public int[] buffers = new int[CHUNK_SIZE * CHUNK_SIZE];

            public NChunk()
            {
                float x, y;
                for (int k = 0; k < CHUNK_SIZE; k++)
                {
                    for (int l = 0; l < CHUNK_SIZE; l++)
                    {
                        x = (l - k) * 1.939f;
                        y = (l + k) * 0.969f;

                        int w = (k * 8) + (l * 8 * CHUNK_SIZE);

                        vertices[w + 0] = VDataBlock[0] + x;
                        vertices[w + 1] = VDataBlock[1] + y;
                        vertices[w + 2] = VDataBlock[2] + x;
                        vertices[w + 3] = VDataBlock[3] + y;
                        vertices[w + 4] = VDataBlock[4] + x;
                        vertices[w + 5] = VDataBlock[5] + y;
                        vertices[w + 6] = VDataBlock[6] + x;
                        vertices[w + 7] = VDataBlock[7] + y;

                        UVs[w + 0] = 0.0f;
                        UVs[w + 1] = 0.5f;
                        UVs[w + 2] = 0.5f;
                        UVs[w + 3] = 1.0f;
                        UVs[w + 4] = 0.5f;
                        UVs[w + 5] = 0.0f;
                        UVs[w + 6] = 1.0f;
                        UVs[w + 7] = 0.5f;

                        int bh = GL.GenVertexArray();
                        GL.BindVertexArray(bh);
                        GL.EnableVertexAttribArray(0);
                        GL.EnableVertexAttribArray(1);

                        Util.PrintGLError();
                        int wvbh = GL.GenBuffer();
                        GL.BindBuffer(BufferTarget.ArrayBuffer, wvbh);
                        float[] blockVertices = new float[8];
                        Array.Copy(vertices, w, blockVertices, 0, 8);
                        GL.BufferData<float>(BufferTarget.ArrayBuffer, new IntPtr(sizeof(float) * 8), blockVertices, BufferUsageHint.StaticDraw);
                        Util.PrintGLError();
                        GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 0, IntPtr.Zero);
                        Util.PrintGLError();

                        int wuvspb = GL.GenBuffer();
                        GL.BindBuffer(BufferTarget.ArrayBuffer, wuvspb);
                        float[] blockUVs = new float[8];
                        Array.Copy(UVs, w, blockUVs, 0, 8);
                        GL.BufferData<float>(BufferTarget.ArrayBuffer, new IntPtr(sizeof(float) * 8), blockUVs, BufferUsageHint.StaticDraw);
                        Util.PrintGLError();
                        GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 0, IntPtr.Zero);
                        Util.PrintGLError();



                        buffers[k * CHUNK_SIZE + l] = bh;
                    }
                }
            }
        }


        private static void RenderChunk(NChunk c)
    {
        for (int k = 0; k < CHUNK_SIZE; k++)
        {
            for (int l = 0; l < CHUNK_SIZE; l++)
            {
                GL.BindVertexArray(c.buffers[k * CHUNK_SIZE + l]);
                GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
            }
        }
\$\endgroup\$

closed as off-topic by Josh Mar 13 '14 at 17:26

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions about debugging a problem in your project must present a concise selection of code and context so as to allow a reader to diagnose the issue without needing to read all of your code or to engage in extensive back-and-forth dialog. For more information, see this meta thread." – Josh
If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\begingroup\$ Why its still on hold? What do I have to do? \$\endgroup\$ – Mateusz Krzaczek Mar 13 '14 at 21:17
  • \$\begingroup\$ it needs to go through the reopen vote process. If the votes go your way, it will be reopened. \$\endgroup\$ – Seth Battin Mar 13 '14 at 21:35