Эффективный способ рисования в 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)
)