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

StackOverflow https://stackoverflow.com/questions/2954349

  •  23-10-2019
  •  | 
  •  

Вопрос

Я пытаюсь получить четкое представление о том, когда я должен использовать индексированные массивы вершин OpenGL, нарисованные с помощью GL [Multi] Чрезмерными наборами и тому подобным, по сравнению с тем, когда я должен просто использовать смежные массивы вершин, нарисованные с помощью GL [Multi]. Анкет

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

Я несколько раз ходил взад и вперед по этому вопросу, поэтому я собираюсь изложить свое нынешнее понимание, в надежде, что кто -то сможет сказать мне, что я наконец более или менее правильный, либо указал, где мои оставшиеся недопонимание Анкет В частности, у меня есть три вывода, жирных шрифтов. Пожалуйста, поправьте их, если они не правы.

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

Это заставляет меня к выводу, что:

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, я никогда не должен использовать индексированные массивы, а вместо этого должен всегда использовать RAWARRES GL [Multi].

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

Единственное исключение из правила 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 используются дважды, но представлены только один раз в каждом из массивов Verts, Normals и Colors. Это звучит как небольшая победа для использования индексов, даже в крайнем случае, когда каждый край геометрии является швом.

Это заставляет меня к выводу, что:

3. При использовании gl_triangles всегда следует использовать индексированные массивы, даже для геометрии, которая является всеми швами.

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

Это было полезно?

Решение

Из этого я заключаю, что при использовании геометрии, которая представляет собой все швы или в основном швы, при использовании gl_triangle_strip или _fan, я никогда не должен использовать индексированные массивы и вместо этого должен всегда использовать [мульти] ливень Gl.

Нет, и причина довольно проста.

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

Но попробуйте подумать о большой геометрии местности. Каждый блок местности рисуется как квадроцикл с использованием примитива вентилятора/полосы треугольника. Например:

Каждая полоска треугольника на рисунке имеет общие вершины с соседними треугольными полосками, и использование индексов позволяет сжимать определение геометрии, а не повторять вершины для каждой полоски треугольника.


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

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

  • Избегайте синхронизации информации, принадлежащей к той же «концептуальной» вершине, указанной много раз
  • Разрешить выполнять одну и ту же операцию шейдера на одной вершине, вместо этого выполняющего много раз, по одному для каждого дублирования вершин.
  • Кроме того, объединение использования треугольных полос/вентиляторов и индексов позволяет приложению сжимать буфер индексов, поскольку спецификация полосы/вентилятора требует меньше индексов (треугольник всегда требует 3 индекса для каждой лица).

Индексированный массив не может быть использован, как вы указали, всякий раз, когда вершина не может делиться каждой связанной с ним информации (цвет, координат текстуры и т. Д.) С другой случайной вершиной.


Просто ради полноты, размер информации, необходимой для спецификации геометрии, является не единственным фактором, который определяет оптимальную операцию рендеринга.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top