【问题标题】:OpenGL Draw Vertex Buffer ObjectOpenGL 绘制顶点缓冲对象
【发布时间】:2015-09-15 00:42:41
【问题描述】:

我有两个“std::vector”,一个用于索引,一个用于顶点,我用 std::vector.push_back() 填充它们。然后我做

glGenBuffers(1, &verticesbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, verticesbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, /*EDITED-->*/vertices.size() * sizeof(vertices[0])/*<--EDITED*/, &vertices[0], GL_STATIC_DRAW);

为每个创建缓冲区,然后尝试用

绘制多边形
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

glBindBuffer(GL_ARRAY_BUFFER, verticesbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesbuffer);

glDrawElements(
    GL_TRIANGLES,
    indices.size(),
    GL_UNSIGNED_INT,
    &indices[0]
    );

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

当我运行程序时,什么也没有出现。我可以使用 glBegin() / glEnd() 方法让它工作,但索引的 vbo 不起作用(glGetError() 也没有给出任何错误)。我什至不知道这是否接近正确,因为我搜索了无数教程和其他 stackoverflow 问题并尝试了许多不同的方法来修复它。我还应该提到我打过电话

glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glOrtho(0.0f, windowX, windowY, 0.0f, 0.0f, 1000.0f);

在程序开始时,我也不知道这是否正确(如您所见,我对这方面很陌生)。

【问题讨论】:

  • 您确定没有 glEnable 或 glEnableClientState 丢失吗?
  • 我修复了答案指出的错误,但我仍然没有看到任何东西。我错过了 glEnable 或 glEnableClientState 吗?我在问题中发布的 OpenGL 方法调用是我所做的唯一与绘图相关的调用
  • 现在这个问题的问题是你没有提供MCVE。我们已经解决了使用您提供的代码的明显问题原因。如果您想继续获得帮助,您应该发布一个包含 MCVE 的新问题。
  • @ArcaneEnforcer:您实际上似乎从未将属性指针设置为指向您的 VBO。

标签: c++ opengl indexing vbo


【解决方案1】:

问题是您希望sizeof(vertices) 为您提供存储在向量中的总字节数。但是,它只给出向量对象本身的大小,而不是它包含的动态数据。

您应该使用vertices.size() * sizeof(vertices[0])

【讨论】:

    【解决方案2】:

    您误解了sizeof 运算符的工作原理。它是一个在编译时执行并返回指定类型或变量的大小(以字节为单位)的运算符。

    float f;
    std::cout << sizeof(f); // prints 4
    std::cout << sizeof(float); // prints 4
    

    但是当我们在指向数组的指针上使用sizeof 时会发生什么?让我们检查以下案例:

    float array1[50]; // static size array, allocated on the stack
    float *array2 = new float[50]; // dynamic size array, allocated on the heap
    
    std::cout << sizeof(array1); // prints 200, which is ok (50*4 == 200)
    std::cout << sizeof(array2); // prints out the size of a float pointer, not the array
    

    在第一种情况下,我们在一个静态数组上使用sizeof,该数组分配在堆栈上。由于 array1 的大小是恒定的,编译器知道它并在sizeof(array1) 上返回它的实际大小(以字节为单位)。

    在第二种情况下,我们在堆上分配的动态数组上使用sizeofarray2 的大小理想情况下在编译时是无法知道的(否则你应该使用静态数组,如果适合堆栈),所以编译器对数组 array2 的大小一无所知,所以它将指针的大小返回到我们的数组。

    当您在 std::vector 上使用 sizeof 时会发生什么?

    std::vector<float> vec(50);
    std::cout << sizeof(vec); // prints out the size of the vector (but it's not 4*50)
    

    但是如果sizeof(vec)返回向量的大小,为什么不返回4*50呢? std::vector 管理一个底层动态分配的数组(上例中的第二种情况),因此编译器对该底层数组的大小一无所知。这就是为什么它返回向量对象的整体封装(隐藏)变量的大小,包括指向实际数组数据的指针的大小。如果您想要底层数组中的元素数量,则需要使用 vec.size()。 要获取底层浮点数组的大小(以字节为单位),只需使用 vec.size() * sizeof(float)

    用上面的知识修复你的代码:

    std::vector<float> vertices;
    // ...add vertices with push_back()...
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertices.size() * sizeof(float), &vertices[0], GL_STATIC_DRAW);
    

    std::vector<float> vertices;
    // ..add vertices with push_back()...
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertices.size() * sizeof(vertices[0]), &vertices[0], GL_STATIC_DRAW);
    

    【讨论】:

    • 在 C++11 及更高版本中 vertices.data() 也会给你一个指向底层数组的指针
    【解决方案3】:

    将来您还可以使用图形调试器来帮助解决这些问题。根据您的显卡,您可以在 Windows 上使用 AMDs gpu perf studio 或 nVidia nsight,在 Linux 上使用图形调试器。这节省了很多时间和头痛。

    如果您再次出现空白屏幕。在附加调试器的情况下运行您的应用程序并遵循管道。

    您应该看到输入顶点着色器的数据,因为它比您预期的要短,它会标记一个问题,您可以从那里开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-30
      相关资源
      最近更新 更多