Opengl:基于着色器的渲染到帧缓冲区,然后是固定管道渲染
opengl: shaders-based rendering to a frame-buffer, followed by fixed-pipeline rendering
我有一个应用程序,它使用OpenGl的固定管道在屏幕上渲染图像以及一些GUI。在此之前,我想使用基于着色器的管道,对图像进行一些图像处理操作,并将其渲染为纹理。然后我将把这个纹理传递给现有的应用程序。基本上,当前流是这样的:
cpu image --> gpu texture --> fixed-pipeline processing --> display on screen
我想让它看起来像这样:
cpu image --> gpu texture --> rendering passes to enhance the image --> gpu texture --> fixed-pipeline processing --> display on screen
我的问题是:我如何在这些不同的操作模式之间切换?我已经看到了前面的一些问题(1,2,3,4),但没有一个回答我的具体问题。也许这只是解除顶点数组绑定的一个简单问题?
编辑
现在我对@Reto Koradi的问题有了一个很好的答案,我还有另一个问题:你知道这种模式改变需要多长时间吗?当我切换回固定管道时,是否有任何"冲洗"?从基于着色器的渲染切换回固定管道:
glUseProgram(0);
从FBO渲染切换回渲染到默认的framebuffer:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
可以在固定管道中使用顶点数组。但如果你想解除顶点数组/缓冲区的绑定,也是一样的。只需绑定0来释放你的绑定,例如:
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
编辑:回答关于开销的后续问题。
简单的答案是……视情况而定。根据平台/硬件的不同,某些操作的开销可能会有很大的不同。只要能用比较一般的话来回答:
- 我不知道最近制造的任何硬件仍然有完整的固定管道。过去5-10年间制作的所有东西都运行着色器。如果你使用传统的固定管道,驱动程序会为你生成着色器。当你切换到固定管道时,着色器生成可能会花费一些时间,但往往会进行大量优化(只要人们仍然运行旧的基准测试),并且很可能使用缓存的着色器。所以它应该不是很重要。 编译着色器是昂贵的。简单地切换着色器是低开销的。我在我工作的平台上以亚微秒的时间对其进行基准测试,与绑定顶点缓冲区相当。我想在其他平台上可能会更高,但例如现代游戏使用许多不同的着色器,并且能够以低开销绑定它们是至关重要的。
- 绑定/取消绑定顶点缓冲区的开销很低。并且在驱动程序中进行了大量优化,因为它对许多常用的基准测试有很大的影响,特别是那些没有产生足够的着色器负载来保持GPU完全繁忙的基准测试
- 绑定不同绘制目标的开销(例如从FBO切换到默认framebuffer)是高度依赖于平台的。但在大多数平台上,它至少是中等价格的,而且在某些平台上,它可能是一个相当糟糕的性能杀手。如果你不太频繁地切换,没有理由担心,但你肯定不希望这样做过于频繁。
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- IPC使用多个管道和分支进程来运行Python程序
- 这是我尝试让用户将值输入到数组中.然后将其隐藏为大量的星号
- boost::asio如何生成多个协同程序,然后加入它们
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 在std::thread中,joinable()然后join()线程安全吗
- C++:如何读取分离变量,然后读取向量
- 如何创建函数管道,以便函数一个接一个地运行?
- 为什么我的递归函数按降序打印,然后按升序打印?
- Gstreamer 管道从命令 lne 到 c 代码
- 等待整个 omp 块完成,然后再调用第二个函数
- CMake:如何将库 A 链接到库 B,然后将可执行文件链接到库 A
- 外壳包装器句柄/执行交互式命令管道C++ UNIX
- 如何存储用户输入的所有数据,然后在他们想要查看所有数据时显示它们
- '{'标记之前的预期类名,然后在预声明时无效使用不完整的类型'class class_name'
- 如何重复写入,然后读取,在管道中,就像打字到"cat | tr a-z A-Z"一样
- 从用户中读取整数并写入子管道,然后父管道从中读取
- Opengl:基于着色器的渲染到帧缓冲区,然后是固定管道渲染