opengl - 在OpenGL中更新纹理的有效方法

标签 opengl jogl

我想使用 OpenGL 渲染多个视频流。目前我正在使用 JOGL 提供的 glTexImage2D 执行并在 Swing 窗口上渲染。
为了更新每个视频帧的纹理内容,我调用 glTexImage2D。我想知道是否有任何更快的方法来更新纹理而无需为每一帧调用 glTexImage2D。

最佳答案

您将永远使用 glTexImage2D , 但不同之处在于数据来自缓冲区对象 ( what is this? ) 而不是来自指针。

更新纹理的慢点不是更新纹理,而是与当前绘制操作和 PCIe 传输同步(阻塞)。当您调用 glTexImage , OpenGL 必须等到它完成绘制它仍在读取纹理的最后一帧。在此期间,您的应用程序被阻塞并且什么都不做(这是必要的,因为否则您可以在 OpenGL 复制它之前修改或释放指向的内存!)。然后它必须复制数据并将其传输到图形卡,然后您的应用程序才能继续运行。
虽然无法使该过程更快,但可以使其异步运行,因此这种延迟几乎消失了。

对于视频帧,最简单的方法是 create a buffer name ,绑定(bind)它,reserve-initialize一次。
然后,在每个后续帧上,通过调用 glBufferData 丢弃初始化它使用空数据指针,并用 non-reserving 填充它调用,或通过 mapping the buffer's complete range .

你想要做这种奇怪的舞蹈而不是简单地覆盖缓冲区的原因是它不会阻塞。 OpenGL 将同步对缓冲区对象的访问,因此您不会在数据仍在读取时覆盖数据。 glBufferData使用空数据指针是告诉 OpenGL 您并不真正关心缓冲区并且您不需要相同的缓冲区的一种方式。所以它只会分配另一个并给你那个,继续阅读旧的,并在完成后 secret 交换它们。

由于已经使用了“同步”这个词,我将解释我的选择 glMapBufferRange在上面的链接中,实际上您想要映射整个缓冲区,而不是某个范围。为什么要这样?
即使 OpenGL 在使用上述丢弃技术时大多数情况下都可以避免同步,但有时它仍可能不得不这样做。
此外,它仍然必须运行某种内存分配算法来管理缓冲区,这需要驱动程序时间。 glMapBufferRange允许您指定其他标志,特别是(在以后的 OpenGL 版本中)一个表示“不同步”的标志。这允许一种更复杂但仍然更快的方法,在这种方法中,您创建一个两倍于您需要的大小的单个缓冲区,然后继续映射/写入下半部分或上半部分,告诉 OpenGL 根本不同步。然后,您有责任知道何时安全(可能是通过使用栅栏对象),但您要尽可能避免所有开销。

关于opengl - 在OpenGL中更新纹理的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21577964/

相关文章:

java - 修复具有多个视口(viewport)的窗口中的严重闪烁

matlab - 使用 opengl 硬件渲染器导出带有颜色条的 MATLAB 冲浪图会导致损坏的 png 文件

c++ - 将 QT5 与 glLoadGen 结合使用

opengl - 将我的场景渲染到帧缓冲区对象(FBO)然后将该 FBO 渲染到屏幕所需的步骤是什么?

java - 在可运行的jar中使用jogl,手动加载dll

java - 如何 : install JOGL for Eclipse in Mac OSX 10. 6?

java - OpenGL 3D 中的平滑模型移动

c++ - opengl中递归函数内部的时间延迟

c++ - 从 GLSL 中的数组初始化结构

OpenGL 最大 FBO 和 PBO