OpenGL ES - Как Batch Render 500+ частиц с различными альфа, вращениями и масштабами?

Я разрабатываю игру для iOS, в которой нужно будет визуализировать 500-800 частиц за раз. Я узнал, что это хорошая идея для пакетной визуализации многих спрайтов в OpenGL ES вместо вызова glDrawArrays(..) на каждом спрайте в игре, чтобы иметь возможность рендерить больше спрайтов без резкого снижения частоты кадров.

Мой вопрос: как мне сделать пакетную рендеринг 500+ частиц, которые имеют разные альфы, вращения и масштабы, но имеют один и тот же атлас текстуры? Акцент этого вопроса на различных альфа, вращений и масштабов для каждой частицы.

Я понимаю, что этот вопрос очень похож на Как нарисовать более 1000 частиц (с уникальным вращением, масштабом и альфа) в системе частиц iPhone OpenGL ES без замедления игры? однако этот вопрос не касается пакетного рендеринга. Прежде чем воспользоваться преимуществами объектов буфера вершин, я хочу разобраться в пакетном рендеринге в OpenGL ES с уникальными альфами, поворотами и масштабами (но с одинаковой текстурой). Поэтому, хотя я планирую в конечном итоге использовать VBO, сначала я хочу воспользоваться этим подходом.

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

РЕДАКТИРОВАТЬ Я использую OpenGL ES 1.1.

РЕДАКТИРОВАТЬ Ниже приведен пример кода того, как я рендерил каждую частицу в сцене. Предположим, что они используют одну и ту же текстуру, и эта текстура уже связана в OpenGL ES 1.1 до выполнения этого кода.

- (void) render {

    glPushMatrix();

    glTranslatef(translation.x, translation.y, translation.z);

    glRotatef(rotation.x, 1, 0, 0);
    glRotatef(rotation.y, 0, 1, 0);
    glRotatef(rotation.z, 0, 0, 1);

    glScalef(scale.x, scale.y, scale.z);

    // change alpha
    glColor4f(1.0, 1.0, 1.0, alpha);

    // glBindTexture(GL_TEXTURE_2D, texture[0]);

    glVertexPointer(2, GL_FLOAT, 0, texturedQuad.vertices);
    glEnableClientState(GL_VERTEX_ARRAY);


    glTexCoordPointer(2, GL_FLOAT, 0, texturedQuad.textureCoords);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glPopMatrix();
}

Кодовая альтернатива этому методу будет принята с благодарностью!

1 ответ

Решение

Одной из возможностей будет включение этих значений в массив атрибутов вершин - я думаю, что это лучший вариант. Если вы используете OpenGL ES 1.1 вместо 2.0, вы выбиты из этого метода. Массивы атрибутов вершин позволяют хранить значения в каждой вершине, в этом случае вы можете хранить альфы и повороты каждый в своем собственном массиве атрибутов и передавать их в шейдер с помощью glVertexAttribArray, Затем шейдер выполняет преобразование вращения и обработку цвета с помощью альфа-канала.

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

ПРИМЕЧАНИЕ. Вопрос, на который вы ссылаетесь, также рекомендует решение для массива.

РЕДАКТИРОВАТЬ: учитывая ваш код здесь OpenGL ES 1.0, вот решение с использованием glColorPointer:

// allocate buffers to store an array of all particle data
verticesBuffer = ... 
texCoordBuffer = ...
colorBuffer = ...

for (particle in allParticles)
{
  // Create matrix from rotation
  rotMatrix = matrix(particle.rotation.x, particle.rotation.y, particle.rotation.z)
  // Transform particle by matrix
  verticesBuffer[i] = particle.vertices * rotMatrix

  // copy other data
  texCoordBuffer[i] = particle.texCoords;
  colorBuffer[i] = color(1.0, 1.0, 1.0, particle.alpha);
}

glVertexPointer(verticesBuffer, ...)
glTexCoordPointer(texCoodBuffer, ...)
glColorPointer(colorBuffer, ...)

glDrawArrays(particleCount * 4, ...);

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

Другие вопросы по тегам