我已经编写了一个简单的基准来了解VBO的用法。 在逻辑方面,这样做非常简单:
// enable states
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
// bind vertexes
glBindBuffer(GL_ARRAY_BUFFER, vbos_[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
// normal
glBindBuffer(GL_ARRAY_BUFFER, vbos_[1]);
glNormalPointer(GL_FLOAT, 0, 0);
// indexes
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos_[2]);
// draw n_i_ triangles using offset of index array
glDrawElements(GL_TRIANGLES, n_i_, GL_UNSIGNED_INT, 0);
// deactivate vertex array
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
// bind with 0, so, switch back to normal pointer operation
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
sceneVBO
告诉要绘制多少相同的实例:
for(const auto& i : sceneVBO) {
glPushMatrix();
glColor3fv(i.rgb);
glTranslatef(i.posX, 0.0f, i.posZ);
glRotatef(angle*i.r_speed, 0.0f, 1.0f, 0.0f);
vboTest->draw(); // Executes step 3
glPopMatrix();
}
以下一些参考编号(w / u / s是 msec 的时间 w 所有/ u ser / s ystem)。
对于此测试,我已经将100 实例呈现为完全相同的 VBO (即sceneVBO
包含100个元素,所有那些都指向非常相同 3 VBOs - 顶点,法线和索引)。
Loaded [bunny.obj] 34835/69666 (Tris/Vertexes)
FPS: 333.3 CPU (ms/frame): 3.0/ 0.8/ 2.0 (w/u/s) Total time (ms): 14999.5/4000.4/10000.2 (w/u/s) Frames: 5000
Loaded [dragon.obj] 50000/100000 (Tris/Vertexes)
FPS: 217.4 CPU (ms/frame): 4.6/ 1.4/ 3.0 (w/u/s) Total time (ms): 22999.6/6999.7/15000.9 (w/u/s) Frames: 5000
Loaded [buddha.obj] 543524/1087474 (Tris/Vertexes)
FPS: 27.5 CPU (ms/frame): 36.4/10.4/26.0 (w/u/s) Total time (ms): 181999.9/51999.8/130000.3 (w/u/s) Frames: 5000
因此我的问题是,为什么VBO顶点大小与用户/系统CPU时间成正比?
据我所知,如果GPU有更多的三角形绘制,它会花费更长的时间,但为什么需要更多的CPU用户/系统时间呢?
我没有重新发送每个帧的顶点/法线和索引 - 所有假设要保存在GPU内存中(数组缓冲区用GL_STATIC_DRAW
填充) - 我原以为绘制帧的时间较长,但相对较少的CPU使用率(用户和系统)。
或是驱动程序(nVidia 352.63)/ GL在glXSwapBuffers
上有活动旋转吗?
我一直希望 w 一直增加,但坦率地说不 u ser和 s ystem time ...
聚苯乙烯。当然 V-Sync 已被禁用。
答案 0 :(得分:1)
您的代码中可能存在一些可疑内容。
您正在使用立即模式,这意味着您的API调用依赖于已弃用的行为,而您的驱动程序可能会对其进行优化。
// enable states
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
// bind vertexes
glBindBuffer(GL_ARRAY_BUFFER, vbos_[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
// normal
glBindBuffer(GL_ARRAY_BUFFER, vbos_[1]);
glNormalPointer(GL_FLOAT, 0, 0);
// indexes
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos_[2]);
// draw n_i_ triangles using offset of index array
glDrawElements(GL_TRIANGLES, n_i_, GL_UNSIGNED_INT, 0);
// deactivate vertex array
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
// bind with 0, so, switch back to normal pointer operation
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
你强调这个代码每个实例只调用一次,但由于OpenGL的工作原理,它和DX9(OpenGL的立即模式最相似)并没有真正映射到实际的功能。图形卡特别好 - 在这些用于正确设置状态的API调用中可能发生任何数量的事情。例如,您对glVertexPointer
的调用必须设置状态以从正确的内存段读取,如果您的缓冲区对象特别大,那么这可能是一个非常重要的操作,因为必须设置这些指针GPU启动每个线程以运行着色器。
或是驱动程序(nVidia 352.63)/ GL在
glXSwapBuffers
上有活动旋转吗?
我也不排除这种可能性。它必须定期查询显卡以查明命令是否已完成执行,因此Nvidia可能已选择将此功能实现为忙碌等待。
但最重要的是,如果您担心OpenGL中的CPU开销,您可能希望查看一些AZDO techniques(对于OpenGL 4.3+),或者考虑学习DirectX 12(对于Windows) 10)或Vulkan(对于任何不是Windows 10的东西)
答案 1 :(得分:0)
如上所述,我进行了以下操作:
gluLookAt
,gluPerspective
,glColor3fv
,glTranslatef
,glRotatef
,glLightfv
,... < / LI>
glDebugMessageCallback
和glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, &unusedIds, GL_TRUE)
我仍然得到类似的结果: VAO 中的三角形数量越多,CPU时间越长(用户和系统)我们在glXSwapBuffers
内度过。
这一切似乎都非常意外(至少可以说) 当然,一旦启用了 V-Sync ,CPU时间(用户和系统)就会下降到~0。
所以看起来在glXSwapBuffers
里面我们有一个与要渲染的三角形数量直接相关的主动旋转(渲染的三角形越多,等待一些>的CPU循环就越多 event)。