Skip to main content
 首页 » 编程设计

python之具有多个基元的显示列表的 VBO 等价物

2025年05月04日16oomusou

我有一个简单的 OpenGL 应用程序,我在其中绘制海岸线数据。数据是一长串多边形(约 41000 个),其中每个多边形都是 (x,y) 点的列表。多边形的长度各不相同(因为有些海岸线比其他海岸线长)。 现在,使用显示列表绘制起来很简单 - 这是 Python 代码,但我相信你明白了要点:

self.coastlines_dl = GL.glGenLists(1) 
GL.glNewList(self.coastlines_dl, GL.GL_COMPILE) 
for poly in coastline_polys: 
    GL.glBegin(GL.GL_LINE_STRIP) 
        for point in poly: 
            GL.glVertex3f(point[0], point[1], 0.0) 
    GL.glEnd() 
GL.glEndList() 

然后在渲染循环中:

GL.glCallList(self.coastlines_dl) 

这表现得很好。

我的问题是:如何使用 VBO 进行等效操作?我最初的方法是为每个多边形创建一个 VBO,然后在渲染循环中绘制每个 VBO,例如:

for v in self.vbos: 
    v.bind() 
    GL.glEnableClientState(GL.GL_VERTEX_ARRAY) 
    GL.glVertexPointerf(v) 
    GL.glDrawArrays(GL.GL_LINE_STRIP, 0, v.data.shape[0]) 
    GL.glDisableClientState(GL.GL_VERTEX_ARRAY) 
    v.unbind() 

这是有效的,因为它绘制了数据,但帧速率令人震惊,这并不奇怪,因为我每帧绑定(bind)和绘制 41000 多次。

那么我可以将我所有的多边形放入一个大的 VBO 中,只做一个绑定(bind)和一个 glDrawArrays 吗?我不明白的是 glDrawArrays 如何知道每个多边形中有多少个点,因为每个多边形都不同?

抱歉,如果这是非常微不足道的,但我一直在读到,我可以用显示列表做的任何事情都可以用 VBO 来完成,但我找不到一个例子来说明我需要做什么。


编辑 1 - 鉴于 VBO 性能缓慢,这是我的平台详细信息

Windows 7 64 位
i5-2430M
GPU 仅板载 Intel HD Graphics 3000
4GB 内存

应用程序是 Python OpenGL。 Python 版本为 2.7.9 64 位,带有 PyOpenGL 3.1.0 amd64,并通过 PySide 1.2.2 amd64 使用 QT QGLWidget。

这是来自 gDEBugger 的转储:

General 
------- 
OpenGL Version           3.1 
Shading Language Version 1.40  - Intel Build 8.15.10.2345 
Is Backward-Compatible Yes 
Is Forward-Compatible No 
Is Debug Context Yes 
Renderer Vendor Intel 
Renderer Name Intel(R) HD Graphics Family 
Renderer Version 3.1.0 - Build 8.15.10.2345 
Renderer Type Installable client 
Marked for Deletion      No 
OpenGL Sharing Contexts  None 
 
Pixel Format Information 
------------------------ 
Pixel Format ID          9 
Hardware Acceleration    Full 
Double-Buffered          Yes 
Stereographic            No 
Native Rendering         No 
 
Channel                  Bits 
Red                      8 
Green                    8 
Blue                     8 
Alpha                    8 
Depth                    24 
Stencil                  8 
Accumulation             64 

请您参考如下方法:

您可能不应该为每个多边形创建一个 VBO。这将非常缓慢,并且不是驱动程序在您的第一次实现中将在幕后做的事情。你应该有一个 VBO(当你优化时可能是几个分块的 VBO)和你需要的所有顶点数据。然后索引到 VBO 中以绘制每个图元。所以你的 glDrawArrays 将开始使用第二个参数'first'。

也没有必要在循环中每次都启用和禁用ClientState,这样做可能会导致驱动程序执行不必要的验证

请原谅我缺乏 python-gl 知识,但它看起来像这样。

v.bind() 
GL.glEnableClientState(GL.GL_VERTEX_ARRAY) 
GL.glVertexPointerf(v) 
for v in self.vbos: 
    GL.glDrawArrays(GL.GL_LINE_STRIP, vbo_offset_goes_here, v.data.shape[0]) 
GL.glDisableClientState(GL.GL_VERTEX_ARRAY) 
v.unbind() 

这仍然不是最理想的,因为它需要大量的绘制调用,而绘制调用的成本可能相当高。但这应该是您示例的简单增量改进。之后,您可以尝试 glMultiDrawArrays,因为您只有一个原始类型,所以它应该能够让您完全删除循环。