Я пытаюсь понять, когда я должен использовать индексированные массивы вершин 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 всегда следует использовать индексированные массивы, даже для геометрии, которые являются всеми швами.
Пожалуйста, исправьте мои выводы жирным шрифтом, если они ошибаются.