unity入门精要之第6 章 Unity 中的基础光照概述-1

Unity系列文章目录

前言

渲染总是围绕着一个基础问题:我们如何决定一个像素的颜色?从宏观上来说,渲染包含了
两大部分:决定一个像素的可见性,决定这个像素上的光照计算。而光照模型就是用于决定在一
个像素上进行怎样的光照计算。
我们首先会在6.1 节介绍在真实世界中,我们是如何看到一个物体的,以此来帮助读者理解
光照模型背后的原理。随后在6.2 节中,我们将解释什么是标准光照模型,以及如何在Unity Shader
中实现标准光照模型。6.3 节介绍如何计算光照模型中的环境光和自发光部分。在6.4 节和6.5 节
中,我们将学习两种最基本的光照模型,并比较逐顶点和逐像素光照的区别。最后,在6.6 节中
介绍如何使用Unity 的内置函数来帮助我们实现这些光照模型。
需要提醒读者注意的是,本章着重讲述光照模型的原理,因此实现的Shader 往往并不能直接
应用到实际项目中(直接使用会缺少阴影、光照衰减等效果)。我们会在9.5 节给出包含了完整光
照模型的可真正使用的Unity Shader。

6.1 我们是如何看到这个世界的

我们可能常常会问类似这样的问题:“这个物体是什么颜色的?”如果读者对小学的自然课还
有印象的话,可能还会记得这个问题是没有意义的:当我们在描述“这个物体是红色的”时,实
际上是因为这个物体会反射更多的红光波长,而吸收了其他波长。而如果一个物体在我们看来是
黑色的,实际上是因为它吸收了绝大部分的波长。这种物理现象就是本节需要探讨的内容。
通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3 种物理现象。
 首先,光线从光源(light source)中被发射出来。
 然后,光线和场景中的一些物体相交:一些光线被物体吸收了,而另一些光线被散射到其
他方向。
 最后,摄像机吸收了一些光,产生了一张图像。
下面,我们将对每个部分进行更加详细的解释。
6.1.1 光源
光不是从石头里蹦出来的,而是由光源发射出来的。在实时渲染中,我们通常把光源当成一
个没有体积的点,用l 来表示它的方向。那么,我们如何测量一个光源发射出了多少光呢?也就
是说,我们如何量化光呢?在光学里,我们使用辐照度(irradiance)来量化光。对于平行光来说,
它的辐照度可通过计算在垂直于l 的单位面积上单位时间内穿过的能量来得到。在计算光照模型
时,我们需要知道一个物体表面的辐照度,而物体表面往往是和l 不垂直的,那么如何计算这样
的表面的辐照度呢?我们可以使用光源方向l 和表面法线n 之间的夹角的余弦值来得到。需要注
意的是,这里默认方向矢量的模都为1。图6.1 显示了使用余弦值来计算的原因。

在这里插入图片描述
因为辐照度是和照射到物体表面时光线之间的距离d/cos成反比的,因此辐照度就和cos 成正
比。cos 可以使用光源方向l 和表面法线n 的点积来得到。这就是使用点积来计算辐照度的由来。
6.1.2 吸收和散射
光线由光源发射出来后,就会与一些物体相交。通常,相交的结果有两个:散射(scattering)
和吸收(absorption)。
散射只改变光线的方向,但不改变光线的密度和颜色。而吸收只改变光线的密度和颜色,但
不改变光线的方向。光线在物体表面经过散射后,有两种方向:一种将会散射到物体内部,这种
现象被称为折射(refraction)或透射(transmission);另一种将会散射到外部,这种现象被称为
反射(reflection)。对于不透明物体,折射进入物体内部的光线还会继续与内部的颗粒进行相交,
其中一些光线最后会重新发射出物体表面,而另一些则被物体吸收。那些从物体表面重新发射出
的光线将具有和入射光线不同的方向分布和颜色。图6.2 给出了这样的一个例子。

在这里插入图片描述
为了区分这两种不同的散射方向,我们在光照模型中使用了不同的部分来计算它们:高光反
射(specular)部分表示物体表面是如何反射光线的,而漫反射(diffuse)部分则表示有多少光线
会被折射、吸收和散射出表面。根据入射光线的数量和方向,我们可以计算出射光线的数量和方
向,我们通常使用出射度(exitance)来描述它。辐照度和出射度之间是满足线性关系的,而它们
之间的比值就是材质的漫反射和高光反射属性。
在本章中,我们假设漫反射部分是没有方向性的,也就是说,光线在所有方向上是平均分布
的。同时,我们也只考虑某一个特定方向上的高光反射。
6.1.3 着色
着色(shading)指的是,根据材质属性(如漫反射属性等)、光源信息(如光源方向、辐照
度等),使用一个等式去计算沿某个观察方向的出射度的过程。我们也把这个等式称为光照模型

