Самый быстрый способ рисовать четырехугольники в OpenGL ES?


22

Я использую OpenGL ES 2.0. У меня есть куча четырехугольников, которые я хотел бы нарисовать. Мне бы хотелось иметь возможность передавать только 4 вершины на каждый квад, как если бы я использовал GL_QUADS, но в основном я просто хочу знать лучший способ рисования куча отдельных квадов.

Пока, что я нашел, я мог сделать: -GL_TRIANGLES (6 вершин на квад) -Регенерация GL_TRIANGLE_STRIP (6 вершин на квад)

Возможности, которые я нашел: -GL_TRIANGLE_STRIPS со специальным значением индекса, которое сбрасывает полосу квадраторов (это будет означать 5 индексов на квад, но я не думаю, что это возможно, это OpenGL ES 2.0)

Ответы:


33

Просто используйте индексный буфер и GL_TRIANGLES. В этом случае вам нужно 4 вершины + 6 индексов на квад (6 дополнительных индексов могут показаться большими накладными расходами, но на самом деле это не так - после того, как вы построили индексный буфер, вам больше не нужно его трогать). Смотрите эту страницу для получения дополнительной информации (поиск glDrawElements)

Простой пример кода:

GLfloat vertices[] = {-1, -1, 0, // bottom left corner
                      -1,  1, 0, // top left corner
                       1,  1, 0, // top right corner
                       1, -1, 0}; // bottom right corner

GLubyte indices[] = {0,1,2, // first triangle (bottom left - top left - top right)
                     0,2,3}; // second triangle (bottom left - top right - bottom right)

glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);

Кроме того, если вы рисуете только один квад, вам нужно всего 4 вершины, чтобы нарисовать его треугольными полосками ( как показано в википедии ), но я думаю, вы уже знали это.


Традиционный прием для объединения нескольких треугольных полос в одну полосу - это «вырожденные треугольники»: повторение последнего элемента одной полосы и первого элемента следующей полосы создает 2 треугольника с нулевой площадью, которые, таким образом, ничего не рисуют. Рассмотрим индексы второго квадрата (4, 5, 6, 7). Индексный буфер для GL_TRIANGLE_STRIP из двух квадов может быть: {0, 1, 2, 3, 3, 4,4, 5, 6, 7}. Вырожденные треугольники - это 3,3,4и 3,4,4. Стоит ли это делать? Нет, если только ваши четверки не собираются в пары (или больше) с общими ребрами. Если 2-й квадрат равен {3, 2, 4, 5}, то полоса равна {0,1,3,2,5,4}.
ToolmakerSteve

8
И чтобы это было понятно каждому, кто придет и должен нарисовать кучу квадов: ради производительности НЕ копируйте приведенный выше код и сделайте вызов glDrawElements ONCE FOR EACH QUAD . Вместо этого создайте ОДИН массив вершин и ОДИН массив индексов, который включает ВСЕ квадранты, которые вы хотите нарисовать. Используя GL_TRIANGLES, два квадра могут иметь индексы {0,1,2, 0,2,3, 4,5,6, 4,6,7}или одинаково хорошо это {0,1,2, 2,3,0, 4,5,6, 6,7,4}. Хороший класс, чтобы помочь в этом - glText-Android / SpriteBatch
ToolmakerSteve

6

Использование буферов индекса не обязательно быстрее, как указано в документации Apple: «Для лучшей производительности ваши модели должны быть представлены в виде одной неиндексированной треугольной полосы с использованием glDrawArrays» .

Таким образом, хотя a GL_TRIANGLE_STRIPбудет делать это в 4 вершинах, не нуждаясь в буфере индекса, и вы можете использовать буфер индекса, довольно сложно попытаться «сохранить» повторяющиеся 2 вершины . По этой причине я бы предложил вам нарисовать 2 отдельных GL_TRIANGLESи повторить 2 вершины по диагонали .


8
Нет Этот документ говорит, что ваши модели должны быть представлены в виде одной треугольной полосы INDEXED. И самое следующее предложение: «Чтобы не указывать данные для одной и той же вершины несколько раз в буфере вершин, используйте отдельный индексный буфер и нарисуйте треугольную полосу с помощью функции glDrawElements». Что именно то, что вы решили, было «хромым».
davidf2281

3
Учитывая, что абзац документа теперь ссылается на glDrawElements, а не на glDrawArrays, он, вероятно, был переписан после этого ответа. Тем не менее, идея документа заключалась в том, что для повышения производительности поставляйте одну полосу (а не несколько полос, следовательно, несколько вызовов GL). В этой ситуации я считаю, что разница между использованием индексов или нет незначительна ; важно собрать все в один массив вершин (плюс необязательный индексный массив), чтобы вы могли сделать один вызов gl.
ToolmakerSteve

0

Большим преимуществом на рабочем столе является перемещение данных в VBO GL_STATIC_DRAW. Предположительно, это относится и к графическому процессору iPhone MBX.


-2

Использование GL_TRIANGLE_FANдля четырехугольника использует 4 вершины, а не 6.


Да, но так же GL_TRIANGLE_STRIP, как уже указали другие ответы.
Анко

@Мистер. Бла - Ты упустил суть вопроса, который заключается в том, как эффективно сделать кучу квадов. Не следует делать вызов gl для каждого квадратора, а скорее объединять множество квадов в один массив, который можно нарисовать одним вызовом gl. GL_TRIANGLE_FAN не поможет с этим, поэтому редко используется для высокопроизводительного рендеринга.
ToolmakerSteve
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.