Android OpenGL ES простая проблема производительности генератора плитки - PullRequest
2 голосов
/ 25 января 2010

после этого вопроса: Лучший подход для старой школы 2D Zelda-подобной игры

Благодаря предыдущим ответам и с большим вдохновением от http://insanitydesign.com/wp/projects/nehe-android-ports/ я начал создавать простой Tile Generator для моего простого 2D-проекта, похожего на zelda.

Теперь я могу сгенерировать карту с той же текстурированной плиткой, используя 2 для (..) ибрированных итераций для рисования горизонтальных и вертикальных плиток, и получил несколько базовых слушателей ввода ключа DPAD для прокрутки по осям x и y. *

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

При попытке построить карту 10х10 прокрутка выполняется нормально и гладко.

При попытке с 50x50 все ухудшается, а с 100x100 его путь неприемлем.

Есть ли способ только сказать OpenGL визуализировать «видимую» часть моего набора карт и игнорировать скрытые тайлы? Я совершенно новичок в этом.

я использую

GLU.gluLookAt(gl, cameraPosX, cameraPosY, 10.0f,cameraPosX, cameraPosY, 0.0f, 0.0f, 1.0f, 0.0f);

для установки камеры и точки обзора для ощущения в стиле 2D.

Любая помощь? :)

for (int j = 0; j < 10; j++) {

        for (int i = 0; i < 10; i++) {

            gl.glPushMatrix(); // Sauvegarde la matrice sur le stack

            //Bind the texture according to the set texture filter
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[filter]);
            //Set the face rotation
            gl.glFrontFace(GL10.GL_CW);
            //Enable texture state
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            //Enable vertex state
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            //Point to our vertex buffer
            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
            //point to our texture buff
            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
            //Draw the vertices as triangle strip
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
            //Disable the client state before leaving
            gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

            gl.glTranslatef(1.0f, 0.0f, 0.0f); // on avance d'une tile
        }
        // on va commencer a dessiner la 2e ligne
        gl.glPopMatrix(); // Rappelle la matrice sur le stack
        gl.glTranslatef(0.0f, -1.0f, 0.0f);
    }

Ответы [ 2 ]

3 голосов
/ 14 февраля 2010

Причина, по которой цикл замедляется, заключается в том, что он заставляет OpenGL выполнять много ненужной работы. Это связано с большим количеством избыточных изменений состояния.

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

Например, вы должны вызывать glBindTexture, только если вы хотите изменить используемую текстуру. Приведенный выше код снова и снова связывает одну и ту же текстуру во внутреннем цикле, что очень дорого. Точно так же вам не нужно включать и отключать текстурные координаты и массивы вершин во внутреннем цикле. Даже установка указателя координат текстуры и указателя вершины во внутреннем цикле не требуется, поскольку они не изменяются между последующими циклами.

Суть в том, что во внутреннем цикле вы должны только изменить перевод и вызвать glDrawArrays. Все остальное просто пожирает ресурсы.

Есть более продвинутые вещи, которые вы можете сделать, чтобы ускорить это еще больше. Фон мозаики можно нарисовать так, чтобы он вызывал только один вызов glDrawArrays (или glDrawElements). Если вас это интересует, вам следует использовать такие темы Google, как пакетная обработка и атласы текстур.

2 голосов
/ 25 января 2010

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

int cols = SCREEN_WIDTH / TILE_SIZE + 1;      // how many columns can fit on the screen
int rows = SCREEN_HEIGHT / TILE_SIZE + 1;     // haw many rows can fit on the screen
int firstVisibleCol = cameraPosX / TILE_SIZE; // first column we need to draw
int firstVisibleRow = cameraPosY / TILE_SIZE; // first row we need to draw

// and now the loop becomes
for (int j = firstVisibleRow; j < rows; j++) {
    for (int i = firstVisibleCol ; i < cols; i++) {
        ...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...