首页 > 解决方案 > VBO 是否必须在第一个渲染循环之前“glBufferData”?

问题描述

我是 OpenGL 的新手。现在我可以在屏幕上渲染一些东西,这很棒。现在我想在我的屏幕上流式传输一些数据点(GL_POINTS)。但是,最初它没有显示任何内容。我花了好几天的时间才弄清楚如何让它发挥作用。

关键是,我使用 VBO 来保存我的数据并调用 glBufferSubData() 来更新缓冲区。但是,只有在第一个渲染循环之前调用 glBufferData() 时它才有效。换句话说,如果我这样做

glGenVertexArrays(1, &VAO);    
glGenBuffers(1, &VBO);

在我的初始化函数中(在第一个渲染循环之前),在我的 updateData 循环中我做

glBindVertexArray(VAO);
glBindBuffer(VBO);
glBufferData(GL_ARRAY_BUFFER, myData.size() * sizeof(float), &myData[0], GL_DYNAMIC_DRAW);
... // glVertexAttribPointer and other required general process

它不会渲染任何东西。看来我必须glBufferData(/这里的一些随机数据/)来“分配”缓冲区(我认为它是在调用glGenBuffer()时分配的)。并使用

glBufferSubData(/*override previous data*/) or
glMapData()

更新该缓冲区。所以我的问题是......如果我不知道在编译时需要绘制多少数据/顶点,初始化 VBO 的正确/正常方法是什么?(现在我只是 glBufferData() 一个loooooong缓冲区并在需要时更新它)

注:OpenGL3.3、Ubuntu16.04

更新:

在我看来,它的工作方式类似于分配char[],我不得不指出我需要多少字符串char[200],并通过snprintf() 填写数据。但是我们现在有了向量或字符串,它允许我们动态地改变内存位置。为什么OpenGL不支持?如果他们这样做了,我应该如何使用它。

标签: opengl

解决方案


我以为它是在调用 glGenBuffer() 时分配的

该声明:

int *p;

在 C/C++ 中创建一个对象。该对象是一个指针。它不指向实际对象或任何类型的存储;它只是一个指针,等待获得有效地址。

的结果也是如此glGenBuffers。它是一个缓冲区对象,但它没有存储空间。就像未初始化的指针一样,没有存储空间的缓冲区对象也无能为力。

如果我只不知道在编译时需要绘制多少数据/顶点,那么初始化 VBO 的正确/正常方法是什么?

选择一个合理的起始数字。如果溢出该缓冲区,则终止应用程序或分配额外的存储空间。

但是我们现在有了向量或字符串,它允许我们动态地改变内存位置。为什么OpenGL不支持?

因为OpenGL是一个低级API(相对而言)。

为了以您建议的方式支持动态重新分配存储,OpenGL 实现必须分配您请求大小的新存储,将旧数据复制到新存储中,然后销毁旧存储。std::vector并且std::string必须做同样的事情;他们只是在无形中做到这一点。

此外,重复执行这种操作会严重破坏 GPU 的地址空间。vector和 并没有太大问题string,因为这些数组通常很小(大约为千字节或低兆字节)。而占用 GPU 总内存 10% 的单个缓冲区对象在严肃的图形应用程序中并不少见。重新分配这不是一个好主意。

如果您想为此遭受性能损失,OpenGL 为您提供了构建它的低级部分。但它不会为你实现它。


推荐阅读