我有 2 个对象每帧渲染一次,其中一个渲染速度快,每帧更新一次,另一个渲染速度慢(使用实例化渲染的大对象(。由于我不能在两个不同的线程中使用 opengl,因此每次更新大对象时(为此,我调用 glBufferData 并使用新数据重置其缓冲区(,程序都会滞后,光源对象停止渲染。我想一种解决方案是每帧渲染重物的一部分,而不是一次渲染所有重物。但是这种划分不是很实际,那么有没有更好的方法呢?
由于您没有包含代码或描述性细节,我将尽力理解它。如果您的大型模型是静态且不变的,最好的办法是创建一个 VBO(顶点缓冲区对象(并分配数据一次,然后使用提供的句柄进行渲染,在此处阅读更多内容;https://www.khronos.org/opengl/wiki/VBO_-_just_examples
但是,从您的大纲来看,我相信您的大型模型每帧都修改了顶点。此外,我相信你是说你使用每一帧来更新 GPU 端的顶点/索引数据glBufferData
。
更有效的方法是映射索引/顶点缓冲区并仅修改需要更改的内容,而不是每帧重置数据。
C++
为此,您需要映射缓冲区并获取 CPU 端仅写入缓冲区;
void* result = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY)
然后,您可以重写需要更改的值。完成此操作后,只需释放指针即可更新;
glUnmapBuffer(GL_ARRAY_BUFFER);
可以将void*
转换为顶点数据结构,然后像顶点数据数组一样进行修改。例如;
m_Buffer = (VertexData*)result;
另外,请注意,glMapBuffer
将等到 GPU 完成缓冲区使用完毕。如果您不想要同步写入,请使用glMapBufferRange
;
void* result = glMapBufferRange(GL_ARRAY_BUFFER, 0, getSize(), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_RANGE_BIT)
以下是此方法的规范,说明和教程。阅读它们并充分了解正在发生的事情将是有益的。
glMapBuffer: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBuffer.xhtml
glMapBufferRange: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBufferRange.xhtml
缓冲区映射:https://www.khronos.org/opengl/wiki/Buffer_Object#Mapping
缓冲流:https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming