微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

OpenGL 文本渲染 - 修改单个 VBO 或每个文本对象使用一个 VBO?

如何解决OpenGL 文本渲染 - 修改单个 VBO 或每个文本对象使用一个 VBO?

我正在制作一个小型 2D 引擎/游戏来学习 OpenGL(使用 OpenGL 330 核心),并且我正在尝试抽象掉大多数 OpenGL 函数调用

现在,我正在研究如何最好地处理文本渲染。我有一个字体图集工作,但我不知道如何处理文本的顶点。现在,我有一个 Renderer 类,它有一个 drawText(const Text& text) 方法,如下所示:

const std::vector<Text::Vertex>& vertices = text.getVertices();
glBufferData(GL_ARRAY_BUFFER,sizeof(Text::Vertex) * vertices.size(),vertices.data(),GL_STREAM_DRAW);
glDrawArrays(GL_TRIANGLES,vertices.size());

我不确定这是否好,因为我正在为每个绘制的 Text 对象重新定义 VBO 的内容,并且每帧可能绘制多个 Text 对象。>

注意:我没有使用 Text 进行批量渲染,因为:

  • 这是一个简单的 2D 游戏,所以我宁愿等待绘制调用成为一个实际问题再优化它们
  • Text 可以通过多种方式更新(即在工具提示旁边可见、悬停时更改颜色等),这需要我修改包含批处理顶点数据的单个 VBO

因此,由于我的 Text 对象在转换时非常不稳定,我是否应该为每个实例设置一个 VBO,以便在适当的时候进行修改,并在我在屏幕上绘制文本时绑定一个新的 VBO?

我的理解是,如果我这样做,每次绑定新的 VBO 时我都需要手动调用 glVertexAttribPointer() 方法,因为绑定新的 VBO 本身不会影响绘制调用

或者我应该只有一个 VBO 并不断更新其值?

我不确定哪种方法是首选方法,而且我读到重新绑定 VBO 可能很昂贵,但我不确定覆盖它们的数据是否更快/更慢。另外,查看一个真实世界示例的 SFML 源代码,他们似乎在每次绘制某些东西时都设置新的顶点(尽管他们的情况可能与我的不同,因为他们不使用 OpenGL 3+ 并且不做任何批处理渲染)。

解决方法

最好将文本渲染视为 vertex streaming 的一种形式,因为它就是这样。你应该假设你的文本每一帧都在改变,并且每一帧都更新它。由于文本不多,即使文本数据没有改变,流式传输文本数据也没什么大不了的。

鉴于您正在流式传输,处理此问题的最佳方法是通过映射。在开始寻找要渲染的文本之前,您已经映射了缓冲区。您将顶点数据写入每个字形的缓冲区。当您完成渲染文本时,取消映射缓冲区并绘制它。

现在,这假设纯文本绘制。也就是说,您不是在做 UI 的东西、用于窗口剪裁的视口剪裁等。如果是,那么事情会变得更加复杂,因为您将需要从缓冲区的不同部分发出多次绘制。但即使在这种情况下,您要做的就是为您的文本构建一个绘图列表,然后在写入所有字形数据后发布它们。

映射缓冲区。当您遍历需要绘制的文本时,将字形顶点数据写入映射指针。完成后,取消映射缓冲区并绘制字形。 (注意:可以随意使用 persistent mappinginvalidation techniques 来提高性能。并且您可能需要在缓冲区的区域之间进行乒乓操作,以免与 GPU 同步)。

这是关于内存分配,而不是绘制调用的数量。您应该选择一个足以绘制您需要的所有文本的缓冲区大小。

这里的要点是填充缓冲区,然后从中抽取。不要在同一个循环中填充和绘制,并且绝对不要在渲染过程中分配缓冲区对象。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。