问题描述
我有一个基于传递的堆栈数,扇区数和半径来制作球体的类。问题是,每当我绘制球体时,我的帧速率就会从57-60 fps下降到20 fps。
这就是我画球的方式:
def draw_edges(self):
"""Draws the sphere's edges"""
glPushmatrix()
glTranslate(self.position[0],self.position[1],self.position[2])
glrotate(self.rotation[3],self.rotation[0],self.rotation[1],self.rotation[2])
glpolygonMode(GL_FRONT_AND_BACK,GL_LINE)
glBegin(GL_TRIANGLES)
for edge in self.edges:
for vertex in edge:
glVertex3fv(self.vertices[vertex])
glEnd()
glpolygonMode(GL_FRONT_AND_BACK,GL_FILL)
glPopMatrix()
有人知道我该如何加快速度吗?
解决方法
尝试摆脱嵌套循环。有关使用Vertex Specification和Vertex Buffer Object来绘制网格的现代方法,请参见Vertex Array Object。
另一种(不建议使用的)可能性是使用固定函数属性。
命令
void VertexPointer( int size,enum type,sizei stride,const void *pointer ); void NormalPointer( enum type,const void *pointer ); void ColorPointer( int size,const void *pointer ); [...]
指定数组的位置和组织以存储顶点坐标,法线,颜色等。通过调用以下其中一个来启用或禁用单个数组。
void EnableClientState( enum array ); void DisableClientState( enum array );
分别将顶点,法线,颜色,[...]阵列的数组分别设置为
VERTEX_ARRAY
,NORMAL_ARRAY
,COLOR_ARRAY
,[...]。
在类的构造函数中使用顶点属性数据创建一个列表:
def __init__(self):
# [...]
self.vertexArray = []
for edge in self.edges:
for vertex in edge:
self.vertexArray.append(self.vertices[vertex])
使用数组指定顶点并绘制网格:
def draw_edges(self):
"""Draws the sphere's edges"""
glPushMatrix()
glTranslate(self.position[0],self.position[1],self.position[2])
glRotate(self.rotation[3],self.rotation[0],self.rotation[1],self.rotation[2])
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3,GL_FLOAT,self.vertexArray)
glDrawArrays(GL_TRIANGLES,len(self.vertexArray))
glDisableClientState(GL_VERTEX_ARRAY)
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL)
glPopMatrix()
这是使用VBO和VAO的现代解决方案的第一步(小步骤)。
使用Vertex Buffer Object可以进一步提高性能:
def __init__(self):
# [...]
self.vertexArray = []
for edge in self.edges:
for vertex in edge:
self.vertexArray += self.verticies[vertex] # <--- flat list
array = (GLfloat * len(self.vertexArray))(*self.vertexArray)
self.vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER,self.vbo)
glBufferData(GL_ARRAY_BUFFER,array,GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER,0)
def draw_edges(self):
# [...]
glBindBuffer(GL_ARRAY_BUFFER,self.vbo)
glVertexPointer(3,None)
glBindBuffer(GL_ARRAY_BUFFER,0)
glEnableClientState(GL_VERTEX_ARRAY)
glDrawArrays(GL_TRIANGLES,len(self.vertexArray) // 3)
glDisableClientState(GL_VERTEX_ARRAY)
# [...]