问题描述
我正在尝试使用pyqt5在pyopengl中渲染多个对象。在遵循了教程之后,我创建了一个3D网格,该网格上传了波前obj文件并使用纹理进行渲染。这对我有用:
class Model:
def __init__(self,file_name,texture_name):
self.object = ObjectLoader()
self.object.load_model(file_name)
//creating and compiling shaders
gluseProgram(shader)
vertex_buffer_object = gluint(0)
glGenBuffers(1,vertex_buffer_object)
glBindBuffer(GL_ARRAY_BUFFER,vertex_buffer_object)
glBufferData(GL_ARRAY_BUFFER,len(self.object.model) * 4,self.object.c_model,GL_DYNAMIC_DRAW)
glDrawArrays(GL_TRIANGLES,len(self.object.vertex_index))
# vertices
vertex_offset = 0
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,self.object.model.itemsize * 3,ctypes.c_void_p(vertex_offset))
glEnabLevertexAttribArray(0)
# textures
texture_offset = len(self.object.vertex_index) * 12
glVertexAttribPointer(1,2,self.object.model.itemsize * 2,ctypes.c_void_p(texture_offset))
glEnabLevertexAttribArray(1)
# normals
normal_offset = texture_offset + len(self.object.texture_index) * 8
glVertexAttribPointer(2,ctypes.c_void_p(normal_offset))
glEnabLevertexAttribArray(2)
texture = gluint(0)
glGenTextures(1,texture)
glBindTexture(GL_TEXTURE_2D,texture)
# texture wrapping
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT)
# texture filtering
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
image = Image.open(texture_name)
flipped_image = image.transpose(Image.FLIP_TOP_BottOM)
image_data = image.convert("RGB").tobytes()
glTexImage2D(GL_TEXTURE_2D,GL_RGB,image.width,image.height,GL_UNSIGNED_BYTE,image_data)
// setting the view,projection etc matrix
由于我正在使用PyQt5,因此在加载对象时就拥有此类:
class Obj(qopenglwidget):
def __init__(self,parent):
qopenglwidget.__init__(self,parent)
def initializeGL(self):
glClearColor(82/255,95/255,107/255,1.0)
glEnable(GL_DEPTH_TEST)
self.model = Model("....obj","texture.png")
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glDrawArrays(GL_TRIANGLES,len(self.model.object.vertex_index))
self.update()
def resizeGL(self,width,height):
glViewport(0,height)
我正在努力的是在Obj
类中创建另一个Model
。我尝试在initializeGL
中创建它,并在另一个paintGL
调用中在glDrawArrays
中渲染,但是什么也没发生,或者什么也没想到……我在做什么错了吗?
解决方法
您必须使用Vertex Array Object。顶点数组对象存储提供顶点数据所需的所有状态。
模型的构造函数仅创建所有必需的OpenGL对象。着色器程序不是模型的一部分。对所有模型使用相同的程序:
class Model:
def __init__(self,file_name,texture_name):
self.object = ObjectLoader()
self.object.load_model(file_name)
# create vertex array object
self.vao = glGenVertexArrays(1)
glBindVertexArray(self.vao)
vertex_buffer_object = GLuint(0)
glGenBuffers(1,vertex_buffer_object)
glBindBuffer(GL_ARRAY_BUFFER,vertex_buffer_object)
glBufferData(GL_ARRAY_BUFFER,len(self.object.model) * 4,self.object.c_model,GL_DYNAMIC_DRAW)
glDrawArrays(GL_TRIANGLES,len(self.object.vertex_index))
# vertices
vertex_offset = 0
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,self.object.model.itemsize * 3,ctypes.c_void_p(vertex_offset))
glEnableVertexAttribArray(0)
# textures
texture_offset = len(self.object.vertex_index) * 12
glVertexAttribPointer(1,2,self.object.model.itemsize * 2,ctypes.c_void_p(texture_offset))
glEnableVertexAttribArray(1)
# normals
normal_offset = texture_offset + len(self.object.texture_index) * 8
glVertexAttribPointer(2,ctypes.c_void_p(normal_offset))
glEnableVertexAttribArray(2)
# create texture
self.texture = GLuint(0)
glGenTextures(1,self.texture)
glBindTexture(GL_TEXTURE_2D,self.texture)
# texture wrapping
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT)
# texture filtering
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
image = Image.open(texture_name)
flipped_image = image.transpose(Image.FLIP_TOP_BOTTOM)
image_data = image.convert("RGB").tobytes()
glTexImage2D(GL_TEXTURE_2D,GL_RGB,image.width,image.height,GL_UNSIGNED_BYTE,image_data)
向类添加一个方法,该方法绑定OpenGL对象(VAO和纹理)并绘制网格:
class Model:
# [...]
def draw(self):
// bind texture
glBindTexture(GL_TEXTURE_2D,self.texture)
// create vertex array object
glBindVertexArray(self.vao)
// draw object
glDrawArrays(GL_TRIANGLES,len(self.object.vertex_index))
使用此设置,您可以绘制多个模型:
class Obj(QOpenGLWidget):
def __init__(self,parent):
QOpenGLWidget.__init__(self,parent)
def initializeGL(self):
glClearColor(82/255,95/255,107/255,1.0)
glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
self.model1 = Model("....obj","texture.png")
self.model2 = Model("....obj","texture2.png")
# [...]
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
# install program
glUseProgram(self.shader)
# setting the view,projection etc matrix
# [...]
self.model1.draw()
self.model2.draw()
# [...]
self.update()
def resizeGL(self,width,height):
glViewport(0,height)
模型也可以按列表组织:
class Obj(QOpenGLWidget):
# [...]
def initializeGL(self):
# [...]
self.models = [
Model("....obj","texture.png"),Model("....obj","texture2.png")
# [...]
]
def paintGL(self):
# [...]
for model in self.models:
model.draw()
# [...]