编辑 - 为了帮助澄清最上面的问题.. 我想我正在寻找哪种排序会表现更好:按程序排序或按纹理排序?有关系吗?我所有的对象都在相似的 z 空间中,并且都存储在同一个 VBO 中。如果我不通过 glUseProgram 切换着色器,我是否必须为每个对象重新设置属性?
原帖:
这是一个两部分的问题。我试图弄清楚在绘制之前如何最好地对我的 3d 对象进行排序,以及每个 glDrawElements 必须执行哪些打开的 gl 调用,以及每次屏幕刷新(甚至一次)可以完成哪些调用。目的当然是为了速度。对于我的游戏,让我们假设从前到后的 z 不是什么大问题(大多数对象都在同一个 z 上)。因此,除了最后对所有具有透明度的对象进行排序外,我不会对 z 进行排序。
当然,我不希望排序过程花费比渲染未排序更长的时间。
第 2 部分是每个 glDrawElements 必须使用哪些 open gl 调用,哪些只能在信息更改时执行?presentRenderbuffer 是否会清除某些内容,以便您必须重新调用它们。
大多数 opengl 2 演示都会对每个对象进行每次调用。实际上大多数演示只绘制一个对象。所以在 3d 引擎中(就像我正在写的那样)我想避免不必要的冗余调用。
这是我做的顺序(未排序,未优化):
glUseProgram(glPrograms[useProgram]);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
Loop through objects {
Do all matrix calcs
Set Uniforms (matrix, camera pos, light pos, light colors, material properties)
Activate Textures.. (x2)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture0);
glUniform1i(glUniforms[useProgram][U_textureSampler], 0);
Bind VBOs
glBindBuffer(GL_ARRAY_BUFFER, modelVertVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelIndVBO);
Set Attributes (vertexpos, texcoord, norm, tan, bitan)
glDrawElements(GL_TRIANGLES, models[modelToUse].indSize, GL_UNSIGNED_INT, (void *) (models[modelToUse].indOffset * sizeof(GLuint)));
}
当然,这只在所有对象使用相同的着色器/程序时才有效。在实践中他们不会。
3D 对象位于一个数组中,其中包含每个对象的所有属性:模型 ID、着色器 ID、纹理 ID、位置等。所以我的想法是进行快速简单的排序,以将类似对象的索引号堆叠在其他数组中。然后在每个数组中绘制项目。我可以按 3d 模型(对象类型)、纹理或着色器排序。许多模型共享相同的纹理。许多模型共享相同的着色器。此时我有 3 个着色器。所有对象共享一个 VBO。
我可以这样做吗?
Bind the VBO - since all objects use the same one
Loop through object types {
If shader hasn't changed
glUseProgram
Set Attributes
If texture hasn't changed
glActiveTexture(s) - based on which program is active
Loop through objects of that type {
Do matrix calcs
Set Uniforms - based on which program is active
glDrawElements
}
}
编辑 - 要清楚 - 我仍在绘制所有对象,只是以不同的顺序组合着色器和/或纹理的使用,以避免绑定,然后在游戏的一个“帧”内再次重新绑定。
我目前在第二次刷新时遇到 glDrawElements 崩溃,但我认为这很容易找到。我只包括这个事实,因为它让我认为绑定纹理可能不会延续到第二帧(或 presentBuffers)。
避免更改着色器或更改纹理会更快吗?属性、vbo 和纹理是否会在多个 glDrawElement 调用中保持活动状态?跨多个presentBuffers?