首页 > 解决方案 > OpenGL:球体减慢帧速率

问题描述

我有一个类可以根据传入的堆栈数、扇区数和半径制作一个球体。问题是,每当我绘制球体时,我的帧速率都会从 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()

有谁知道我怎样才能加快速度?

标签: pythonperformanceopenglpyopenglopengl-compat

解决方案


尝试摆脱嵌套循环。有关使用顶点缓冲区对象顶点数组对象绘制网格的现代方法,请参阅顶点规范


另一种(已弃用)的可能性是使用固定的功能属性。

OpenGL 4.6 API 兼容性配置文件规范;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 EnableClientState( enum array );
void DisableClientState( enum array );

对于顶点、法线、颜色、[...] 数组,数组分别设置为VERTEX_ARRAYNORMAL_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, 0, self.vertexArray)
    glDrawArrays(GL_TRIANGLES, 0, 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, GL_FLOAT, 0, None)
    glBindBuffer(GL_ARRAY_BUFFER, 0)
    
    glEnableClientState(GL_VERTEX_ARRAY)
    glDrawArrays(GL_TRIANGLES, 0, len(self.vertexArray) // 3)
    glDisableClientState(GL_VERTEX_ARRAY)

    # [...]

推荐阅读