Android OpenGL ES glDrawArrays или glDrawElements? - PullRequest
21 голосов
/ 17 января 2011

Как лучше всего: если я использую glDrawArrays или glDrawElements? Какая разница?

Ответы [ 4 ]

32 голосов
/ 17 января 2011

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

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

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

Bad:

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

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

Хорошо

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

Bad

  • Переполнение памяти индексного буфера

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

6 голосов
/ 17 января 2011

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

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

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

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

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

1 голос
/ 24 сентября 2015

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

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

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

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

1 голос
/ 09 января 2012

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

Я использовал glDrawElements и GL_TRIANGLES, но подумывал об использовании glDrawArray вместо GL_TRIANGLE_STRIP.Таким образом, нет необходимости создавать вектор inidice.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...