1

我正在使用带有 VBO 的 glDrawElements 调用来渲染我的场景。场景是一块带有顶点和纹理坐标的布料——在这个例子中,我正在渲染一个标志。

在我的场景中,顶点是动态的,这意味着我需要每帧都写入 VBO。我的大部分处理都是使用 CUDA 在 GPU 上完成的,所以我不断地将 CPU 内存映射到 GPU 内存。另一方面,纹理坐标是静态的。为了使用 glDrawElements 进行渲染(据我了解),我应该在顶点 VBO 中交错纹理坐标,然后简单地调用 glTexCoordPointer() 和 glEnableClientState()。这不是最优的,因为当我进行 CPU<-->GPU 内存映射时,我需要与我一起绘制所有纹理坐标。

有没有办法安排我的 vbo 以便我可以更新 vbo 中的顶点数据而不接触 vbo 中的纹理数据?下面是我的渲染代码——我目前填充了三个数组:一个索引数组、一个顶点数组和一个纹理数组。

在下面的代码中,indexVbo 已映射到索引数组,而 vbo 已映射到顶点数组。我现在需要合并纹理。任何见解或建议将不胜感激。

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, flagTexId);

glPushMatrix();
    glColor3f(1.0, 1.0, 1.0);

    glVertexPointer(4, GL_FLOAT, 0, 0);
    glTexCoordPointer(2, GL_FLOAT, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVbo);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    // Render flag mesh
    glDrawElements(GL_TRIANGLES, numTriangles * 3, GL_UNSIGNED_INT, 0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glDisableClientState(GL_VERTEX_ARRAY); 
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glPopMatrix(); 

glDisable(GL_TEXTURE_2D);
4

1 回答 1

3

您可以为两个顶点属性保留单独的 VBO。这样,您甚至可以将 tex 坐标标记为静态,而将另一个标记为动态。

这实际上是否更快取决于许多因素:驱动程序、内存设置等。将部分数据保存在静态内存中的好处可能超过将整个顶点放在高速缓存行上的好处(当你交错时)。但话又说回来,它可能不会。确定您的目标系统的基准。

IMO,将属性拆分为不同 VBO 的一个很好的论据是,它是数据的最“自然”表示。但我想这取决于个人品味以及你是否让它影响你的编程:-)

顺便说一句,您似乎有一个小错误:您需要在gl*Pointer调用之前绑定正确的 VBO(此外,如果您对顶点使用单个 VBO,那么您的偏移量和步幅也不正确)。这也是绑定单独 VBO 的方式:只需在gl*Pointer调用前选择正确的 VBO:

glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex);
glVertexPointer(4, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vbo_texcoord);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
于 2011-04-13T08:36:33.173 回答