2013-07-09 5 views
5

Как сделать сетку (состоящую из треугольников), где каждый треугольник имеет тот же цвет, не указав этот цвет 3 раза за треугольник в массивах вершин.Как визуализировать сетку, состоящую из треугольников, где каждый треугольник имеет один и тот же цвет, не указав этот цвет 3 раза на треугольник

Предположим, я хочу нарисовать 2 треугольника. Треугольник 1:

Vertex 1, position:(x1,y1) , color: (r1,g1,b1,a1) 
Vertex 2, position:(x2,y2) , color: (r1,g1,b1,a1) 
Vertex 3, position:(x3,y3) , color: (r1,g1,b1,a1) 

Треугольник 2:

Vertex 4, position:(x4,y4) , color: (r2,g2,b2,a2) 
Vertex 5, position:(x5,y5) , color: (r2,g2,b2,a2) 
Vertex 6, position:(x6,y6) , color: (r2,g2,b2,a2) 

Я знаю, что это может быть сделано путем создания 2 вершинных буферов:

Vertex Buffer 1: 
[x1, y1] 
[x2, y2] 
[x3, y3] 
[x4, y4] 
[x5, y5] 
[x6, y6] 


Vertex Buffer 2: 
[r1, g1, b1, a1] 
[r1, g1, b1, a1] 
[r1, g1, b1, a1] 
[r2, g2, b2, a2] 
[r2, g2, b2, a2] 
[r2, g2, b2, a2] 

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

Vertex buffer 1 отлично, потому что все данные уникальны, но мой вопрос: isnt vertex buffer 2 такая пустая трата пространства !? Что, если у меня есть тысячи треугольников, и при таком подходе я дублирую цвет дважды на каждый треугольник. Должен быть более умный способ хранения избыточных атрибутов. Я не знаю об этом. Кто-нибудь может рассказать?

ответ

1

(ВНИМАНИЕ:.. Следующее решение не может быть стоит свеч, так как она не является фиксированной функции трубопровода Пожалуйста, сообщите мне о каких-либо ошибок/дезинформации в этом ответе)

Насколько я знаю, в OpenGL любая вершина должна знать данные, которые она использует либо непосредственно за вершину, либо косвенно за вызов. Вы можете сказать: «все вершины в следующем обратном вызове используют эти данные» или вы можете упаковать каждую вершину с соответствующими данными в один или несколько буферов, используя индексы (как и вы). Поскольку у вас может быть только один набор индексов, вы можете привязать только одну вершину к цвету, поэтому вам нужен новый цвет для каждой вершины, даже если они одинаковы. Это значит, что у вас есть дубликаты данных, если вы хотите делать такие вещи в одном обратном вызове.

Однако вы можете уменьшить размер этих дублирующихся данных, обратившись к цветам с индексами, внутри шейдера. Таким образом, вы можете иметь (например) 256 разных цветов в сетке и только 1 байтовый индекс цвета на вершину (или 256 * 256 цветов с 1 коротким индексом и т. Д.). Это утомительное решение для такой «легкой» проблемы, но все время, которое я потратил на поиск, это единственное решение.

Идея заключается в том, чтобы что-то вроде этого:

  1. Создать буфер, содержащий все цвета, которые вам необходимы.

  2. Создайте сетку с атрибутами вершин, связывающими вершины с правильными цветами и индексом.

  3. Создайте вершинный шейдер, который принимает атрибут, заглядывает в буфер, извлекает цвет и передает его в шейдер фрагмента, который затем меняет свой результат на основе этого цвета.

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

Для меня это решение действительно очень уродливое и неэффективное, но в моем ограниченном опыте OGL это единственное решение, которое у меня для вас. Хотелось бы услышать, что у кого-то есть лучшее решение, поскольку я работаю с подобными проблемами!

PS: Имейте в виду, что данные вершин любят быть размером в два раза, и вам, скорее всего, понадобится только это решение, если вы можете использовать его, чтобы избежать заполнения ненужных данных.

+0

Спасибо. Я, вероятно, просто дублирую данные, но хорошо знать, что я не пропускаю какую-либо функцию, так как вариантов не так много. – viktorzeid

1

Этот вид пахнет преждевременной оптимизацией.

Это, конечно, хорошо, чтобы быть критической, когда речь идет о потреблении памяти, но в большинстве случаев ваши данные текстуры будут использовать много более памяти, чем ваша геометрия (помните FBOs/Renderbuffers, а!). Бритье нескольких байтов здесь и там быстро становится очень дорогим улучшением, возможно, с худшей производительностью. Может быть, вы в конечном итоге заполняете свои данные вершин для выравнивания?

Как упоминалось в другой ответ, вероятно, можно сделать это:

  • Создать палитру
  • магазин индекс цвета/палитра в массиве вершин
  • Отправить в палитре, хотя текстуры или УБО

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

Сохраните это и используйте подробный формат. Оптимизируйте для особых случаев позже, если необходимо.

Лично я сделал бы это только в том случае, если у палитры есть цель кроме уменьшения размера. Возможно, вы хотите динамически изменять данные о цвете? В этой ситуации удобно использовать 1D-массив с 256 entires (Texture или UBO).

Если вы используете instancing (нарисуйте модель несколько раз с помощью одного вызова рисования), вы можете, конечно, определить уникальные значения для каждого экземпляра, указав делитель атрибутов. (Вероятно, недействительно в этом примере)

+0

Спасибо Гримми. Я согласен с вашими соображениями относительно преждевременной оптимизации, если позже мне придется менять цвета на вершину, это будет менее беспорядочно, используя этот подход. – viktorzeid

+0

Если сравнить его с использованием световой карты, это действительно очень дешево. Для световых карт требуется отдельный слой uv + текстура. – Grimmy