【问题标题】:How to redraw only an invalidated part of OpenGL context? (for 2D GUI rendering)如何仅重绘OpenGL上下文的无效部分? (用于 2D GUI 渲染)
【发布时间】:2014-03-18 02:40:26
【问题描述】:

我正在使用 OpenGL 来优化 GUI 渲染。渲染整个场景时效果很好,但这不是最佳的,因为通常只有一小部分发生了变化。所以我尝试了这个:

    glReadBuffer (GL_FRONT);
    glDrawBuffer (GL_BACK);
    glCopyPixels (0, 0, sz.X, sz.Y, GL_COLOR);
    glFlush();

这应该将前端缓冲区复制到后端缓冲区,以便之后我可以只更改使用 glViewport 限制的部分。不幸的是,当场景改变时,看起来 glCopyPixels 命令是在实际渲染之后执行的,因此原始内容的字母排序与新图形混合。

怎么了?还是有更好的方法来做到这一点? (作为记录,当我什么都不做时,前缓冲区开始闪烁,后缓冲区和类似的东西......)

【问题讨论】:

  • 模板化 gui 元素怎么样?

标签: opengl user-interface invalidation


【解决方案1】:

但这不是最优的

是什么让你这么想? OpenGL 和现代 GPU 的设计基础是,在最坏的情况下,无论如何您都必须重新绘制整个事物,并且在这种情况下事物也应该表现良好。

或者有更好的方法吗?

是:重绘整个场景。 (或者我下面的建议)

对于现代低端 GPU 来说,每秒可以轻松地将数千万个三角形投射到屏幕上,2D GUI 的几百到一千个三角形是可以忽略不计的。

实际上,与重绘所有内容相比,您的复制内容可能对性能的影响更糟,因为从前端缓冲区复制到后端缓冲区的性能不是很高,并且会导致严重的同步问题。

如果您想缓存内容,您可以将您的 GUI 拆分为单独的内容小部件,您可以使用 FBO 将其单独绘制到纹理中 - 以小部件可能重叠的方式设计它。如果其内容发生变化,则重绘一个小部件。要绘制整个窗口,您只需将整个窗口内容从纹理重新绘制到主帧缓冲区中。

【讨论】:

  • 我原本是这么想的,但事实并非如此。问题不是GPU,而是CPU! GUI 可能包含相当多的原语,并且需要时间来准备所有内容。对我来说,主要目标是减轻 CPU 负担。不幸的是,我发现当重绘所有内容并说 30% 的 GUI 反复失效时,软件仿真变得比 GPU 更快!显而易见的原因 - 当只渲染一小部分时,大多数小部件保持不变。
  • @VojtěchMeldaMeluzín:如果你受 CPU 限制,那你就做错了。我会把钱花在使用即时模式绘图 (glBegin...glEnd) 和一些准备开销上,这些开销很容易被缓存。
  • “即时模式绘图”是什么意思?确实或多或少是准备开销,但它不能被缓存。正如我所说,我们谈论的是一个非常复杂且不断变化的 GUI,而不是简单的 3D 场景。
  • @VojtěchMeldaMeluzín:如果它是一个不断变化的 GUI,那么这更有理由走完整的重绘路线。看看你的一些代码真的很有帮助。
  • 好吧,我只能说 GUI 对于任何类型的缓存来说都太复杂了。此外,将FB复制到BB不是完全相同的事情吗?轻松缓存。无论如何,现在当我让它工作时,它需要的 CPU 比重绘所有东西少 5 倍,所以我认为它是成功的 ;)。
【解决方案2】:

好吧,看来这解决了问题:

    glDisable( GL_BLEND ); 

我不知道为什么,但它看起来像是在混合数据之前,尽管我在文档中没有找到任何关于它的信息,而且“glCopyPixels”似乎不应该这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多