如何在没有性能问题的情况下渲染大型对象



我有 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

相关内容

最新更新