Когда я должен использовать индексированные массивы вершин OpenGL?

Я пытаюсь получить четкое представление о том, когда мне следует использовать индексированные массивы вершин OpenGL, нарисованные с помощью gl [Multi] DrawElements и т. П., В отличие от того, когда я должен просто использовать смежные массивы вершин, нарисованные с помощью gl [Multi] 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 всегда следует использовать индексированные массивы, даже для геометрии, которая представляет собой все швы.

Пожалуйста, исправьте мои выводы жирным шрифтом, если они ошибочны.

Ответы на вопрос(1)

Ваш ответ на вопрос