OpenGL批量渲染网格

时间:2014-06-09 20:31:41

标签: opengl mesh glew 3d-modelling

我使用OpenGL,glew和GLFW来为项目编写一个简单的游戏。我已经有一个使用Assimp的3D模型导入器,它也在处理纹理。

这就是我绘制一个网格的方式:

    glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[NORMAL_VB]);
    glNormalPointer(GL_FLOAT, 0, NULL);

    glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[TEXCOORD_VB]);
    glTexCoordPointer(2, GL_FLOAT, 0, NULL);

    glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[POS_VB]);
    glVertexPointer(3, GL_FLOAT, 0, NULL);

    //Render the triangles
    glDrawArrays(GL_TRIANGLES, 0, m_Entries[i].NumIndices);

我的问题是如何使用相同的网格渲染数百个移动实体,但每个网格具有不同的世界位置和旋转?

如果我有数百个移动实体,每个帧我渲染相同的网格数百次,我现在可以注意到FPS下降。

顺便说一下,我没有使用着色器,只是简单的绘制

1 个答案:

答案 0 :(得分:2)

由于glVertexPointer()(和其他gl<Foo>Pointer()调用)在OpenGL 3及更高版本中已弃用,我假设您当前未使用OpenGL 3+核心配置文件。

有两种实例渲染方法可能是可用的,都是通过扩展提供的; ARB_Draw_InstancedARB_Instanced_Arrays。任何特定卡/驱动程序都可以使用,或者两者都不可用。

ARB_Draw_Instanced 提供glDrawArraysInstancedARB(),其工作方式与您已经使用的glDrawArrays电话基本相同,但也提供gl_InstanceId整数变量供使用在着色器中,您可以使用它来从UBO,TBO或您想要使用的任何其他机制中读取矩阵或任何其他每个实例数据,以将每个实例数据导入着色器。从理论上讲,早在OpenGL 1.1中就可以在上下文中使用此扩展。

ARB_Instanced_Arrays 提供glVertexAttribDivisorARB(),可让您修改特定顶点属性的工作方式。在顶点着色器中,每个后续顶点通常从附加缓冲区获取下一个属性值。因此,第一个顶点获取缓冲区中首先指定的位置,第二个顶点获取第二个位置,依此类推。使用此函数,您可以告诉OpenGL根据实例而不是根据顶点来提前提供给着色器的数据。因此,您可以创建一个通用顶点属性,其中包含将要绘制的所有实例的世界位置,并告诉OpenGL仅更新实例之间的值,因此第一个实例的每个顶点都获得第一个值,第二个实例的每个顶点都获得第二个值,依此类推。从着色器的角度来看,这些值现在被视为顶点属性,而不是制服。从理论上讲,这个扩展可以在早期的OpenGL 2中提供。

在我的硬件上,这两种方法都不适用于OpenGL 2.1上下文(因为这些扩展或相关扩展都没有公开)。你的电脑可能像我的一样;无法在OpenGL 2.1上下文中进行实例化渲染。或者你的可能支持两种方法。或者只是其中一个。同样,您为程序提供的任何其他人都可能会发现他们的计算机支持其中一个或两个,或两者兼而有之。扩展就是这样,无论主机支持什么,您的程序都应该能够应对。

在我的情况下,根据计算机支持的内容,而不是处理单独的实现,而不是简单的&#39;解决方案是切换到OpenGL 3+上下文,其中两个接口都以非扩展形式提供。

glDrawArraysInstanced()(上述ARB接口的非扩展版本)成为OpenGL 3.1的核心,因此保证在每个3.1核心配置文件中都存在。同样,glVertexAttribDivisor()已添加到OpenGL 3.3的核心配置文件中,并将在每个3.3核心配置文件中提供。