Подтвердить что ты не робот

Android OpenGL ES glDrawArrays или glDrawElements?

Каков наилучший способ: использовать ли glDrawArrays или glDrawElements? Какая разница?

4b9b3361

Ответ 1

Для обоих вы передаете OpenGL некоторые буферы, содержащие данные вершин.

glDrawArrays в основном "нарисовать этот непрерывный диапазон вершин, используя данные, которые я дал вам раньше". Хорошо:

  • Вам не нужно создавать индексный буфер

Плохо:

  • Если вы упорядочиваете свои данные в GL_TRIANGLES, у вас будут дублированные данные вершин для смежных треугольников. Это явно расточительно.
  • Если вы используете GL_TRIANGLE_STRIP и GL_TRIANGLE_FAN, чтобы попытаться избежать дублирования данных: это не очень эффективно, и вам нужно будет сделать вызов рендеринга для каждой полосы и вентилятора. Вызовы OpenGL дороги и их следует избегать, если это возможно.

С помощью glDrawElements вы передаете буфер, содержащий индексы вершин, которые хотите рисовать.

Хорошо

  • Нет дублированных данных вершин - вы просто индексируете одни и те же данные для разных треугольников
  • Вы можете просто использовать GL_TRIANGLES и полагаться на кеш-вершину, чтобы не обрабатывать одни и те же данные дважды - не нужно повторно организовывать геометрию данных или разделить рендеринг на несколько вызовов.

Bad

  • Накладные расходы на память буфера индекса

Моя рекомендация - использовать glDrawElements

Ответ 2

Последствия производительности, вероятно, похожи на iphone, Руководство по программированию OpenGL ES для iOS рекомендует использовать треугольные полосы и объединять несколько полос через вырожденные треугольники.

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

Для лучшей производительности ваши модели должны быть представлены как единая необрезанная треугольная полоса с использованием glDrawArrays с максимально возможным количеством дублированных вершин. Если ваши модели требуют дублирования множества вершин (поскольку многие вершины разделяются треугольниками, которые не появляются последовательно в полосе треугольника или потому, что ваше приложение объединяет множество небольших треугольных полос), вы можете получить лучшую производительность с помощью отдельного буфера индекса и вызова glDrawElements вместо. Существует компромисс: неиндексированная полоса треугольника должна периодически дублировать целые вершины, в то время как индексированный список треугольников требует дополнительной памяти для индексов и добавляет служебные данные для поиска вершин. Для достижения наилучших результатов проверьте свои модели с помощью индексированных и неиндексированных треугольных полос и используйте тот, который выполняет самые быстрые.

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

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

Ответ 3

На самом деле вы можете дегенерировать полосу треугольника для создания непрерывных полос, чтобы вам не приходилось разбить ее при использовании glDrawArray.

Я использую glDrawElements и GL_TRIANGLES, но думая об использовании glDrawArray вместо этого с GL_TRIANGLE_STRIP. Таким образом, нет необходимости в создании вектора inidices.

Любой, кто знает больше о кеш-кепке вершины, о которой упоминалось выше в одном из сообщений? Думая о производительности между glDrawElements/GL_TRIANGLE и glDrawArray/GL_TRIANGLE_STRIP.

Ответ 4

Принятый ответ немного устарел. Следуя ссылке doc в Jorn Horstmann, Руководство по программированию OpenGL ES для iOS, Apple описывает как использовать трюк" вырожденных треугольников" с DrawElements, тем самым получая лучшее из обоих миров.

Небольшая экономия нескольких индексов с помощью DrawArrays не стоит экономии, которую вы получаете, объединяя все ваши данные в один GL-вызов DrawElements. (Вы можете комбинировать все с помощью DrawArrays, но тогда любые "потерянные элементы" будут тратить вершины, которые намного больше, чем индексы, и требуют большего времени рендеринга.)

Это также означает, что вам не нужно тщательно учитывать все ваши модели, как большинство из них могут отображаться как минимальное количество полос, или они слишком сложны. Одно единообразное решение, которое обрабатывает все. (Но старайтесь, по возможности, организовывать на полоски, чтобы минимизировать отправленные данные и максимизировать вероятность использования GPU для повторного использования недавно кэшированных вычислений вершин.)

BEST: один вызов DrawElements с GL_TRIANGLE_STRIP, содержащий все ваши данные (которые меняются в каждом кадре).