计算机图形学入门19:光线追踪

1.前言

        前面几篇中说到的光栅化技术是一种速度很快但近似、质量较低的渲染方法,但实际使用中存在难以处理的问题,光栅化技术只能处理直接光照,不能很好地去表示软阴影(Soft Shadow)光泽反射(Glossy Reflection)间接照明(Indirect Illumination)等全局光照效果。如下图所示的几种光照效果。

        随着计算机硬件性能的提升,出现了光线追踪(Ray-Tracing),这种技术是准确的,并能较好地处理全局光照,提高渲染质量,但目前还不能完全替代光栅化技术。因为光线追踪技术的计算非常慢,在诞生以来更多被用来做离线渲染,比如三维动画、电影特效等等。

        游戏是需要实时计算的,因此直到近几年随着NVIDIA的RTX系列显卡的不断迭代,硬件光线追踪技术和游戏引擎功能的进步,现在的3A级游戏大作才慢慢支持了实时光线追踪技术(Real-Time Ray-Tracing)

2.光线追踪原理

        首先对计算机图形学中的光线做一些定义。

        1.光线一定沿着直线传播,不考虑其波动性。

        2.光线之间相交不会互相产生影响,同样不考虑其波动性导致的干涉、衍射等现象。

        3.光线从光源传播到眼睛(光线路径可逆,中途可发生反射和折射)。

        明白了光线的一些假设之后,想一想人为什么能看到不同的物体?是因为从物体表面上有光进入了人眼。那么能不能逆向思考一下,是不是也可理解为人眼发出了很多感知光线碰撞到了物体,所以可以看见呢?

        在很早之前很多人还真这么认为的。

        当然,这种观点是错误的,但是并不妨碍从中获取一些灵感,考虑一下对光线的第三条假设:光路可逆,所有进入到人眼的光,都可从人眼发出光按照原路反方向返回,那么利用这种模拟从人眼发射光线的方法不就可以还原出所有的光路了呢?

        这就是光线追踪的核心想法,以摄像机为起点通过虚拟屏幕中的每个像素发射一条光线,追踪每条光线在场景中的反射折射,查询光线与物体的交点,计算得到每个像素最终的颜色!如下所示。

光线投射(Ray Casting)

        1.通过每像素投射一条光线来生成图像。

        2.通过向光源发送光线来检查阴影。

3.Whitted-style光线追踪的步骤

        Whitted-style光线追踪算法是由Turner Whitted在1980年提出的,用于解决复杂曲面的反射折射效果,主要有以下两个步骤。

1.光线投射(Ray Casting)

        首先做几个假设:

        1、眼睛是针孔摄像机,假设为一个点

        2、光源假设是点光源

        3、反射折射是完美的(镜面反射)

        从人眼或摄像机向近投影平面上的每一个像素点发射一条光线,称为Eye Ray,判断与场景物体的交点,如下图所示:

        当然一条光线可能会与不止一个物体相交,但是考虑遮挡关系,只去找最近的交点(方便地解决遮挡问题,光栅化中则是通过深度缓存z-buffer解决遮挡问题),说明从摄像机中能够看到这个物体与光线的交点。

        接下来考虑这个点会不会被照亮,连接该交点和光源,这条线叫做Shadow Ray。如果这条连线之间有物体存在(有遮挡),就可以知道该交点在阴影之中。相比于光栅化的Shadow Mapping,光线追踪技术在着色时就可以计算阴影。如下图所示。

        如果这个点对光源可见,则证明光路有效,那么就可以记录这条光路上的能量,利用Blinn-Phong等光照模型对这个点进行局部光照计算,得到该像素的颜色,当遍历所有近投影平面上的像素就能得到一张完整的图像。

        但如果光线追踪仅仅是在第一步Ray Casting就停止的话,那么它的效果与局部光照模型是类似的,光线只是弹射一次。因此我们需要第二步,考虑光线的多次弹射,真正的考虑全局效果。

