基于物理的阴影-环境/间接照明


15

在研究了M. Pharr和G. Humphreys的PBRT之后,我实现了基于物理的路径跟踪器。现在,我正在尝试使用OpenGL ES(在iPhone应用程序中)将基于物理的渲染应用于实时图形。

我想开始将Oren-Nayar和Cook-Torrance用作漫反射和镜面BRDF,但是我有一个问题:如何为间接照明建模?

在路径跟踪器中(如pbrt中包含的那样),从路径跟踪算法“自动”提供间接/环境光,因为它遵循光线的路径,并考虑了直接和间接照明。

如何使用OpenGL ES编写的基于物理的渲染中的间接照明建模,以便使用实时计算机图形?

Answers:


39

实时图形部署了各种近似值,以处理模拟间接照明的计算开销,并在运行时性能和照明保真度之间进行权衡。这是一个活跃的研究领域,每年都会出现新技术。

环境照明

在最简单的范围内,您可以使用环境照明:全局的全向光源,适用于场景中的每个对象,而无需考虑实际光源或局部可见性。这一点都不准确,但是非常便宜,艺术家可以轻松调整,并且可以根据场景和所需的视觉样式看起来还不错。

基本环境照明的常见扩展包括:

  • 使环境颜色有方向性地变化,例如使用球谐函数(SH)小的立方体贴图,并基于每个顶点或像素的法向矢量在着色器中查找颜色。即使没有直射光到达,也可以在不同方向的表面之间进行视觉区分。
  • 应用环境光遮蔽(AO)技术,包括预先计算的顶点AO,AO纹理贴图,AO域屏幕空间AO(SSAO)。所有这些方法都是通过尝试检测不易反射间接光的区域(例如孔和缝隙)并使那里的环境光变暗来进行的。
  • 添加环境立方体贴图以提供环境镜面反射。具有良好分辨率(每面128²或256²)的立方体贴图可以说服曲面,光泽曲面上的高光。

烤间接照明

可以说,技术的下一个“级别”包括烘焙(离线预先计算)场景中间接照明的某种表示形式。烘烤的优点是您可以以很少的实时计算费用获得相当高质量的结果,因为所有硬部件都在烘烤中完成。折衷是烘烤过程所需的时间会损害关卡设计人员的迭代速度;需要更多的内存和磁盘空间来存储预先计算的数据;实时更改照明的能力非常有限;而且烘焙过程只能使用静态关卡几何体中的信息,因此将忽略动态对象(例如角色)的间接照明效果。尽管如此,如今的AAA游戏中仍广泛使用烘烤照明。

烘焙步骤可以使用任何所需的渲染算法,包括路径跟踪,光能传递,或使用游戏引擎本身来渲染立方体贴图(或半立方体)。

结果可以存储在关卡中应用于静态几何的纹理(光照贴图)中,和/或还可以将其转换为SH并存储在体积数据结构中,例如辐照量(每个texel存储一个SH探针的体积纹理)或四面体网格。然后,您可以使用着色器从该数据结构中查找和插值颜色,并将其应用于渲染的几何体。体积方法允许将烘焙的照明应用于动态对象以及静态几何体。

光照贴图等的空间分辨率将受到内存和其他实际限制的限制,因此您可以使用一些AO技术对烘焙照明进行补充,以添加烘焙照明无法提供的高频细节并响应动态对象(例如,使移动的角色或车辆下的间接光变暗)。

还有一种称为预计算辐射转移(PRT)的技术,该技术可扩展烘焙以处理更多动态光照条件。在PRT中,您无需烘焙间接照明本身,而是将传递函数从某些光源(通常是天空)烘焙到场景中所产生的间接照明。传递函数表示为一个矩阵,该矩阵在每个烘烤采样点处从源SH系数转换为目标SH系数。这允许改变照明环境,并且场景中的间接照明将合理地响应。《孤岛惊魂3》和《孤岛惊魂3》使用此技术实现了连续的昼夜循环,间接照明根据一天中的每个天的天空而变化。

关于烘烤的另一点:对于漫反射和镜面间接照明,具有单独的烘烤数据可能会有用。立方体贴图在镜面反射方面比SH更好(因为立方体贴图可以具有更多的角度细节),但是它们也占用更多的内存,因此您不能像SH样本那样密集地放置它们。通过试探性变形立方体贴图以使其反射感觉更贴近其周围的几何体,可以使用视差校正来弥补这一点。

完全实时的技术

最后,可以在GPU上计算完全动态的间接照明。它可以实时响应灯光或几何形状的任意变化。但是,再次需要在运行时性能,照明保真度和场景大小之间进行权衡。其中一些技术根本需要强大的GPU才能工作,并且仅对于有限的场景大小才可行。它们通常也仅支持间接反射的单次反射。

  • 动态环境立方体贴图,其中使用围绕选定点聚类的六个摄像机在每帧中重新渲染立方体贴图的面,可以为单个对象提供良好的环境反射。例如,这通常用于赛车游戏中的玩家汽车。
  • 屏幕空间全局照明,SSAO的扩展,在后期处理过程中收集屏幕上附近像素的反射光。
  • 屏幕空间光线跟踪反射是通过后遍中的深度缓冲区光线行进来进行的。只要反射的对象在屏幕上,它就可以提供高质量的反射。
  • 即时光能传递的工作原理是使用CPU将光线跟踪到场景中,并在每个光线命中点放置一个点光源,该点大致代表该光线在各个方向上的出射反射光。然后,GPU以通常的方式渲染这些称为虚拟点光源(VPL)的光源。
  • 反射阴影贴图(RSM)与即时光能传递相似,但是VPL是通过从灯光的角度渲染场景(如阴影贴图)并将VPL放置在此贴图的每个像素上而生成的。
  • 光传播体积由放置在整个场景中的SH探针的3D网格组成。RSM被渲染并用于将反射光“注入”到最靠近反射表面的SH探针中。然后,类似洪水填充的过程将来自每个SH探测器的光传播到网格中的周围点,其结果用于将照明应用于场景。该技术也已经扩展到体积光散射
  • 体素圆锥跟踪通过对场景几何体进行体素化(可能使用变化的体素分辨率,在相机附近更精细,而在较远处更粗糙)来工作,然后将来自RSM的光注入到体素网格中。渲染主场景时,像素着色器通过体素栅格执行“圆锥轨迹”(半径逐渐增大的射线行进器),以收集入射光以进行漫反射或镜面阴影。

