Що таке буфер індексів і як це пов'язано з вершинними буферами?


11

У мене буфер вершин такий:

0.0, 0.0,
1.0, 0.0,
0.0, 0.6,
1.0, 0.6,
0.5, 1.0

У мене є такий індексний буфер:

0, 2,
2, 4,
4, 3,
3, 2,
2, 1,
1, 0,
0, 3,
3, 1

Я знаю, що хочу малювати gl.LINESза допомогою WebGL, означає декілька відокремлених сегментів рядків.

gl.drawElements(gl.LINES, 16, gl.UNSIGNED_SHORT, indexBuffer);

Схоже, ввімкнено малювання декількох сегментних рядків в одному дзвінку виклику в WebGL.

Може хтось ELI5 для мене, що таке буфер індексів і як це пов'язано з вершинними буферами? Як генерувати індексні буфери від моїх примітивів?

Відповіді:


12

Може хтось ELI5 для мене, що таке буфер індексів і як це пов’язано з вершинними буферами

Ваш вершинний буфер містить координати X і Y 5 вершин. Вони є:

index |  X  |  Y
  0   | 0.0 | 0.0 
  1   | 1.0 | 0.0
  2   | 0.0 | 0.6
  3   | 1.0 | 0.6
  4   | 0.5 | 1.0

Ваш індексний буфер містить інформацію про те, які лінії слід провести між цими вершинами. Він використовує індекс кожної вершини в буфері вершин як значення.

Оскільки ви малюєте лінії, кожна пара послідовних значень у вашому індексному буфері вказує сегмент рядка. Наприклад, якщо індекс буфер починається з 0, 2, це означає , провести лінію між 0th і 2 - й вершиною в масиві вершин, які в цьому випадку будуть малювати лінію , що йде від [0.0, 0.0]до [0.0, 0.6].

На наступній графіці кожна пара індексів координується кольором з рядком, який вона позначає:

введіть тут опис зображення

Аналогічно, якби ви малювали трикутники замість ліній, вам потрібно було б подати індексний буфер, де кожне 3 послідовне значення вказує індекси трьох вершин у вершинному буфері, наприклад

0, 1, 2,
2, 1, 3,
2, 3, 4,

5

Якщо у вас такий буфер вершин:

var vertices = [
  0.0, 0.0, 0.0,
  1.0, 0.0, 0.0,
  0.0, 0.6, 0.0,
  1.0, 0.6, 0.0,
  0.5, 1.0, 0.0
]

І просто намалюйте так, як є:

// Create an empty buffer object
var vertex_buffer = gl.createBuffer();

// Bind appropriate array buffer to it
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

// Pass the vertex data to the buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

/* [...] */

// Draw the lines
gl.drawArrays(gl.LINES, 0, 5);

Для кожного сегмента рядка знадобиться дві виділені координати. Із verticesвизначеним вище способом можна було б лише намалювати дві лінії :

дві лінії

Якщо у вас визначені такі показники:

var indices = [
  0, 2,
  2, 4,
  4, 3,
  3, 2,
  2, 1,
  1, 0,
  0, 3,
  3, 1
]

Можна промальовувати лінії, які перетинаються однакові вершини знову і знову. Це зменшує надмірність. Якщо ви зв’яжете буфер індексів і скажете GPU скласти відрізки рядків, що з'єднують вершини, у порядку, визначеному в масиві indecies:

var index_buffer = gl.createBuffer();

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);

gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

// draw geometry lines by indices
gl.drawElements(gl.LINES, 16, gl.UNSIGNED_SHORT, index_buffer);

Можна малювати складніші фігури, не переробляючи однакові вершини знову і знову. Це результат:

будинок

Щоб досягти такого ж результату без індексів, вершинний буфер повинен виглядати наступним чином:

var vertices = [
  0.0, 0.0, 0.0,
  0.0, 0.6, 0.0,
  0.0, 0.6, 0.0,
  0.5, 1.0, 0.0,
  0.5, 1.0, 0.0,
  1.0, 0.6, 0.0,
  1.0, 0.6, 0.0,
  0.0, 0.6, 0.0,
  0.0, 0.6, 0.0,
  1.0, 0.0, 0.0,
  1.0, 0.0, 0.0,
  0.0, 0.0, 0.0,
  0.0, 0.0, 0.0,
  1.0, 0.6, 0.0,
  1.0, 0.6, 0.0,
  1.0, 0.0, 0.0
]

/* [...] */

// Draw the lines
gl.drawArrays(gl.LINES, 0, 16);

У результаті виходить однакове зображення:

ще один будинок

Зверніть увагу на величезну надмірність збережених вершин.


2
Якщо ви плануєте негайно відповісти на власне запитання, будь-ласка, принаймні зазначте це у питанні, щоб інші не витрачали свій час.
Ротем

2
На кожне добре запитання має бути 2 або 3 гарних відповіді. Ви не витрачали свій час, і я дуже цінував ваші зусилля. Мені потрібна ця нитка, щоб пояснити логіку партнеру по проекту, і ваша публікація допоможе йому багато.
Afr

1
@ 5chdn Самостійне відповідь настійно рекомендується . Дякуємо, що додали цю відповідь. Якщо ви маєте на увазі відповідь під час опублікування запитання, під цим запитом є галочка, яка дозволить вам написати свою відповідь перед тим, як поставити запитання, тож обидва з’являться одночасно. Це просто, щоб повідомити вас у випадку, якщо це корисно - вам, звичайно, цього не потрібно робити, і власні відповіді все ще дуже вітаються на будь-який проміжок часу після публікації питання.
трихоплакс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.