python - 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()
有谁知道我怎样才能加快速度?
解决方案
尝试摆脱嵌套循环。有关使用顶点缓冲区对象和顶点数组对象绘制网格的现代方法,请参阅顶点规范。
另一种(已弃用)的可能性是使用固定的功能属性。
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_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, 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)
# [...]
推荐阅读
- google-apps-script - 如何让谷歌电子表格每天(同一天)刷新自己?
- c# - 布尔值的按位比较是否被认为是错误的?
- java - 在 Java 中,如何有效地从字节数组的开头和结尾修剪 0
- python - 如何检查我的字典中只有一个值被填充?
- .net - 无法从传输连接读取数据:连接尝试失败,因为连接方
- python - 强制chrome web驱动加载翻译成英文的日文网站
- iis - SignalR 与 NetCore,IIS 连接失败并在部署时不时出现超时或 404
- github - 是否可以为 GitHub 操作创建全局工作流?
- excel - 时间值被复制粘贴为小数
- python - 任何数字的数字总和,直到总和为一位数