У вас есть 2 массива.Первый массив содержит 2-мерные координаты вершин, а второй массив содержит индексы.
Вы должны использовать glDrawElements
, чтобы нарисовать примитивы треугольника, которые содержатся во втором массиве.Индексы относятся к соответствующим координатам вершин 1-го массива.
Сначала необходимо создать буфер с плавающей запятой для координат вершин и интегральный буфер для индексов.Самый простой способ - использовать NumPy для преобразования вложенного списка или массивов в буферы массивов.
Предполагая, что у вас есть массив vertices
в форме [[x0, y0], [x1, y1], [x2, y2], ...] и массив indices
в форме [[a0, b0, c0], [a1, b1,c1], [a2, b2, c2], ...] , тогда буферы могут быть созданы следующим образом:
import numpy as np
vertex_array = np.array(vertices, dtype=np.float32)
no_of_indices = len(indices) * 3
index_array = np.array(indices, dtype=np.uint32)
То же самое можно сделать с помощью ctypes
вместо NumPy.Но тогда списки должны быть сведены в виде [x0, y0, x1, y1, x2, y2, ...] соответственно [a0, b0, c0, a1, b1, c1, a2, b2, c2, ...] :
vertex_array = (ctypes.c_float * len(flat_vertices))(*flat_vertices)
no_of_indices = len(flat_indices) * 3
index_array = (ctypes.c_uint32 * no_of_indices)(*flat_indices)
Создать объект массива вершин.См. Спецификация вершин :
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
ibo = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_array, GL_STATIC_DRAW)
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, vertex_array, GL_STATIC_DRAW)
glVertexAttribPointer(0, 2, GL_FLOAT, False, 0, None)
glEnableVertexAttribArray(0)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
Если вы хотите нарисовать треугольные примитивы, достаточно связать объект массива вершин и вызвать glDrawElements
:
glBindVertexArray(vao)
glDrawElements(GL_TRIANGLES, no_of_indices, GL_UNSIGNED_INT, None)
По поводу комментария:
[...] Я уже знаю, как текстурировать плоскость, используя glTexCoord2f
затем glVertex3f
, но не понял, как я могу это сделатьсделать это с помощью vao.
Самый простой способ - создать отдельный массив текстурных координат.Предполагая, что у вас есть координаты текстуры texAttr
в форме [[u0, v0], [u1, v1], [u2, v2], ...].Генерация буфера проста:
texAttr_array = np.array(texAttr, dtype=np.float32)
Если у вас есть шейдерная программа, вам нужно добавить атрибут координаты текстуры:
например,
layout (location = 0) in vec2 vertex;
layout (location = 1) in vec2 texAttr;
и для определения массива универсальных данных атрибутов вершин.
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
# [...] index buffer
vbo = glGenBuffers(2)
glBindBuffer(GL_ARRAY_BUFFER, vbo[0])
glBufferData(GL_ARRAY_BUFFER, vertex_array, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, vbo[1])
glBufferData(GL_ARRAY_BUFFER, texAttr_array, GL_STATIC_DRAW)
glVertexAttribPointer(0, 2, GL_FLOAT, False, 0, None)
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 2, GL_FLOAT, False, 0, None)
glEnableVertexAttribArray(1)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
Если вы используете профиль совместимости и атрибуты фиксированной функции, то вам нужно указать glTexCoordPointer
и включитьсостояние клиента GL_TEXTURE_COORD_ARRAY
.
Обратите внимание, что состояние клиента GL_VERTEX_ARRAY
и glVertexPointer
сопоставлено с атрибутом вершины 0. См. Каковы местоположения атрибутовдля конвейера с фиксированными функциями в профиле ядра OpenGL 4.0 ++? :
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
# [...] index buffer
vbo = glGenBuffers(2)
glBindBuffer(GL_ARRAY_BUFFER, vbo[0])
glBufferData(GL_ARRAY_BUFFER, vertex_array, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, vbo[1])
glBufferData(GL_ARRAY_BUFFER, texAttr_array, GL_STATIC_DRAW)
glVertexPointer(2, GL_FLOAT, 0, None)
glEnableClientState(GL_VERTEX_ARRAY)
glTexCoordPointer(2, GL_FLOAT, 0, None)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
Обратите внимание: если вы не используете шейдер, тогда необходимо включить двухмерное текстурирование с помощью
glEnable(GL_TEXTURE_2D)
Относительно комментария:
Я бы хотел смещать одну вершину по очереди [...]
Может координата одной вершиныможет быть изменено на glBufferSubData
, где 2-й параметр - это смещение в байтах относительно координаты вершины.Смещение для координаты i
будет равно 4*2*i
(4 - это размер с плавающей точкой в байтах, и каждая координата состоит из 2 компонентов x и y ).