什么是光线追踪?看看你周围,那些被光束照亮的物体。 从目光后方的光束,到光与之交互的物体的路径,就是光线追踪。
EA 的 3A 引擎 Frostbite,支持光线追踪。 Unity 和 Unreal 等主流商业引擎后来也陆续支持微软 DirectX Raytracing。 实时光线追踪技术元年:2018 年。
被这两个文章深深的吸引了。https://yangwc.com/
1980 年 Turner Whitted 发表了论文提出了最经典的光线追踪渲染方法。 可以看到,眼睛射出的光线,经过了两次折射一共获得了模型中三个点的光影信息,或许它还可以获取更多,但实际上这已经比光栅渲染真实很多了。 这可不是什么时间反演,其实主要是基于物理学中,光路可逆的规律,与其计算全局的光路图,不如只计算我所希望看到的那一部分像素颜色。
为了更能够接近真实的物理世界,尤其是釉面反射。1984 年的 Cook 提出随机理论,也就是分散式光线追踪(Distribution Ray Tracing)。 釉面物体上的反射光强和方向将被分散成多条光线,那么该点的颜色也会受到多个方向的物体影响。 如图,像素采集点反射后有三条光线,只有三分之二可以到达该场景的光源,所以该点的亮度会比完全暴露在光源下的部分暗三分之一左右, 虽然不够精确,但这同样也是比较符合实际物理世界规律的。
图形渲染的目标和物理世界殊途同归 —— 简化,统一所有的理论便是又一次的本质飞跃。 1986 年 Kajiya 提出的渲染方程,把表面自发光、入射光、材质散射函数和几何项统一到同一个积分框架中。
我们眼睛在一个模型上所看到的颜色,受到四个方面的影响,分别是模型自身发光、模型受到光照的情况、模型的材质(即反射能力)和模型的朝向。 可以看到和模型与接收光作用的这一项包括了后三者,并将这三者的影响进行球面上的积分,从而综合得到了整个空间的光线对这个模型颜色的影响。 这就是我们今天提到的光线追踪的核心了。
光线追踪算法是一种非常自然的技术,相比于光栅化的方法,它更加简单、暴力、真实。 与光栅化根据物体计算所在的像素的方式不同,光线路径追踪的方法是一个相反的过程,它在于用眼睛去看世界而不是世界如何到达眼中。 如下图所示,从视点出发向屏幕上每一个像素发出一条光线 View Ray,追踪此光路并计算其逆向光线的方向,映射到对应的像素上。 通过计算光路上颜色衰减和叠加,即可基本确定每一个像素的颜色。
所谓的实时光线追踪,就是随着摄像机视角的变动,后端需要实时发射追踪光线来重新计算光照信息,如果屏幕分别率很高,这个计算量是很大的, 对 GPU 的性能要求是很高的,如果性能达不到就会严重掉帧。而离线光线追踪不受实时帧率约束,可以用更高采样率和更多反弹次数来换取质量;在游戏生产管线里,它常被用于烘焙 Lightmap,影视离线渲染则可以直接生成最终画面。 所以当时游戏里更多是把光线追踪用于反射、阴影、AO 或全局光照的某些环节,并结合降噪和传统光栅化管线使用。NVIDIA Turing 架构引入硬件光追后,实时光线追踪开始进入游戏渲染流程,但距离所有场景全面依赖光追仍有距离。
关于光线追踪的基本原理,简单来说就是向场景发射 N 条光线,然后根据碰撞点的材质进行 BXDF,BRDF 的运算,然后(根据俄罗斯轮盘)再进行漫反射,镜面反射,或者折射,如此循环直到光线逃离场景或者到达最大反射次数,最后对 N 条光线进行蒙特卡洛积分即可获得结果。 对于实时光线追踪和离线光线追踪,这里发射光线的方式还是有些差异的:实时光线追踪是从视点发射光线,光线数量一般是屏幕的大小,比如屏幕是 1920*1080, 则需要发射 1920*1080 条射线,每条射线对应一个像素点,依照需求,可能要发射多次来采样平均得到理想的结果; 而对于离线光线追踪,每个静态物体都要根据光照 UV 生成 M 个 Patch(数量和 Lightmap 大小有关),每个 Patch 要向法线方向的半球发射 N 条射线(数量由用户采样数量决定),最终对 N 条射线进行蒙特卡洛积分,得到这个物体的 Lightmap。