如何将图像后处理着色器的结果添加到场景中
Posted
技术标签:
【中文标题】如何将图像后处理着色器的结果添加到场景中【英文标题】:How to add the result of an image postprocessing shader to the scene 【发布时间】:2012-10-25 19:29:07 【问题描述】:我有一个 opengl 上下文,我在其中渲染了几个线框图元。我想在其中一些(不是全部)上应用一些后期处理效果(例如模糊、绽放)。为了实现这一点,我定义了一个带有附加纹理(颜色缓冲区)和渲染缓冲区(深度缓冲区)的屏幕外帧缓冲区。然后,我执行以下操作:
-
绑定屏幕外缓冲区
设置透视图
绘制我想要模糊的线框图元
取消绑定屏幕外帧缓冲区并绑定“主”帧缓冲区
进一步绘制不应进行后处理的图元
设置正射视图
设置后处理着色器,将屏幕外缓冲区的纹理作为统一参数传递绘制一个全屏四边形
显示主机缓冲区的内容
问题是,通过将纹理渲染到屏幕外缓冲区并将结果用作 2D 四边形的纹理,我丢失了深度信息,整个场景看起来并不真实。
所以我的问题是,如何将我的深度缓冲区合并到帧缓冲区?或者将模糊或其他片段着色器效果应用于复杂 3D 场景的常用方法是什么?
【问题讨论】:
【参考方案1】:专门解决这个问题:
所以我的问题是,如何将我的深度缓冲区合并到 帧缓冲区?
没有什么可以阻止您在不同的 FBO 之间共享 附件(如果它们是纹理)(通过 glFramebufferTexture2D
)。这甚至适用于深度/深度模板缓冲区。 afaik 在 GL3 中甚至可以使用不同大小的附件。
如果您稍后需要主帧缓冲区(可见窗口)中的深度信息,您可以使用Framebuffer Blitting 复制它。 blit 操作非常快。
有很多方法可以处理渲染顺序。个人喜好/灵活性/性能。由于灵活性,我个人尽可能在 FBO 中做尽可能多的事情,并在需要时进行优化。最终的颜色结果也通过 blit 移动到帧缓冲区。
我在某些 linux 驱动程序上以及在某些情况下在 OS X 下共享深度附件(或一般附件)时遇到了问题,并且最终使用 blit 而不是共享深度附件也取得了巨大成功。
【讨论】:
【参考方案2】:我会使用早期深度测试来实现这一点。这个想法是,您首先将整个场景渲染到深度缓冲区中,即没有颜色写入。接下来进行颜色传递,在此禁用深度写入并使用相同的转换进行深度测试以确保相等。这为您提供了所需的隐藏表面去除。像你已经概述的那样进行颜色传递。现在通过覆盖模糊的图片,它应该看起来没问题(有一些病理情况可能会破坏,但这些可能会使用一些模板缓冲区技巧来修复)。
顺便说一句,您不需要为全屏四边形顶点着色器设置投影。只需通过顶点位置并使用坐标 (-1,-1) (1,-1) (1,1) (-1,1) 作为顶点。
【讨论】:
以上是关于如何将图像后处理着色器的结果添加到场景中的主要内容,如果未能解决你的问题,请参考以下文章
Sprite Kit - 使用 Switch Case 将随机 Sprite 节点添加到场景中
如何将 3D 模型添加到场景中以使它们具有特定的 XYZ 位置?
三个JS:如何使用PNG纹理将Point Light添加到场景中?