Что такое индексный буфер и как он связан с буферами вершин?


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, это означает, что нарисовать линию между 0-й и 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
]

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

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

2
На каждый хороший вопрос должно быть 2 или 3 хороших ответа. Ты не тратил свое время, и я очень ценил твои усилия. Мне нужна эта ветка, чтобы объяснить логику партнеру проекта, и ваш пост очень ему поможет.
Afr

1
@ 5chdn Самоответ очень приветствуется . Спасибо за добавление этого ответа. Если у вас есть ответ на вопрос, когда вы отправляете вопрос, под вопросом есть поле для галочки, которое позволит вам написать свой ответ до того, как вы отправите вопрос, так что оба будут отображаться одновременно. Это просто для того, чтобы вы знали, если это полезно - вам определенно не нужно это делать, и ответы на вопросы все равно приветствуются в любой промежуток времени после публикации вопроса.
Трихоплакс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.