(Lighting Model)。不同的光照模型有不同的目的。例如,一些用于描述粗糙的物体表面,一些
用于描述金属表面等。
6.1.4 BRDF 光照模型
我们已经了解了光线在和物体表面相交时会发生哪些现象。当已知光源位置和方向、视角方向
时,我们就需要知道一个表面是如何和光照进行交互的。例如,当光线从某个方向照射到一个表面
时,有多少光线被反射?反射的方向有哪些?而BRDF(Bidirectional Reflectance Distribution
Function)就是用来回答这些问题的。当给定模型表面上的一个点时,BRDF 包含了对该点外观的
完整的描述。在图形学中,BRDF 大多使用一个数学公式来表示,并且提供了一些参数来调整材质
属性。通俗来讲,当给定入射光线的方向和辐照度后,BRDF 可以给出在某个出射方向上的光照能
量分布。本章涉及的BRDF 都是对真实场景进行理想化和简化后的模型,也就是说,它们并不能真
实地反映物体和光线之间的交互,这些光照模型被称为是经验模型。尽管如此,这些经验模型仍然
在实时渲染领域被应用了多年。读者可以从邓恩的著作《3D 数学基础:图形与游戏开发》(英文名:
《3D Math Primer For Graphics And Game Development》)中提到的一句名言来体会这其中的原因。
计算机图形学的第一定律:如果它看起来是对的,那么它就是对的。
然而,有时我们希望可以更加真实地模拟光和物体的交互,这就出现了基于物理的BRDF 模
型,我们会在第18 章基于物理的渲染中看到这些更加复杂的光照模型。

6.2 标准光照模型

虽然光照模型有很多种类,但在早期的游戏引擎中往往只使用一个光照模型,这个模型被称
为标准光照模型。实际上,在BRDF 理论被提出之前,标准光照模型就已经被广泛使用了。
在1973①年,著名学者裴祥风(Bui Tuong Phong)提出了标准光照模型背后的基本理念。标
准光照模型只关心直接光照(direct light),也就是那些直接从光源发射出来照射到物体表面后,
经过物体表面的一次反射直接进入摄像机的光线。
它的基本方法是,把进入到摄像机内的光线分为4 个部分,每个部分使用一种方法来计算它
的贡献度。这4 个部分是。
 自发光(emissive)部分,本书使用cemissive 来表示。这个部分用于描述当给定一个方向时,一个
表面本身会向该方向发射多少辐射量。需要注意的是,如果没有使用全局光照(global illumination)
技术,这些自发光的表面并不会真的照亮周围的物体,而是它本身看起来更亮了而已。
 高光反射(specular)部分,本书使用cspecular 来表示。这个部分用于描述当光线从光源照
射到模型表面时,该表面会在完全镜面反射方向散射多少辐射量。
 漫反射(diffuse)部分,本书使用cdiffuse 来表示。这个部分用于描述,当光线从光源照射
到模型表面时,该表面会向每个方向散射多少辐射量。
 环境光(ambient)部分,本书使用cambient 来表示。它用于描述其他所有的间接光照。
6.2.1 环境光
虽然标准光照模型的重点在于描述直接光照,但在真实的世界中,物体也可以被间接光照
(indirect light)所照亮。间接光照指的是,光线通常会在多个物体之间反射,最后进入摄像机,
也就是说,在光线进入摄像机之前,经过了不止一次的物体反射。例如,在红地毯上放置一个浅
灰色的沙发,那么沙发底部也会有红色,这些红色是由红地毯反射了一部分光线,再反弹到沙发
上的。
在标准光照模型中,我们使用了一种被称为环境光的部分来近似模拟间接光照。环境光的计
算非常简单,它通常是一个全局变量,即场景中的所有物体都使用这个环境光。下面的等式给出
了计算环境光的部分:
6.2.2 自发光
光线也可以直接由光源发射进入摄像机,而不需要经过任何物体的反射。标准光照模型使用
自发光来计算这个部分的贡献度。它的计算也很简单,就是直接使用了该材质的自发光颜色:
通常在实时渲染中,自发光的表面往往并不会照亮周围的表面,也就是说,这个物体并不会
被当成一个光源。Unity 5 引入的全新的全局光照系统则可以模拟这类自发光物体对周围物体的影
响,我们会在第18 章中看到。
6.2.3 漫反射
漫反射光照是用于对那些被物体表面随机散射到各个方向的辐射度进行建模的。在漫反射中,
视角的位置是不重要的,因为反射是完全随机的,因此可以认为在任何反射方向上的分布都是一
样的。但是,入射光线的角度很重要。
漫反射光照符合兰伯特定律(Lambert’s law):反射光线的强度与表面法线和光源方向之间
夹角的余弦值成正比。因此,漫反射部分的计算如下:
其中, n 是表面法线, l 是指向光源的单位矢量,mdiffuse 是材质的漫反射颜色,clight 是光源颜
色。需要注意的是,我们需要防止法线和光源方向点乘的结果为负值,为此,我们使用取最大值
的函数来将其截取到0,这可以防止物体被从后面来的光源照亮。
6.2.4 高光反射
这里的高光反射是一种经验模型,也就是说,它并不完全符合真实世界中的高光反射现象。
它可用于计算那些沿着完全镜面反射方向被反射的光线,这可以让物体看起来是有光泽的,例如
金属材质。
计算高光反射需要知道的信息比较多,如表面法线、视角方向、光源方向、反射方向等。在
本节中,我们假设这些矢量都是单位矢量。图6.3 给出了这些方向矢量。
在这四个矢量中,我们实际上只需要知道其中3
个矢量即可,而第四个矢量—反射方向可以通过其
他信息计算得到:
这样,我们就可以利用Phong 模型来计算高光
反射的部分:
其中,mgloss 是材质的光泽度(gloss),也被称为
反光度(shininess)。它用于控制高光区域的“亮点”有多宽,mgloss 越大,亮点就越小。mspecular
是材质的高光反射颜色,它用于控制该材质对于高光反射的强度和颜色。clight 则是光源的颜色

