Я пытаюсь получить четкое представление о том, когда мне следует использовать индексированные массивы вершин OpenGL, нарисованные с помощью gl [Multi] DrawElements и т. П., В отличие от того, когда я должен просто использовать смежные массивы вершин, нарисованные с помощью gl [ Мульти] DrawArrays.
( Обновление: Консенсус в ответах, которые я получил, заключается в том, что всегда следует использовать проиндексированные вершины.)
Я несколько раз обсуждал этот вопрос, поэтому я собираюсь изложить свое текущее понимание, в надежде, что кто-то может либо сказать мне, что я теперь, наконец, более или менее прав, или указать, где мой Остальные недоразумения есть. В частности, у меня есть три вывода, выделенные жирным шрифтом. Пожалуйста, исправьте их, если они не правы.
Один простой случай, если моя геометрия состоит из сеток для формирования изогнутых поверхностей. В этом случае вершины в середине сетки будут иметь идентичные атрибуты (положение, нормаль, цвет, координаты текстуры и т. Д.) Для каждого треугольника, который использует вершину.
Это приводит меня к выводу, что:
1. Для геометрии с небольшим количеством швов индексированные массивы - большая победа.
Всегда следуйте правилу 1, кроме:
Для геометрии, которая является очень «блочной», в которой каждое ребро представляет шов, преимущество индексированных массивов менее очевидно. Чтобы взять простой куб в качестве примера, хотя каждая вершина используется в трех разных гранях, мы не можем разделить вершины между ними, потому что для одной вершины нормали поверхности (и, возможно, другие вещи, такие как координаты цвета и текстуры) ) будет отличаться на каждом лице. Следовательно, нам нужно явно ввести избыточные позиции вершин в наш массив, чтобы одна и та же позиция могла использоваться несколько раз с разными нормалями и т. Д. Это означает, что индексированные массивы используются реже.
например. При рендеринге одного лица куба:
0 1
o---o
|\ |
| \ |
| \|
o---o
3 2
(это можно рассматривать изолированно, поскольку швы между этой гранью и всеми смежными гранями означают, что ни одна из этих вершин не может быть разделена между гранями)
если рендеринг с использованием GL_TRIANGLE_FAN (или _STRIP), то каждая грань куба может быть отрисована таким образом:
verts = [v0, v1, v2, v3]
colors = [c0, c0, c0, c0]
normal = [n0, n0, n0, n0]
Добавление индексов не позволяет нам упростить это.
Из этого я заключаю, что:
2. При рендеринге геометрии, которая представляет собой все швы или в основном швы, при использовании GL_TRIANGLE_STRIP или _FAN, я никогда не должен использовать индексированные массивы, а вместо этого всегда должен использовать gl [Multi] DrawArrays.
( Обновление: Ответы указывают на то, что этот вывод неверен. Хотя индексы не позволяют нам уменьшить размер массивов здесь, они все равно должны использоваться из-за других преимуществ производительности, как обсуждалось в комментариях)
Единственное исключение из правила 2:
При использовании GL_TRIANGLES (вместо полос или вееров) половину вершин можно использовать дважды, с одинаковыми нормалями, цветами и т. Д., Поскольку каждая грань куба отображается в виде двух отдельных треугольников. Опять же, для одной и той же грани куба:
0 1
o---o
|\ |
| \ |
| \|
o---o
3 2
Без индексов, используя GL_TRIANGLES, массивы будут выглядеть примерно так:
verts = [v0, v1, v2, v2, v3, v0]
normals = [n0, n0, n0, n0, n0, n0]
colors = [c0, c0, c0, c0, c0, c0]
Поскольку вершина и нормаль часто имеют по 3 числа с плавающей запятой, а цвет часто составляет 3 байта, то для каждой грани куба получается:
verts = 6 * 3 floats = 18 floats
normals = 6 * 3 floats = 18 floats
colors = 6 * 3 bytes = 18 bytes
= 36 floats and 18 bytes per cube face.
(Я понимаю, что число байтов может измениться, если используются разные типы, точные цифры приведены только для иллюстрации.)
С помощью индексов мы можем немного упростить это, получив:
verts = [v0, v1, v2, v3] (4 * 3 = 12 floats)
normals = [n0, n0, n0, n0] (4 * 3 = 12 floats)
colors = [c0, c0, c0, c0] (4 * 3 = 12 bytes)
indices = [0, 1, 2, 2, 3, 0] (6 shorts)
= 24 floats + 12 bytes, and maybe 6 shorts, per cube face.
Посмотрите, как в последнем случае вершины 0 и 2 используются дважды, но представлены только один раз в каждом из массивов вершин, нормалей и цветов. Это звучит как небольшая победа за использование индексов, даже в крайнем случае, когда каждый геометрический край является швом.
Это приводит меня к выводу, что:
3. При использовании GL_TRIANGLES всегда следует использовать индексированные массивы, даже для геометрии, которая представляет собой все швы.
Пожалуйста, исправьте мои выводы жирным шрифтом, если они ошибочны.