Я читал некоторые места, где использование glBegin
и glEnd
вызывает проблемы?Что я должен использовать вместо ...
Рисование glBegin
и glEnd
устарело в современном OpenGL (см. Конвейер с фиксированными функциями и Legacy OpenGL ).В современном OpenGL Вершины задаются с помощью Объекты буфера вершин и Объект массива вершин , и все отрисовывается с помощью шейдерной программы .
В качестве первого шага в этом направлении я рекомендую использовать Объекты буфера вершин и возможности на стороне клиента
См. Спецификация профиля совместимости API OpenGL 4.6;10.3.3. Задание массивов для атрибутов с фиксированными функциями;стр. 402
Команды
void VertexPointer( int size, enum type, sizei stride, const void *pointer );
void NormalPointer( enum type, sizei stride, const void *pointer );
void ColorPointer( int size, enum type, sizei stride, const void *pointer );
void SecondaryColorPointer( int size, enum type, sizei stride, const void *pointer );
void IndexPointer( enum type, sizei stride, const void *pointer );
void EdgeFlagPointer( sizei stride, const void *pointer );
void FogCoordPointer( enum type, sizei stride, const void *pointer );
void TexCoordPointer( int size, enum type, sizei stride, const void *pointer );
определяют местоположение и организацию массивов для хранения координат вершин, нормали, цвета, вторичные цвета, индексы цветов, флаги границ,координаты тумана.
...
Отдельный массив включается или отключается путем вызова одного из
void EnableClientState( enum array );
void DisableClientState( enum array );
с массивом, установленным в VERTEX_ARRAY
, NORMAL_ARRAY
,COLOR_ARRAY
, SECONDARY_COLOR_ARRAY
, INDEX_ARRAY
, EDGE_FLAG_ARRAY
, FOG_COORD_ARRAY
или TEXTURE_COORD_ARRAY
для вершины, нормали, цвета, вторичного цвета, индекса цвета, флага края, координаты тумана или массива координат текстуры,соответственно.
Для этого вам нужно подготовиться и включить NumPy :
import numpy
Создать глобальные переменные для объектов буфера вершин
global face_vbos, edge_vbo
Создать наборы атрибутов (пары цвета и координаты вершины) для граней и создания объектов буфера вершин для граней (координата вершины и цвет).Наконец, создайте объект буфера вершин для координат вершин ребер:
def main():
global face_vbos, edge_vbo
.....
# define the vertex buffers vor the faces
vertex_array = []
color_array = []
for face in range(len(surfaces)):
for vertex in surfaces[face]:
vertex_array .append( vertices[vertex] )
color_array.append( colors[face] )
face_vbos = glGenBuffers(2)
glBindBuffer(GL_ARRAY_BUFFER, face_vbos[0])
glBufferData( GL_ARRAY_BUFFER, numpy.array( vertex_array, dtype=numpy.float32 ), GL_STATIC_DRAW )
glBindBuffer(GL_ARRAY_BUFFER, face_vbos[1])
glBufferData( GL_ARRAY_BUFFER, numpy.array( color_array, dtype=numpy.float32 ), GL_STATIC_DRAW )
glBindBuffer(GL_ARRAY_BUFFER, 0)
# define the vertex buffer for the edges
edge_vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, edge_vbo)
glBufferData( GL_ARRAY_BUFFER, numpy.array( vertices, dtype=numpy.float32 ), GL_STATIC_DRAW )
glBindBuffer(GL_ARRAY_BUFFER, 0)
while True:
.....
Когда вы рисуете грани и ребра, вы должны определить массив данных вершин (glVertexPointer
)и определить массив цветов (glColorPointer
) для включения возможности на стороне клиента (glEnableClientState
).Грани могут быть нарисованы с помощью glDrawArrays
, поскольку все координаты цветов сохраняются в последовательном массиве (vertex_array
и color_array
-> face_vbos
).Края должны быть нарисованы с помощью glDrawElements
с использованием индексов edges
, поскольку вершины (vertices
-> edge_vbo
) должны быть проиндексированы для формирования линий:
def Cube(veritces):
global face_vbos, edge_vbo
# draw faces
glBindBuffer(GL_ARRAY_BUFFER, face_vbos[0])
glVertexPointer( 3, GL_FLOAT, 0, None )
glEnableClientState( GL_VERTEX_ARRAY )
glBindBuffer(GL_ARRAY_BUFFER, face_vbos[1])
glColorPointer( 3, GL_FLOAT, 0, None )
glEnableClientState( GL_COLOR_ARRAY )
glBindBuffer(GL_ARRAY_BUFFER, 0)
glDrawArrays(GL_QUADS, 0, 6*4)
glDisableClientState( GL_VERTEX_ARRAY )
glDisableClientState( GL_COLOR_ARRAY )
#draw edges
glBindBuffer(GL_ARRAY_BUFFER, edge_vbo)
glVertexPointer( 3, GL_FLOAT, 0, None )
glEnableClientState( GL_VERTEX_ARRAY )
glBindBuffer(GL_ARRAY_BUFFER, 0)
glColor3f( 1, 1, 0 )
glDrawElements(GL_LINES, 2*12, GL_UNSIGNED_INT, numpy.array( edges, dtype=numpy.uint32 ))
glDisableClientState( GL_VERTEX_ARRAY )
Это можно улучшить, используя Объекты массива вершин и Индексный буфер для краев:
global face_vao, edge_vao
def main():
global face_vao, edge_vao
.....
# define the vertex buffers vor the faces
attribute_array = []
for face in range(len(surfaces)):
for vertex in surfaces[face ]:
attribute_array.append( vertices[vertex] )
attribute_array.append( colors[face] )
face_vbos = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, face_vbos)
glBufferData( GL_ARRAY_BUFFER, numpy.array( attribute_array, dtype=numpy.float32 ), GL_STATIC_DRAW )
glBindBuffer(GL_ARRAY_BUFFER, 0)
# define the vertex array object for the faces
face_vao = glGenVertexArrays( 1 )
glBindVertexArray( face_vao )
glBindBuffer(GL_ARRAY_BUFFER, face_vbos)
glVertexPointer( 3, GL_FLOAT, 6*4, None )
glEnableClientState( GL_VERTEX_ARRAY )
glColorPointer( 3, GL_FLOAT, 6*4, ctypes.cast(3*4, ctypes.c_void_p) )
glEnableClientState( GL_COLOR_ARRAY )
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray( 0 )
# define the vertex buffer for the edges
edge_vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, edge_vbo)
glBufferData( GL_ARRAY_BUFFER, numpy.array( vertices, dtype=numpy.float32 ), GL_STATIC_DRAW )
glBindBuffer(GL_ARRAY_BUFFER, 0)
# define the vertex array object for the edges
edge_vao = glGenVertexArrays( 1 )
glBindVertexArray( edge_vao )
glBindBuffer(GL_ARRAY_BUFFER, edge_vbo)
glVertexPointer( 3, GL_FLOAT, 0, None )
glEnableClientState( GL_VERTEX_ARRAY )
glBindBuffer(GL_ARRAY_BUFFER, 0)
edge_ibo = glGenBuffers(1)
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, edge_ibo )
glBufferData( GL_ELEMENT_ARRAY_BUFFER, numpy.array( edges, dtype=numpy.uint32 ), GL_STATIC_DRAW )
glBindVertexArray( 0 )
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 )
while True:
.....
def Cube(veritces):
global face_vao, edge_vao
# draw faces
glBindVertexArray( face_vao )
glDrawArrays( GL_QUADS, 0, 6*4 )
glBindVertexArray( 0 )
#draw edges
glColor3f( 1, 1, 0 )
glBindVertexArray( edge_vao )
glDrawElements( GL_LINES, 2*12, GL_UNSIGNED_INT, None )
glBindVertexArray( 0 )
Дальнейшее улучшение производительности вы можете получить с помощью Отбор лица и добавление теста Глубина .Тест на глубину должен быть меньше или краем, чтобы края не были закрыты гранями:
# enable depth test (less or equal)
glEnable( GL_DEPTH_TEST )
glDepthFunc( GL_LEQUAL )
# enable back face culling (front faces are drawn clockwise)
glEnable( GL_CULL_FACE )
glCullFace( GL_BACK )
glFrontFace( GL_CW )
Обратите внимание, что последним шагом для рисования геометрии "современным" способом в OpenGL будет использование программы Shader и замена glEnableClientState
на glEnableVertexAttribArray
и glVertexPointer
соответственно glColorPointer
glVertexAttribPointer
(конечно, используя правильные параметры).