【问题标题】:C++ Vertex Buffer IssueC++ 顶点缓冲区问题
【发布时间】:2013-05-12 18:25:55
【问题描述】:

我正在尝试将顶点缓冲区添加到 pixel city 程序城市生成程序的 Mesh.cpp 文件中。当前部分代码如下所示:

for (qsi = _quad_strip.begin(); qsi < _quad_strip.end(); ++qsi) {
  glBegin (GL_QUAD_STRIP);
  for (n = qsi->index_list.begin(); n < qsi->index_list.end(); ++n) {
    glTexCoord2fv (&_vertex[*n].uv.x);
    glVertex3fv (&_vertex[*n].position.x);
  }
    glEnd ();
}

这会将纹理绘制到某些建筑物的矩形边上。刚刚离开我在网上找到的 VBO 教程,我尝试将其转换为使用这样的顶点缓冲区(我将 vboId 存储在 Mesh.h 中):

for (qsi = _quad_strip.begin(); qsi < _quad_strip.end(); ++qsi) {
    void * varray = (char *) malloc(sizeof(GLfloat)*5*qsi->index_list.size());
    GLfloat *p = (GLfloat*)varray;

    int counter = 0;
    for (n = qsi->index_list.begin(); n < qsi->index_list.end(); ++n) {
      memcpy(&p[counter+0],&_vertex[*n].uv.x, sizeof(GLfloat)*2);
      memcpy(&p[counter+2],&_vertex[*n].position.x, sizeof(GLfloat)*3);
      counter+=5;
    }
    glGenBuffersARB(1, &vboId);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(GLfloat)*5*qsi->index_list.size(), p, GL_STATIC_DRAW_ARB);

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat)*5, (GLfloat*)0); 
    glVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*5,  (GLfloat*)2);

    glDrawArrays(GL_QUAD_STRIP, 0, qsi->index_list.size());

    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

    free(varray);
   }

但是,此代码根本不起作用。什么都没有渲染。有时,当我将参数弄乱到 glTexCoordPointer 或 glVertexPointer 中时,我真的会歪曲/垃圾数据绘制在屏幕上(或程序崩溃),但没有任何东西可以接近远程工作。

【问题讨论】:

  • 对每个循环迭代都使用一个新的缓冲区有点达不到目的。
  • 另外,这会在几帧后失败,因为你正在快速泄漏 VBO 内存。
  • 我打算先让它工作,然后再把它移到循环之外。
  • 问题是,您的数据已经完全按照单个 VBO 所需的方式进行布局。你可以只吃整个_vertex 数组。然后使用将n 的索引列表传递给glDrawArrays。事实上,现在看起来您正在将顶点数据重新排列为连续的,然后传递一组不连续的索引 - 结果不会很好。
  • 哎呀,对不起。您将把索引传递给glDrawElements。 glDrawArrays 确实希望数据按顺序排列。

标签: c++ opengl vbo


【解决方案1】:

您的顶点指针错误。使用 VBO 时,指针被解释为相对于当前绑定缓冲区的字节偏移量。所以,你需要 sizeof(GLfloat)*2 字节作为偏移量。

glVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*5,  (char*)0 +sizeof(GLfloat)*2);

附带说明:如果您要创建具有正确大小但 NULL 作为数据指针(基本上创建数据存储)的 VBO 并使用 glMapBuffer() 对其进行内存映射,则可以保存额外的数据副本,完全避免了您使用的malloc()ed 临时缓冲区。

【讨论】:

  • 非常感谢!那解决了它!绝对希望我早点发布这个消息,这样可以省去很多麻烦:)我也会考虑使用 glMapBuffer()。
  • 2 + (GLfloat*)0 怎么样?
  • @BenVoigt:好吧,如果你更喜欢这样的话。为什么不2[(GLfloat*)0]?
  • 2 + (GLfloat*)0 也很有趣。我想有很多事情我没有尝试。 2[(GLfloat*)0] 无法为我编译。
  • @Brutalisk:是的,我的错。它实际上会尝试取消对该指针的引用。 &2[(GLfloat*)0] 应该可以编译,但我不建议使用这种废话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多