| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> 计算机图形学六:光线追踪-Ray Tracing -> 正文阅读 |
|
[游戏开发]计算机图形学六:光线追踪-Ray Tracing |
阴影映射(Shadow Mapping)其实这应该是属于纹理映射这一块的知识,但是闫老师当时没说,知道几何的最后一块才说,因为这又与光线追踪有关,所以我就把它记录于此。 前面我们说过着色,它仅仅考虑着色点与光照这两者,忽略了其他物体甚至自身对于着色点的遮挡关系,这显然是不对的。光源被遮挡,必然会产生阴影,而光栅化并不能很好的表示这种阴影。而阴影映射可以较好的解决这个问题。 再来一遍废话,为什么会有阴影? 因为光源照射不到,更具体点,摄像机能看到的地方,光源“看”不见。 而这正是启发阴影贴图这种做法的动机,接下来我们便来看看详细过程是怎么样的。 第一步,把光源当做一个摄像机让它去看,去渲染整个场景一遍从而得到从光源视角的深度Buffer,记为 d m a p d_{map} dmap?。它被记录在 shadow map中。如图中就记录了四个点的深度 第二步,从设定好的摄像机位置去真正的渲染场景得到摄像机视角的深度Buffer,记为 d d d 第三步,将所有摄像机视角可见点,利用光源视角下的那一套投影矩阵,重新投影回光源,找到与shadow map上对应的 d m a p d_{map} dmap? 如果该点的 d m a p d_{map} dmap? 与 d d d 相等,则说明此点可被光源与摄像机共同看见,因此不在阴影中,如下图橘色线条这种情况: 如果该点的 d m a p d_{map} dmap? 小于 d d d ,则说明此点不可被光源看见,但摄像机看得见,即该点前方有物体遮挡,因此在阴影中,如下图红色线这种情况: 如此便能确定每个可见像素点是否在阴影之中了,如果在阴影之中就不去计算Blinn-Phong中的镜面反射项与漫反射项。效果如下图: 什么是硬阴影?什么是软阴影?软硬阴影示意如下,上方棱角分明为硬阴影,下方为软阴影: Whitted-Style 光线追踪首先要清楚的是,我们为什么需要光线追踪? 在光栅化着色这一章节中,我们介绍了Blinn-Phong反射模型,但这个模型的 bug 之处也是十分明显的,它只考虑了光源到物体的直接光照,其它的间接光照一概不考虑,物体之前的遮挡关系也不考虑。这显然是不对的,例如: 原理光线追踪,顾名思义,核心是光线。首先对光线做一些假设: 1. 光线一定沿着直线传播 人为什么能看到不同的物体?是因为从物体表面上有光进入了人眼。那由上述的假设是不是也可理解为人眼发出了很多感知光线碰撞到了物体,所以可以看见呢?在古代可还真就有不少人这么想: 第一步:Ray Casting 从人眼(摄像机)向近投影平面上的每一个像素点发射一条光线,判断与场景物体的交点,示意图如下: 第二步 Recursive (Whitted-Style) Ray Tracing 考虑第一步中所做的Ray Casting,该条光线第一个与圆球物体相交,假设该圆球是一个玻璃球,那么便会发生镜面反射,如图: 从图中可以见到,不仅仅是与圆球相交的那一点可以贡献光到达眼睛,折射与反射之后再与物体相交的点也可以贡献光(光路可逆原理)。简而言之,除了直接从光源照射到圆球交点再沿着 eye rays(第一条发射的光线)到眼睛中,也可能存在这样一种情形,有光照射到其他物体,再沿着eye rays的反射或折射的光线方向传回人眼。 因此每一个着色点的颜色贡献来自这样种几类型 直接光照,反射方向间接光,折射方向间接光(如果有折射的话) 下一步将这些所有交点与光源连接,称这些线为shadow rays(因为可以用来检测阴影),计算这些所有点的局部光照模型的结果,将其按照光线能量权重累加,最终得到近投影平面上该像素点的颜色。这就是一个全局光照模型,因为不仅仅考虑了直接光源的贡献,还考虑各种折射与反射光线的贡献。 以上就是光线追踪的整个过程,还有额外几点要注意的:
参考伪代码如下:
光线与物体求交上述Whitted-Style模型中有一个重要的问题,我们如何得到光线与物体的交点呢?在讨论之前,我们先对光线进行一个定义。 光线的表示方法将每一条光线想象成一条射线,那么每一条光线都会由起点及方向这两个属性所固定,如下图所示: 光线与隐式曲面求交首先计算光线与隐式曲面的交点的方法,以一个球体为例,二者表示方程如下: 虽然这里只举了对一个球的隐式曲面交点的计算,对于所有其他隐式曲面过程都是类似的,只要将光线方程代入求解
t
t
t 即可: 光线与显示曲面求交在几何中提到过,最常用的曲面表示形式,是通过定义各个多边形面的顶点以及顶点之间的连接关系得到许许多多的三角形面。因此如何判断一条光线与显示曲面的交点,其实也就是计算光线与三角形面的交点。进一步想,直接求光线是否与三角形有交点可能比较难,我们可以通过先求光线是否与该三角形所在平面有交点,再判断交点是否在三角形内来进行判断。对于任意一个平面,可以用如下图中的式子表达: N \bold{N} N 是平面的法线, p ′ \bold{p'} p′ 是平面内的一点(这两个元素就可以确定一个平面了,想想看是不是这样)。 而 a x + b y + c z + d = 0 ax+by+cz+d=0 ax+by+cz+d=0 是高数中对平面的一般化表示。那么到这里其实已经成功把对显示曲面的求交又转化为了类似隐式曲面求交的方法。 首先给出如何计算光线与平面交点的过程: 至此,whited-style光线追踪的第一个小问题得以解决。相比与光栅化中所使用的的Blinn-Phong模型,光线追踪显著了提升了图像质量,但随之而来的问题是渲染速度过慢。因为在判断光线与场景交点的时候,需要去进行所有三角形面与光线的求交,而且这仅仅是对一个像素而言。那么总体来说光是进行光线与三角形的求交这样一个计算过程就一共要: 如何加速轴对齐包围盒(Axis-Aligned Bounding Box)AABB(Axis-Aligned Bounding Box)的提出是十分自然的,当有的光线显然不会与一个物体相交的时候,那么自然也没有必要去遍历该物体的所有三角形面,因此利用一个包围盒包住该物体,在与该物体的三角面计算求交之前先判断光线是否与包围盒相交,倘若连包围盒都与光线没有交点的话,那么显然不会与物体的三角面有交点。 我们以2D的AABB为例,因此只有
x
,
y
x,y
x,y 两对平面,3D情况可类推: 我们得到了光线与一对 x x x 平面的交点,与一对 y y y 平面的交点,究竟哪些点才是真正与盒子的交点呢?要明白: 1. 只有当光线进入了所有的平面才算是真正进入了盒子中 所以对每对平面的
t
m
i
n
t_{min}
tmin? 和
t
m
a
x
t_{max}
tmax? 做如下运算: 光线一定会与包围盒有交点吗?显然不是,那么什么条件下才会有交点呢? 当
t
e
n
t
e
r
<
t
e
x
i
t
t_{enter}<t_{exit}
tenter?<texit? 的时候,光线所在直线一定在盒子中待过一段时间,也必然存在交点。但光线并不是直线,而是射线,除了保证了光线所在的直线在盒子里待过一段时间,还要考虑实际物理意义,具体如下: 均匀网格(Uniform Grids)现在已经可以通过事先对每个物体求一个包围盒,在与三角形面求交之前先对包围盒求交,达到不错加速效果。但是考虑这样两个极端情况: 1. 整个场景只有一个极其复杂的单一人物模型,那么只对这一个物体做包围盒的话,相当于对效率没有任何提升 基于以上两点考虑,AABB并不应只局限于以物体模型为单位,可以更加精细的考虑到以面为单位。另外对于场景的许许多多包围盒来说应该要有一种数据结构将其统领起来。因此如何更好的划分场景形成不同的AABB,使得划分之后的AABB能够更好的加速光线追踪,这就是接下来要考虑的问题关键! 最简单的划分方法,均匀网格。 第一步对所要考虑的场景找一个包围盒,第二步均匀划分这个大包围盒成网格,第三步在每个重叠小包围盒上存储物体模型信息,最后根据光线的方向与判断出所有相交的方格(这一步可以利用bresenham算法,移步至直线光栅化了解),倘若方格中存储有物体,再进一步与方格中的物体模型或是面求交。 因此这种方法最适合的场景就是空间中均匀布满了三角形面,如下图这种场景: KD-Tree空间划分(Spatial Partitions)一些常用的空间划分方法: 第二种KD-Tree,其每次将空间划分为两部分,且划分依次沿着 x ? a x i s , y ? a x i s , z ? a x i s x-axis,y-axis,z-axis x?axis,y?axis,z?axis (保持最规整的空间区域),如图中所示,第一次横着将2维空间分为上下,第二次再竖着将上下两个子空间分别划分为左右部分,依次递归划分,终止条件与八叉树类似。 第三种BSP-Tree,其与KD-Tree类似,唯一不同的是划分不再沿着固定一轴,可以任意方向划分,缺点自然是划分的空间没有规则性,求交困难。 为什么这种分法叫树?看下面的KD-Tree就可以知道答案。 第一步将空间分为两部分,第二步对左右两个子空间换个方向再分为两部分(这里只画出了有半部分) 1. 依次沿着
x
?
a
x
i
s
,
y
?
a
x
i
s
,
z
?
a
x
i
s
x-axis,y-axis,z-axis
x?axis,y?axis,z?axis 划分,使得空间被划分的更加平衡 当KD-Tree建立完成之后,如何进行光线与物体求交判断呢?过程如下: 第一步判断光线是否与最外层的包围盒相交,如果相交进一步判断是否与对应的两个子空间相交(因图中做了简化,最大包围盒的左半边并没继续进行划分,实际上应该要划分的,所以左半部分对应的1号空间是叶子节点),如果光线与之相交,进一步判断与存储与叶子节点的物体信息求交。左半边判断完之后,接着判断右半部分,同样如果对于有半部分存在相交情况,则对于右半部分的所有子空间,递归的执行这个步骤即可。 利用KD-Tree的结构来构建AABB的好处是倘若光线与哪一部分空间不相交,那么则可以省略该部分空间所有子空间的判断过程,在原始纯粹的AABB之上更进一步提升了加速效率。 缺点: 缺点是判断包围盒与三角面的是否相交较难,因此划分的过程不是那么想象的简单,其次同一个三角面可能被不同的包围盒同时占有,这两个不同包围盒内的叶节点会同时存储这一个三角形面。 KD-Tree划分方法技术在业界之中逐渐不再被使用,但依然有很多借鉴参考价值。 Bounding Volume Hierarchy(Object Partitions)BVH与前几种方法最显著的区别就是,不再以空间作为划分依据,而是从对象的角度考虑,即三角形面,过程如下: 第一步同样找出场景的整体包围盒作为根节点,第二步找到合适的划分点,将最大包围盒内的三角形面分为两部分,再分别重新就算新的包围盒,此时包围盒会重叠,但一个三角形面只会被存储在唯一的包围盒内,而这也就解决了KD-Tree的缺点! 接下来与KD-Tree的建立类似,递归的对所有子空间重复该步骤 细节:
最后给出这样一个BVH加速结构遍历节点的伪代码参考:
至此,基本的基于Whitted-Style光线追踪的知识到此为止,以下部分为进阶部分。 辐射度量学(Radiometry)为什么突然扯这个?在Blinn-Phong模型中,我们时如何定义光线的,好像根本就没有定义。就算最基本的光的强度我们都是简单的用 I I I 来表示。这肯定是不对。其次,上述的Whited-Style光线追踪模型,它真的是一个正确的模型吗?显然不是,原因如下: 1. whited-style光线追踪只考虑了光滑面的镜面反射与折射,并没有对漫反射的光线进行追踪,而是直接返回当前着色点颜色 为此,更好的渲染模型路径追踪出现了,而在这之前,我们必须掌握一些辐射度量学的知识,它是对光照的一套测量系统和单位,能够准确的描述光线的物理性质。 一些必要定义辐射能量(Radiant Energy)和辐射通量/功率(Radiant Flux/Power)首先看一看Radiant energy的定义: 接下来是Radiant flux(power): 辐射强度(Radiant Intensity)Radiant itensity是指从一个光源出发某一方向上的亮度。看它的数学定义:
solid angle其实就是对应二维空间中圆的弧度在三维空间中球上的拓展。首先看在二维计算弧度公式如下: 即
θ
=
l
r
\theta = \frac{l}{r}
θ=rl? (中学知识),那么对应在三维上的球的弧度(立体角),只需进行一个简单的扩展如下: 那么对于Radiant intensity的定义当中,微分立体角 d ω d\omega dω 计算如下:
上述确定空间中一个方向(通过 θ , ? \theta,\phi θ,?),这个方向就是为 ω \omega ω,然后才在此基础之上分别对 θ , ? \theta,\phi θ,? 增加 d θ , d ? d\theta,d\phi dθ,d? 经计算得到最终的 d ω d\omega dω ,因此Radiant intensity的物理含义此时就很清楚了,为光源向某一方向所发射出的单位立体角的功率,简而言之就是光源在某个方向上的亮度。(一定要弄清,不然极有可能和下面两个概念弄混) 最后举一个对各向同性点光源计算Radiant intensity的例子: irradiance没有合适的中文翻译,直接用英文了。来看irradiance的数学定义: 该现象完全可以用irradiance解释,因为光的功率始终一致,离点光源所照射到的圆球面积也就越大,因此根据irradiance的式子,分母的面积值也就越大,irradiance也就越小。 radiance最后来看radiance的定义:
但这里有一个细微的区别,在irradiance中定义的每单位照射面积,而在radiance当中,为了更好的使其成为描述一条光线传播中的亮度,且在传播过程当中大小不随方向改变,所以在定义中关于接收面积的部分是每单位垂直面积,而这一点的不同也正解释了图中式子分母上的
c
o
s
θ
cos\theta
cosθ ,具体可以观察如下图: 在理解了radiance和irradiance的定义之后,再讨论讨论它们之间的关系,通过二者的定义式子,不难得出如下结果: 双向反射分布函数(BRDF)通过上述所有辐射度量学各种概念的定义之后,我们可以从这样一个角度理解光线的反射,如下图所示:
直观的理解,不同物体表面材质自然会把一定方向上的入射亮度
d
E
(
ω
i
)
dE(\omega_i)
dE(ωi?) 反射到不同的方向的光线上
d
L
r
(
ω
r
)
dL_r(\omega_r)
dLr?(ωr?)。用上述概念解释,就是着色点所收到的irradiance经过反射产生radiance到其他方向。如理想光滑表面会把入射光线完全反射到镜面反射方向,其它方向则完全没有;如理想粗糙表面会把入射光线均匀的反射到所有方向。因此所谓 借助BRDF,可以定义出反射方程如下: 至此通过辐射度量学,以及BRDF最终得到的反射方程正是一个几乎完全正确的光照模型了。再仔细观察一下反射方程:
渲染方程(The Rendering Equation)反射方程明白了,渲染方程也就水到渠成。上述我们并没有讨论物体自身的发光情况,渲染方程就是在反射方程的基础之上添加了一个自发光项(Emission term): 接下来从一个点光源和单个物体的场景开始理解渲染方程: 观察一下图中的渲染方程可以发现除了两个入射和反射的radiance,其它所有项都是知道的,可以将上式进一步写成如下图下方所示的式子: 一次反射直接光照,没有被光照直接照射的地方全部都是黑色的: 路径追踪(Path Tracing)可以看看英伟达的官博 What Is Path Tracing? 其中给了这么一幅图: 要想实现路径追踪,就要用到上述的渲染方程,具体定义及数学公式是给出来了,但是如何解是一个问题。为此,引入蒙特卡洛积分。 蒙特卡洛积分(Monte Carlo Integration)蒙特卡洛积分的目的: 当一个积分很难通过解析的方式得到答案的时候可以通过蒙特卡洛的方式近似得到积分结果,如下图所示: 蒙特卡洛积分的原理及做法: 对函数值进行多次采样求均值作为积分值的近似。 该做法十分容易理解,想象一下如果对上图这个函数值进行均匀采样的话,其实就相当于将整个积分面积切成了许许多多个长方形,然后将这些小长方形的面积全部加起来。它可以指定一个分布来对被积分的值进行采样,定义如下:
为了方便,所有的采样都使用均匀采样,因此很容易推出: 蒙特卡洛路径追踪(Monte Carlo Path Tracing)有了这个基础,我们就可以解渲染方程了,先回顾一下:
我们先对渲染方程做出一点小修改,先不考虑发光项
L
e
(
p
,
ω
o
)
L_e(p,\omega_o)
Le?(p,ωo?),以方便进行计算推导: 从具体例子出发,首先仅仅考虑直接光照: 那么现在所有的问题都解决了吗?还没有,之前一直强调的递归问题(上述中体现在shade函数里)没有解决。在现实世界中,光线确实无限折射反射的,但是在程序中我们要确保有穷性,但是人为给一个限定的反射限定次数又显得很怪(ray tracing中我们是这样做的),我们并不知道最好的反射次数是多少。这里十分精妙得采用了俄罗斯轮盘赌(Russian Roulette)。 因此在计算直接光照的时候改进为直接对光源进行采样。这样所有采样的光线都一定会击中光源(如果中间没有别的物体),没有光线再会被浪费了。假设光源的面积为A,那么对光源进行采样的
p
d
f
=
1
A
pdf = \frac{1}{A}
pdf=A1?(因为
∫
pdf
?
d
A
=
1
\int \operatorname{pdf} d A=1
∫pdfdA=1,概论密度函数性质),但原始的渲染方程: |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/17 3:09:15- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |