Эффективный способ рисования в OpenGL ES

В моем приложении я рисую много кубов через OpenGL ES Api. Все кубы имеют одинаковые размеры, только они расположены в разных координатах в пространстве. Я могу представить два способа их рисования, но я не уверен, какой из них наиболее эффективен. Я не эксперт OpenGL, поэтому я решил спросить здесь.

Метод 1, который я использую сейчас: поскольку все кубы имеют одинаковые размеры, я вычисляю буфер вершин, буфер индекса, обычный буфер и цветной буфер только один раз. Во время обновления сцены я просматриваю все кубы, делаю bufferData() для одного и того же набора буферов, а затем рисую треугольную сетку куба с помощью вызова drawElements(). Поскольку каждый куб находится в другом положении, я переводил mvMatrix, прежде чем рисовать. bufferData() и drawElements() выполняется для каждого куба. В этом методе я, вероятно, сохраняю много памяти, не вычисляя буферы каждый раз. Но я делаю много вызовов drawElements().

Метод 2 будет: обрабатывать все кубы как множество полигонов, распространяющихся по всей сцене. Вычислите вершины, индексы, цвета, нормальные буферы для каждого многоугольника (фактически треугольники внутри полигонов) и подтолкните их к памяти графической карты при одном вызове bufferData(). Затем нарисуйте их одним вызовом drawElements(). Преимущество такого подхода заключается в том, что я выполняю только один вызов bindBuffer и drawElements. Недостатком является то, что я использую много памяти для создания буферов.

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

Я использую это в приложении WebGL, но это общий вопрос OpenGL ES.

Ответ 1

Я реализовал метод 2 и победил оползнем. Предполагаемый недостаток большого объема памяти, казалось, был только моим воображением. Фактически сборщик мусора вызывался в методе 2 только один раз, в то время как он был вызван 4-5 раз в методе 1.

Ваш сценарий OpenGL может отличаться от моего, но если вы пришли сюда в поисках рекомендаций по производительности, урок из этого вопроса: Определите части вашей сцены, которые не часто меняются. Независимо от того, насколько они велики, поместите их в один буферный набор (VBOs) и загрузите в графическую память минимальное количество раз. То, как предполагается использовать VBOs. Ширина памяти между клиентом (т.е. Ваше приложение) и графическая карта ценна, и вы не хотите часто ее потреблять без причины.

Прочтите раздел "Объекты буфера вершин" в гл. 6 "Руководство по программированию OpenGL ES 2.0", чтобы понять, как они должны использоваться. http://opengles-book.com/

Ответ 2

Я знаю, что на этот вопрос уже дан ответ, но я считаю, что стоит отметить презентацию Google IO о оптимизации WebGL:

http://www.youtube.com/watch?v=rfQ8rKGTVlg

Они охватывают, по сути, эту ту же самую проблему (много идентичных фигур с разными цветами/позициями) и рассказывают о некоторых отличных способах оптимизации такой сцены (и их динамика тоже!)

Ответ 3

Предлагаю следующий подход:

Нагрузка:

  • Создать буфер координат (для одного куба) и загрузить его в VBO (gl.glGenBuffers, gl.glBindBuffer)

На рисунке:

  • Буфер привязки (gl.glBindBuffer)

  • Нарисуйте каждую ячейку (цикл)

    2,1. Переместить текущее положение в центр текущего куба (gl.glTranslatef(position.x, position.y, position.z)

    2,2. Нарисуйте текущий куб (gl.glDrawArrays)

    2,3. Переместить позицию назад (gl.glTranslatef(-position.x, -position.y, -position.z))