OpenGL绘制顶点缓冲对象

时间:2015-09-15 00:42:41

标签: c++ opengl indexing vbo

我有两个' std :: vector' s,一个用于索引,一个用于顶点,我用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);

在程序开始时,我也不知道这是否正确(正如你所看到的,我对这个东西很新)。

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分: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)上返回它的实际大小(以字节为单位)。

在第二种情况下,我们在堆上分配的动态数组上使用sizeof。理想情况下,array2的大小在编译时是不可知的(否则你应该使用静态数组,如果适合堆栈),那么编译器对数组 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()。 要获取基础float数组的大小(以字节为单位),只需使用 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);

答案 2 :(得分:0)

将来您还可以使用图形调试器来解决这些问题。根据您的卡,您可以在Linux上使用AMDs gpu perf studio或nVidia nsight或Linux上的图形调试器。这节省了大量时间和麻烦。

如果再次出现空白屏幕。使用附加的调试器运行您的应用程序并按照管道进行操作。

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