由于将问题扩展到实际场景大小或其他限制,这些技术中的大多数如今尚未在当今的游戏中广泛使用。屏幕空间反射是一个例外,它非常流行(尽管对于屏幕空间部分发生故障的区域,它通常与多维数据集贴图一起用作备用)。

如您所见,实时间接照明是一个巨大的话题,即使这个答案(相当长!)也只能提供10,000英尺的概览和上下文,以供进一步阅读。哪种方法最适合您,将在很大程度上取决于特定应用程序的详细信息,您愿意接受哪些约束以及需要投入多少时间。


嗨@Nathan,谢谢您的详细回答。我知道这是一个很大的话题(也是一个很大的研究课题)。最大的问题是在线文档是零散的,很难找到合适的方法。我的项目是goo.gl/Fgo21x:BRDF查看器(受WDAS查看器启发),用于显示最常见的基于经验和基于物理的BRDF模型,并支持使用光谱数据(三刺激值)进行颜色计算。这是研究OpenGL的教育项目。
法布里齐奥·杜罗尼

我认为最好的第一种方法是使用您提到的通用扩展名:SH或小立方体贴图+环境立方体贴图(用于反射和折射)。你怎么看待这件事?(我在不眠之夜下班后正在开发此应用程序:)。再次感谢您收集以上链接的资源(我现在有很多材料需要研究)。
法布里齐奥·杜罗尼

@FabrizioDuroni是的!对于BRDF查看器,简单的定向环境加上环境立方体贴图应该很棒。
内森·里德

也许这属于您的类别之一,但是从技术上讲,老式的多维数据集渲染到所有面孔不是一种完全实时的技术吗?另外,是否还可以使用用于散射反射的环境立方体贴图来增强基本环境?

@racarate对不起,我花了一段时间回答,但是的,你是对的!我想我想提一提,但是忘了。:)无论如何,我添加了它。(我确实提到在第一个要点上使用立方体贴图进行扩散。)
内森·里德

5

这是实时CG中仍然存在的主要“难题”,并且正在进行大量研究来解决它。

最大的障碍是,在光栅图形中,场景的每个组成部分都是“在真空中”渲染的-每个三角形都在不参考场景中其他三角形的情况下进行渲染,像素也是如此,这与光线追踪方法不同每个光线都可以访问内存中的整个场景。因此,实时程序员需要使用技巧性的技巧来进行诸如反射和阴影之类的操作,这同样适用于全局照明。

一种便宜的运行时方法是使用烘焙的光照贴图,在该方法中,您先运行慢速但很棒的操作,例如光能传递或脱机进行路径跟踪,然后将照明信息与常规顶点数据一起保存。这对于静态几何非常有用,但是一旦添加移动对象,就会出现问题。Michal Iwanicki很好地介绍了他们如何解决“ The Last of Us”。

球形谐波在游戏引擎中被大量使用以表示间接光。它们基本上是整个球体表面的傅立叶变换,通过丢弃高频分量,您可以得到视觉上令人愉悦的,大多数是准确的环境照明,每种颜色仅9个系数。例如,Unity使用SH在场景中的各个点烘烤“光探测器”,然后可以在附近的探测器之间插入运动对象,以获取其位置处的间接光的近似值。罗宾·格林(Robin Green)的论文基本上就是这种技术的圣经,但它的工作量很大。

目前最热门的技术似乎是Voxel Cone Tracing,它不涉及任何预烘焙步骤。我自己不太熟悉它,但是据我所知,它涉及将场景体素化为低分辨率的Minecraft风格的世界,将体素放置到像八叉树这样的可快速穿越的空间结构中,然后将其宽广从每个点发出光线(锥体),并检查它们击中了哪些体素以收集反射光。NVidia目前正在大力推动这一工作,这里这里都有论文。

希望有帮助:)


0

路径跟踪是一种在计算上非常昂贵的算法,不适合实时。PBRT的体系结构也不适合实时,PBRT的主要目标是使用无偏蒙特卡洛积分来解决渲染方程。有关更多信息,请参见https://en.wikipedia.org/wiki/Unbiased_rendering

如果没有很多优化和约束,我怀疑您能否在移动设备上达到不错的性能。

无论如何,路径跟踪都可以在OpenGL中实现,我建议研究一下功能强大的计算着色器。与Desktop GL相比,OpenGL ES 3.1支持具有一些次要限制的计算着色器。

通读此页面以获取更多信息:https : //github.com/LWJGL/lwjgl3-wiki/wiki/2.6.1.-Ray-tracing-with-OpenGL-Compute-Shaders-(Part-I)

祝你好运!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.