2.递归光线追踪(Recursive Ray Tracing)

        这一步才是Whitted-style光线追踪的核心,Whitted-style算法就是递归(Recursive)

        当光线与物体相交时,如果该交点处是不透明的漫反射材质,那么就在第一步Ray Casting就停止。

        如果该交点处是不透明的光滑镜面材质,那么光线便会发生反射并损失少量能量,继续沿光路传递寻找下一个碰撞物体,如下图所示。

        如果该交点处是透明的玻璃材质,那么除了反射之外,玻璃球内部也会发生光线的折射,反射光和折射光都会沿光路继续向前走,能量都有损失,如下图所示。Whitted风格就是在任意一个点可以继续传播光线。

        同时反射与折射出去的光线可能会与场景中的物体再次碰撞,发生第二次反射和折射等。

        递归光线追踪就体现在反射和折射光线上,当场景中有大量光滑镜面材质物体和透明材质物体时,光线会不断进行反射和折射,导致计算量失控,因此需要一定的递归终止条件,比如说允许的最大反射或折射次数为10。

        因此每一个像素点的颜色来自这样几种类型的光照:直接光照、间接反射光照,间接折射光照(如果有折射的话),下一步将这些光路上的所有交点与光源连接,称这些线为Shadow Rays(因为可以用来检测阴影),计算这些所有交点的局部光照模型的结果,将其按照光线能量权重累加,最终得到近投影平面上该像素点的颜色!

        之所以用光线能量权重,是因为光线在每次反射和折射之后都有能量损耗的,因此递归层级越多的折射和反射光贡献的能量越小, 例如反射权重系数为0.7,那么第一次反射折损30%,第二次反射折损1-(70%x70%),依次类推。

        另外如果反射或折射光线没有碰撞到物体,一般会终止该光线并返回一个背景色。

        这就是一个考虑全局效果的光照模型了,因为不仅仅考虑了直接光源的贡献,还考虑各种反射与折射光线的贡献,最终得到的效果如下。

4.光线与平面的交点算法

        光线追踪通过光线与物体表面相交,进行一系列的操作,得到最终效果。那么如何求出光线与平面的交点呢?

4.1光线方程(Ray Equation)

        光线是一条射线,数学意义上可以表示为一个原点和一个方向,考虑到光线传播的时间参数,因此一般表示为以下形式。

        对于光线上任意一点 r,在 时间,都可以表示为从起始位置o,加上 乘以向量d。对于来讲,由于这里是射线,而且 表示时间,所以 不能取负数值。

4.2 光线与隐式曲面相交

        如何计算光线与隐式曲面的交点的方法,以一个球体为例,二者表示方程如下图所示,P为交点。

        所谓交点就是在光线上又在球上,所以P点即满足光线方程,又满足球体方程。把 P=O+td 代入球体,然后利用一元二次方程的解法即可得到参数 t 值。

        同样的根据 b^{2}-4ac 的正负关系,即可判断光线与球是一个交点还是两个交点又或是没有交点。

        虽然这里只举了对一个球的隐式曲面交点的计算,对于所有其他隐式曲面过程都是类似的,只要将光线方程代入求解 t 即可(t大于0且必须是实数),如下图所示。

4.3 光线与显式曲面求交

        当然,真正在图形学中大量运用的其实是显式曲面,更具体来说就是许许多多个三角形,因此如何判断一条光线与显式曲面的交点,其实也就是计算光线与三角形面的交点。

        通过光线与三角形求交点,可以判断交点是否在物体内外部。在交点处任意找一个方向发射一条射线,与物体如果有奇数个交点,那么该交点在物体内部,否者在外部。前提是物体是封闭的,没有空洞。

        光线与三角形怎么求交点?

        先来分析一下。

        1.最简单的想法,让光线与每个三角形相交。

        2.但是物体表面三角形很多,计算会很慢(加速?)。

        3.注意:光线与三角形可以有0、1个交点(忽略多个交点)。

        对于任意一个三角面来说,它一定处于一个平面之上,只需求出光线与平面的交点,再判断该交点是否在三角形内,就可以得到光线是否与三角形面相交的结果了。如下图所示。

        对于任意一个平面,可以定义成一个法线以及平面上的一个点,也就是立体几何中的点法式,这个点与平面上任意一点连成线与法线垂直。用如下图中的式子表达。

        这样其实已经成功把对显示曲面的求交转化为了类似隐式曲面求交的方式。

        首先给出如何计算光线与平面交点的过程。同理,这个交点在光线上又在平面上,所以将 P=O+td 带入式子,可得 t

        得到参数 t 之后,自然可以计算出交点,并且再去计算出重心坐标就能判断该交点是否在三角形内了,但是这种方法略显繁琐,能不能一步就得到结果呢?

        人们发现了一种方法,如下图所示。

        直接将点的形式用重心坐标的形式表示,随后利用克莱姆法则求解线性方程组即可得到 b_{1}b_{2}的值,那么只要该点的重心坐标1-b_{1}-b_{2}b_{1}b_{2}都是非负数,那么就说明该点在三角形内。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YanisWu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值