В следующих примерах используется список из 6 индексов, которые могут образовывать четырехугольник, состоящий из 2 треугольных примитивов.
indices = [0, 1, 2, 0, 2, 3]
Поскольку данные, которые передаются в функции OpenGL, должны состоять из единиц фиксированного размера в связном буфере, список значений должен храниться в массиве с плавающей запятой.
Буферы связного массива могут быть созданы либо библиотекой ctypes , либо библиотекой numpy.array
.
Тип элементов массива должен соответствовать константе перечислителя типа значения, которая устанавливается при вызове glDrawElements
или glMultiDrawElements
:
ctypes.c_ubyte / numpy.uint8 <-> GL_UNSIGNED_BYTE
ctypes.c_ushort / numpy.uint16 <-> GL_UNSIGNED_SHORT
ctypes.c_uint / numpy.uint32 <-> GL_UNSIGNED_INT
Использование ctypes
:
import ctypes
indexArray = (ctypes.c_uint * 6)(*indices)
Использование numpy
:
import numpy
indexArray = numpy.array(indices, dtype=numpy.uint32)
Для использования индексного буфера и glDrawElements
существуют различные возможности.
Используя Legacy OpenGL ( профиль совместимости xontext ), буфер может быть напрямую передан в glDrawElements
. Указатель на данные массива передается в функцию.
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indexArray)
Если в объекте массива вершин указан объект буфера массива именованных элементов, то последний параметр glDrawElements
обрабатывается как смещение байта в хранилище данных объекта буфера.
glBindVertexArray(vao)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexArray, GL_STATIC_DRAW)
Если индексы должны быть нарисованы, начиная с 1-го элемента буфера, тогда последний параметр может быть None
, что эквивалентно ctypes.c_void_p(0)
:
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)
Если рисование не должно начинаться с первого индекса, то необходимо рассчитать смещение байта начального индекса. например 3*4
устанавливает начало для индекса 3 для буфера типа GL_UNSIGNED_INT
:
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, ctypes.c_void_p(3 * 4))
Использование glMultiDrawElements
очень похоже.
Используя профиль совместимости xontext , указатели буфера можно напрямую передавать в функцию OpenGL.
К массивам индексов должны быть сгенерированы:
Использование ctypes
:
indexArray1 = (ctypes.c_uint * 3)(0, 1, 2)
indexArray2 = (ctypes.c_uint * 3)(0, 2, 3)
Использование numpy
:
indexArray1 = numpy.array([0, 1, 2], dtype=numpy.uint32)
indexArray2 = numpy.array([0, 2, 3], dtype=numpy.uint32)
Указатели на буферы должны быть расположены на массив указателей:
Используя ctypes
, указатель на индексные массивы данных получается по ctypes.addressof()
:
indexPtr = (ctypes.c_void_p * 2)(ctypes.addressof(indexArray1),ctypes.addressof(indexArray2))
При использовании numpy
указатель на индексные массивы данных получается по numpy.ndarray.ctypes
:
indexPtr = numpy.array([indexArray1.ctypes.data, indexArray2.ctypes.data], dtype=numpy.intp)
Этот массив указателей может быть передан в функцию OpenGL:
counts = [3, 3]
glMultiDrawElements(GL_TRIANGLES, counts, GL_UNSIGNED_INT, indexPtr, 2)
Если используется объект массива вершин с буфером массива именованных элементов,
glBindVertexArray(vao)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)
тогда параметр индекса обрабатывается как указатель на массив смещений байтов. Далее в массив передается 2 смещения. 0 идентифицирует 1-й индекс в массиве и 3 * 4 3-й индекс.
Использование ctypes
:
indexPtr = (ctypes.c_void_p * 2)(0, 3 * 4)
counts = [3, 3]
glMultiDrawElements(GL_TRIANGLES, counts, GL_UNSIGNED_INT, indexPtr, 2)
Использование numpy
:
indexPtr = np.array([0, 3*4], dtype=numpy.intp)
counts = [3, 3]
glMultiDrawElements(GL_TRIANGLES, counts, GL_UNSIGNED_INT, indexPtr, 2)