opengl - 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不支持?如果他们这样做了,我应该如何使用它。
解决方案
我以为它是在调用 glGenBuffer() 时分配的
该声明:
int *p;
在 C/C++ 中创建一个对象。该对象是一个指针。它不指向实际对象或任何类型的存储;它只是一个指针,等待获得有效地址。
的结果也是如此glGenBuffers
。它是一个缓冲区对象,但它没有存储空间。就像未初始化的指针一样,没有存储空间的缓冲区对象也无能为力。
如果我只不知道在编译时需要绘制多少数据/顶点,那么初始化 VBO 的正确/正常方法是什么?
选择一个合理的起始数字。如果溢出该缓冲区,则终止应用程序或分配额外的存储空间。
但是我们现在有了向量或字符串,它允许我们动态地改变内存位置。为什么OpenGL不支持?
因为OpenGL是一个低级API(相对而言)。
为了以您建议的方式支持动态重新分配存储,OpenGL 实现必须分配您请求大小的新存储,将旧数据复制到新存储中,然后销毁旧存储。std::vector
并且std::string
必须做同样的事情;他们只是在无形中做到这一点。
此外,重复执行这种操作会严重破坏 GPU 的地址空间。vector
和 并没有太大问题string
,因为这些数组通常很小(大约为千字节或低兆字节)。而占用 GPU 总内存 10% 的单个缓冲区对象在严肃的图形应用程序中并不少见。重新分配这不是一个好主意。
如果您想为此遭受性能损失,OpenGL 为您提供了构建它的低级部分。但它不会为你实现它。
推荐阅读
- python-3.x - Python:如何使用随机坐标逐像素显示图像
- javascript - mapStateToProps 未在 redux 中调用,未定义状态
- python - 使用 init.d 在引导时运行时,Shell 文件会跳过命令吗?
- reactjs - 函数在 render() 之外的 React 中不起作用
- thunderbird - 如何在外部浏览器而不是内置浏览器中使用 Thunderbird 68 插件打开网址?
- shell - zsh_history 中命令的平均长度
- r - Tibble 列必须具有一致的长度,如何正确地从列表中提取
- asp.net-mvc - 如何处理同一实体类型的多个一对零或一关系?
- jquery - 单击时重定向到当前页面(不重新加载)
- openstack - Redhat OSP13 undercloud 升级失败