在这里插入图片描述
和强度。同样,这里也需要防止v · r 的结果为负数。
和上述的Phong 模型相比,Blinn 提出了一个简单的修改方法来得到类似的效果。它的基本
思想是,避免计算反射方向r 。为此,Blinn 模型引入了一个新的矢量h ,它是通过对v 和l 的取
平均后再归一化得到的。即
然后,使用n 和h 之间的夹角进行计算,而非v 和r 之间的夹角,如图6.4 所示。
总结一下,Blinn 模型的公式如下:
在硬件实现时,如果摄像机和光源距离模型足够
远的话,Blinn 模型会快于Phong 模型,这是因为,此
时可以认为v 和l 都是定值,因此h 将是一个常量。但
是,当v 或者l 不是定值时,Phong 模型可能反而更快
一些。需要注意的是,这两种光照模型都是经验模型,
也就是说,我们不应该认为Blinn 模型是对“正确的”Phong 模型的近似。实际上,在一些情况
下,Blinn 模型更符合实验结果。
6.2.5 逐像素还是逐顶点
上面,我们给出了基本光照模型使用的数学公式,那么我们在哪里计算这些光照模型呢?通
常来讲,我们有两种选择:在片元着色器中计算,也被称为逐像素光照(per-pixel lighting);在
顶点着色器中计算,也被称为逐顶点光照(per-vertex lighting)。
在逐像素光照中,我们会以每个像素为基础,得到它的法线(可以是对顶点法线插值得到的,
也可以是从法线纹理中采样得到的),然后进行光照模型的计算。这种在面片之间对顶点法线进行
插值的技术被称为Phong 着色(Phong shading),也被称为Phong 插值或法线插值着色技术。这
不同于我们之前讲到的Phong 光照模型。
与之相对的是逐顶点光照,也被称为高洛德着色(Gouraud shading)。在逐顶点光照中,我
们在每个顶点上计算光照,然后会在渲染图元内部进行线性插值,最后输出成像素颜色。由于顶
点数目往往远小于像素数目,因此逐顶点光照的计算量往往要小于逐像素光照。但是,由于逐顶
点光照依赖于线性插值来得到像素光照,因此,当光照模型中有非线性的计算(例如计算高光反
射时)时,逐顶点光照就会出问题。在后面的章节中,我们将会看到这种情况。而且,由于逐顶
点光照会在渲染图元内部对顶点颜色进行插值,这会导致渲染图元内部的颜色总是暗于顶点处的
最高颜色值,这在某些情况下会产生明显的棱角现象。
6.2.6 总结
虽然标准光照模型仅仅是一个经验模型,也就是说,它并不完全符合真实世界中的光照现象。
但由于它的易用性、计算速度和得到的效果都比较好,因此仍然被广泛使用。而也是由于它的广
泛使用性,这种标准光照模型有很多不同的叫法。例如,一些资料中称它为Phong 光照模型,因
为裴祥风(Bui Tuong Phong)首先提出了使用漫反射和高光反射的和来对反射光照进行建模的基
本思想,并且提出了基于经验的计算高光反射的方法(用于计算漫反射光照的兰伯特模型在那时
已经被提出了)。而后,由于Blinn 的方法简化了计算而且在某些情况下计算更快,我们把这种模
型称为Blinn-Phong 光照模型。
在这里插入图片描述
但这种模型有很多局限性。首先,有很多重要的物理现象无法用Blinn-Phong 模型表现出来,
例如菲涅耳反射(Fresnel reflection)。其次,Blinn-Phong 模型是各项同性(isotropic)的,也就
是说,当我们固定视角和光源方向旋转这个表面时,反射不会发生任何改变。但有些表面是具有
各向异性(anisotropic)反射性质的,例如拉丝金属、毛发等。在第18 章中,我们将学习基于物
理的光照模型,这些光照模型更加复杂,同时也可以更加真实地反映光和物体的交互。

参考

Unity Shader入门精要
作者:冯乐乐

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值