Повышение производительности рисования с шестигранной сеткой - PullRequest
2 голосов
/ 06 июня 2011

Я работаю над своей самой первой игрой openGL, вдохновленной игрой "Greed Corp" в сети PlayStation. Это пошаговая стратегия, основанная на гекс-сетке. Каждая шестигранная плитка имеет свою высоту и текстуру.

В настоящее время я рисую шестиугольник, основываясь на некоторых примерах и учебных пособиях, которые я прочитал. Вот мой шестнадцатеричный класс:

public class HexTile
{
    private float height;

    private int[] textures = new int[1];

    private float vertices[] = {     0.0f,   0.0f, 0.0f,    //center
                                     0.0f,   1.0f, 0.0f,    // top
                                    -1.0f,   0.5f, 0.0f,    // left top
                                    -1.0f,  -0.5f, 0.0f,    // left bottom
                                     0.0f,  -1.0f, 0.0f,    // bottom
                                     1.0f,  -0.5f, 0.0f,    // right bottom
                                     1.0f,  0.5f, 0.0f,     // right top
    };

    private short[] indices = {      0, 1, 2, 3, 4, 5, 6, 1};

    //private float texture[] = { };

    private FloatBuffer vertexBuffer;
    private ShortBuffer indexBuffer;
    //private FloatBuffer textureBuffer;    

    public HexTile()
    {
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
        vbb.order(ByteOrder.nativeOrder());
        vertexBuffer = vbb.asFloatBuffer();
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);

        ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
        ibb.order(ByteOrder.nativeOrder());
        indexBuffer = ibb.asShortBuffer();
        indexBuffer.put(indices);
        indexBuffer.position(0);

        /*ByteBuffer tbb = ByteBuffer.allocateDirect(texture.length * 4);
        tbb.order(ByteOrder.nativeOrder());
        textureBuffer = tbb.asFloatBuffer();
        textureBuffer.put(texture);
        textureBuffer.position(0);*/
    }

    public void setHeight(float h)
    {
        height = h;
    }
    public float getHeight()
    {
        return height;
    }

    public void draw(GL10 gl)
    {
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        //gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

        gl.glDrawElements(GL10.GL_TRIANGLE_FAN, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
    }

    public void loadGLTexture(GL10 gl, Context context)
    {
        textures[0] = -1;
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.hex);

        while(textures[0] <= 0)
            gl.glGenTextures(1, textures, 0); 

        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

        bitmap.recycle();
    }
}

В каждом кадре я перебираю все видимые плитки, чтобы нарисовать их, это будет 11 * 9 плиток МАКС. Это, однако, снижает мою частоту кадров до 38, и это даже без рисования текстур на них, только плоские шестиугольники.

Теперь я пытаюсь понять, как повысить производительность. Я полагал, что рисование всей сетки за один раз может быть быстрее, но я понятия не имею, как это сделать, поскольку каждая плитка может иметь разную высоту и, скорее всего, будет иметь другую текстуру, чем соседняя плитка.

Я бы очень признателен за помощь в этом, потому что я хотел бы начать с настоящей игры ^. ^

Ответы [ 2 ]

1 голос
/ 06 июня 2011

Предполагая, что ваша шестнадцатеричная сетка статична, вы можете просто прокрутить все свои шестиугольники один раз, сгенерировать их геометрию и добавить все в одну (или более, если у вас более 2 ^ 16 вершин) большую VBO, которую вы можете нарисовать в одномgo.

Что касается текстур, вы можете использовать текстурный атлас .

0 голосов
/ 30 декабря 2011

В настоящее время я также изучаю OpenGL, я создал одно приложение Android OpenGL под названием «Облачный поток», в котором обнаружил похожие проблемы с производительностью.

Как общий ответ на проблемы производительности, есть несколько вещей, которые могут помочь. Конвейер Vertex для графики на аппаратном уровне, очевидно, более эффективен, когда передается большее количество вершин одновременно. Вызов glVertexPointer для каждой шестнадцатеричной плитки не так эффективен, как вызов его один раз с вершинами всех плиток.

Это усложняет кодирование, поскольку вы фактически рисуете все свои плитки одновременно, но, похоже, это немного ускоряет процесс. В моем приложении все облака нарисованы за один вызов.

Другие возможности - сохранить позиции Vertice в VBO, что я считаю довольно хитрым, по крайней мере, при попытке обслуживать пользователей 2.1. В наши дни все может быть проще, я не уверен. При этом идея состоит в том, чтобы сохранить массив Vertice для вашей плитки в видеопамяти, и вы получите указатель, как вы делаете с вашими текстурами. Как вы можете себе представить, не посылая буфер Vertice Array Buffer в каждом кадре, вы немного ускоряете процесс прорисовки каждой плитки. Даже если все не статично, это хороший подход, так как я сомневаюсь, что все меняется для каждого кадра.

Еще одно предложение, с которым я сталкивался в Интернете, - это использовать Short вместо Float для своих вершин. А затем изменить масштаб готового рендеринга, чтобы получить желаемый размер. Это уменьшит размер ваших вершин и немного ускорит процесс ... не так много, но все же стоит попробовать, я бы сказал.

И последнее, что я хотел бы добавить, если вы в конечном итоге используете какую-либо прозрачность ... имейте в виду, что вы должны рисовать спереди, чтобы она работала, что также влияет на производительность. Если вы рисуете спереди назад, движок рендеринга автоматически знает, что не нужно рисовать, когда координаты не видны ... рисование спереди означает, что все нарисовано. Помните об этом и всегда старайтесь рисовать спереди назад, когда это возможно.

Удачи в вашей игре, я хотел бы знать, как вы поживаете ... Я только начинаю свою игру, и я очень рад начать. Если вы еще не сталкивались с этим ... Я думаю, что это стоит прочитать. http://www.codeproject.com/KB/graphics/hexagonal_part1.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...