OpenGL:球体减慢帧速率
Posted
技术标签:
【中文标题】OpenGL:球体减慢帧速率【英文标题】:OpenGL: Sphere slowing down framerate 【发布时间】:2020-09-11 18:32:31 【问题描述】:我有一个类可以根据传入的堆栈数、扇区数和半径制作一个球体。问题是,每当我绘制球体时,我的帧速率都会从 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()
有谁知道我怎样才能加快速度?
【问题讨论】:
for 循环在 Python 中可能非常慢。也许有一种方法可以替换两个 for 循环。 请注意,您使用的是已弃用的固定功能管道。尽管您的系统显然支持它,但它可能远非最佳。您应该考虑转向基于可编程着色器的替代方案。 或者至少是显示列表或 VBO。 【参考方案1】:尝试摆脱嵌套循环。有关使用 Vertex Buffer Object 和 Vertex Array Object 绘制网格的现代方法,请参阅 Vertex Specification。
另一种(已弃用)的可能性是使用固定的函数属性。
OpenGL 4.6 API Compatibility Profile Specification; 10.3.3 Specifying Arrays for Fixed-Function Attributes; page 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)
# [...]
【讨论】:
谢谢!这种方法使我的帧速率翻了一番,达到 40 fps 多一点。 @User-92 谢谢。别客气。通过使用 VBO 可以实现进一步的改进。我会扩展答案。请稍等一下…… @User-92 我已经扩展了答案。 哇,太疯狂了!我现在有超过 70 fps。我不知道 VBO 可以这么快地提高性能。非常感谢! @User-92 诀窍是在构造函数中将顶点数组上传到 GPU 一次。绘制对象时,只需引用数组即可。self.vbo
只是一个名称 ID。以上是关于OpenGL:球体减慢帧速率的主要内容,如果未能解决你的问题,请参考以下文章