unity shader development[8]

56 篇文章 3 订阅

基于物理的Shader

  本书的这一部分涵盖了基于物理的着色,从基本概念到如何实现自定义照明模型。

  你将学习microfacet理论,了解许多不同的自定义照明功能,包括可视化和分析它们的方便方法以及如何在Unity中实现它们。

  你将学习如何将你的自定义照明功能加入Unity标准着色器,这样你就可以利用其广泛的功能,包括镜面反射和全局照明。

  你还将学习如何实现通常类型的自定义照明功能中不包括的高级技术,比如半透明。这一部分包括对如何实现反射的概述,或者说Unity的反射探针是如何在下面工作的。

什么是基于物理的着色?

  基于物理的着色与我们以前所做的着色类似,但现在的照明计算是基于具有一定精度的光的物理学。正确性被定义为真实的行为。你可以通过使用基于物理的离线渲染器渲染同一场景来检查你的着色器中实现的光照是否正确。

  本章讨论了我们感兴趣的光的物理学原理。我们在第一章中介绍了一些关于光在撞击表面时的行为的信息,现在我们将对此进行扩展。

光是一种电磁波

  为了充分涵盖这一主题,我们必须简要地深入研究物理学。从光的性质开始,它是一种电磁波,为了某些目的,它在概念上可以简化为射线。这对我们来说意味着,有一些光的行为可以通过把它当作波来解释,如衍射,还有一些特性我们可以只把光当作射线,如镜像反射。

  一般来说,当一个表面的不规则性大于光的波长宽度时,它是安全的 不需要担心光作为一种波的性质。我们感兴趣的大多数行为都可以从更高的抽象层次上得到解释。我们感兴趣的大部分行为都可以从一个更高的抽象层次来解释,即把光看作是射线。回顾我们之前对 阴影–漫反射和镜面反射的光的行为。现在我们要用更现实、更抽象的术语来重新解释它们。不那么抽象的术语来重新解释。

微面理论概述

  我们说过,漫反射发生在表面上的微孔朝向许多不同的方向,而镜面反射是当它们朝向几个相似的方向时。这是一个很大的简化,让你开始,所以请继续关注更多物理上的准确解释。

  首先,当一个表面的不规则性大于光的波长,但与我们观察的尺度相比又很小的时候,微面理论是适用的。把一个表面是否平坦看作是一个宏观的概念,把它是否有微面看作是一个微观的概念,然后在波长尺度上,重要的是不规则的东西是比光的波长大还是小。

  Microfacet理论是很有用的,它可以从数学上推导出入射光线在撞击表面后的最终去向的统计表示。我们在顶点或像素上着色,我们不太可能在如此放大的情况下渲染一个表面,以至于我们需要担心单个光线的问题。对于我们的目的来说,一个统计模型已经足够了。

折射和其他Beasts

  还有一种光的行为我们还没有涉及,因为它一般不在游戏中直接表现。我们说过一束光可以被反射或吸收,我们还提到了光如何穿过半透明的层,比如水,但我们没有说让它到达下面一层的东西叫做折射或传播。

  当一条射线击中一个表面时,它的一部分光被吸收,一部分被反射,还有一部分被折射。而光线有多少进入到每个人的体内是很重要的。我所说的 “撞击”,实际上是指一个稍微复杂的概念。每种材料都有一个折射率,它代表了光线通过材料的速度。

  光在折射率恒定的介质中沿直线传播,如果折射率稍有变化,它就会在传播过程中发生弯曲。但当在折射率非常不同的介质之间通过时,它就会散开,分成多个方向。

  吸收(见图8-1)需要发生(或不发生),以使表面具有特定的反照率颜色。把光看成是一种波,光带有各种颜色的光谱,而表面的吸收会消除光谱的每一部分,除了我们在表面看到的颜色。这一部分的光谱被反射出去,到我们的眼睛。为了我们的目的,光的光谱性质可以简化为RGB颜色

在这里插入图片描述
  到目前为止,反射一直是我们的重点。正如我们所说的,当一条射线击中一个表面时,它的部分能量被送往一个特定的方向,即反射方向。但是我们还没有真正涉及到进来的能量有多少被反射。到目前为止,我们主要担心的是它往哪个方向去。追踪进入反射方向的能量比例对于基于物理的阴影是很重要的。

  由于我们没有在三维模型中建立微观几何模型,所以我们必须对其进行统计学处理,如前所述。对于我们正在着色的每一个像素,光线被反射到多个方向,形成一个圆锥体(见图8-2)。

在这里插入图片描述
  为了跟踪反射光是否是一个适当的数量,我们需要将其与 入射光线进行比较。我们稍后会看到这与渲染方程的哪些部分相对应。入射光线是 通常被测量为来自点周围的一个半球,如图8-3所示。

在这里插入图片描述
  这个半球基本上是半个球体,围绕表面的法线排列。在渲染方程中,来自这个半球的各个方向的入射光线被加起来,这是这些计算中最耗时的部分之一。其中有些光线是直射的,我们可以很容易地跟踪和计算,但另一部分则是间接的。那是在到达该点之前经过反弹的光。这需要大量的近似计算,一般来说,这可以归结为光线映射或全局照明。在镜面反射的情况下,这种现象使得看到整个场景反映在一个反射物体上成为可能。这需要用另一种技术来模拟,比如Unity中的反射探针,或者只是普通的立方体地图。

在这里插入图片描述
  当光线离开一种材料进入一种新的材料时,角度会发生变化。根据它们的折射率的不同,折射角的变化也就越大。从一个较快的材料到一个较慢的材料,例如从空气到水,光的方向会向正常方向弯曲。此外,请记住,在离开材料的时候,光会再次改变方向。

  折射方向通常是用斯奈尔定律来计算的,但是除非我们模拟的是无误的折射材料,比如水或玻璃,否则我们不会去担心每一束光,以及每一个折射方向。正如我们所说的,我们需要在一个真正可笑的分辨率下进行渲染,才能实现一个像素/一条光线的对应。在现实中,每一个像素都包含了许多光线,所以从统计学的角度来处理它们才是有意义的,尤其是我们必须要实时渲染这个。

  为了折射的目的,你可以把材料分为金属和非金属(电介质)。金属吸收所有的折射光,这就是为什么我们在金属上观察到低得多的漫射成分。非金属会四处散射,直到它被吸收或再次离开材料,但远离它最初进入的地方。

  这就是漫反射近似的物理起源。当出口点与入口点在同一像素内时,它可以被简化为漫射。如果它在该像素之外,你需要使用次表面散射技术来充分模拟它。因此,离摄像机的距离是一个重要的因素,它决定了什么东西可以作为漫反射进行着色,或者应该用次表面技术进行着色。

菲涅尔反射率

  如前所述,跟踪有多少能量(如光强度)传入,以及有多少能量最终会从我们的表面上的点传出,对于保持阴影的物理基础是很重要的。在Specular近似中,我们并不担心确保Specular不会比入射光线更亮。这就是为什么Phong感觉不真实的原因之一。

  多少入射光线被反射和多少被折射的比例取决于光的角度、法线和观察角度的变化。扫视的角度会比直视的角度有更多的反射。

  举个例子,想想自己在船上,直视下面。会有很少的反射,而且你能看到水面下的东西。另一方面,如果你看向地平线,你会看到大量的反射发生,而看不到水底下的东西。

  如果你用入射角绘制菲涅尔反射率图(见图8-5),从0度到大约45度,大多数材料几乎没有任何变化。它们从一个特定的菲涅尔值开始并坚持下去。从45度到75度,它们开始发生变化,大多数向最大反射率提高。在90度,几乎每一种材料都是完全反射的。

在这里插入图片描述
图8-5. 材料中菲涅尔反射率的变化图,取决于入射角度

  入射角为0度时,表面的颜色在大多数入射角值中都是保持的,所以方便简化,把它作为材料的一般镜面颜色。你可能已经看到周围的材料图表,列出了各种材料应该使用的镜面颜色。Unity的是在https://docs.unity3d.com/Manual/StandardShaderMaterialCharts.html。

  镜面色对金属来说大多是必要的。电介质往往有不太精确、较暗和单色的镜面颜色。由于金属没有任何次表面散射(它们吸收所有未被反射的光线),如果它们没有镜面色,它们就不会有任何颜色。

  我们通常使用菲涅尔方程来计算反射和折射之间的分割,通常在代码中通过Schlick近似来实现。这个近似值应该与我们描述的图中的那些真实的物理世界的值相似。
在这里插入图片描述
  Fo是镜面色,意思是入射角为0度的颜色。最初的菲涅尔公式使用的是折射率的光谱指数,而不是镜面色,这在处理上就不太方便了。

如何测量光线

  正如您现在可能已经意识到的(也许有些恐惧),渲染与物理学有着千丝万缕的联系。 十年前,我们的直观近似是最先进的,但现在已经有了进展。 在这个基于物理着色的时代,如果不具备光物理和微积分的实际应用知识,你就无法真正创新。

  正如我所写的,我无法知道你对这本书的个人目标。你可能只想让你的独立游戏看起来更好。你可能想制作你自己的基于物理的渲染器。你可能想成为一名图形研究人员。根据你的目标,你可能需要更深入地研究物理学,但我在这里试图至少让你对所有东西如何结合在一起有一个好的概念。这包括向你介绍大多数用于测量光的单位。物理学中测量光(和其他电磁辐射)被称为辐射测量。你至少需要知道一些与光有关的计量单位,以便能够读懂渲染方程。

实心角

  实体角(见图8-6)用一个叫做立体角的单位来表示,其符号是sr。形状在一个单位球体上的投影。这个半球应该是你以前就熟悉的。

在这里插入图片描述

Power

  从任何方向来的能量,通过一个表面的传输率,就是功率(见 图8-7)。你会发现功率表示为W

在这里插入图片描述

Irradiance(辐照度)

  辐照度是来自各个方向的功率,通过一个点(见图8-8)。在公式中,它通常表示为E,你会发现它表示为W/m2。

在这里插入图片描述

Radiance (辐射度)

  辐射度是指沿着一条射线的光的大小(见图8-9)。它在公式中通常用L表示 公式中用L表示,其中Li 是传入的辐射度,L0 是出射的辐射度。你会发现它被表示为 W/(m2 sr)。

在这里插入图片描述
  这些测量方法是相互建立的,你可以通过辐射度W/(m2 sr)看到。最后一个是使用之前的所有单位–功率(W),实体角(sr),和辐照度W/(m2)。还有更多的单位需要用来测量光,但这些应该可以满足我们的目的。

如何表现一种材料

  现在我们知道了我们可以用什么单位来测量光线,所以我们可以解决如何为渲染的目的来表示一个材料。我们通常会用尽可能少的参数来表示光在照射到材料上时的行为方式。

  到目前为止,我们所看到的所有光照模型(Lambert、Phong和BlinnPhong)都至少需要法线的方向和光线的方向。依赖于视图的照明模型也至少需要视图方向。

  到目前为止,我们用照明模型这个表达方式指的是一个实现或一个公式,它模拟了光在照射到某个表面时的行为。但是,还有更多的技术术语来描述同样的概念,这取决于你想用它来模拟什么子集的光照行为,我们现在就来介绍这些术语。你会发现,灯光模型的普通数学表示法与我们到现在为止所实现的和所看的感觉不同

双向反射率分布函数(BRDF)

  BRDF是一个函数,它定义了光线在表面上的反射方式。到目前为止,我们实现的所有照明模型都是BRDF,这意味着它们主要关注的是反射率。这意味着它们不能表示诸如次表面散射或半透明等现象。

  它们是以入射光线的方向和出射光线的方向为参数的函数,但它们是以球面极坐标的形式存在(见图8-10)。这种坐标系使我们能够只用四个数字来表示这些方向。在这个系统中,一切都以从原点出发的角度来测量。在不同的参考资料中,你可能会发现不同的符号代表不同的角度(甚至换来换去,只是为了让人更困惑),但在本书中,我们会用θ表示方位角,用ϕ表示天顶角。这是计算机图形学文献所遵循的惯例。
在这里插入图片描述
图8-10. 入射光线方向、视图方向和法线方向在球面极坐标中表示 坐标

  在图8-10中,有四个命名的角度。其中,θi和ϕi定义了入射光方向,而θ0和ϕ0定义了出射光方向(或视图方向)。ϕ从切线矢量t开始。我们将来会再次使用这种坐标,以分析不同BRDF的行为,所以请留意它们。

BRDF的原始定义是:
在这里插入图片描述
  正如我们在上一节所显示的,L是辐射度,E是辐照度。ωi和ωr是入射和出射(反射)光方向。cosθi是入射光方向与表面法线的角度。

  还有其他类型的函数,不像BRDF那么好定义,可以处理次表面散射等问题。它们是BSDF(双向散射分布函数)和BSSRDF(双向散射-表面反射分布函数),但它们在我们的实时渲染范围之外。

  一个表现良好的基于物理的BRDF必须具备一些属性,它们是正性、对等性和能量守恒。

正性

这意味着BRDF不能返回一个负数,不存在负光。

对等性

ωi和ωr互换时,BRDF必须有相同的值。

能量守恒

用最简单的话来说,出射的光不能超过入射的光,除非多余的光是从物体上发射出来的。

在这三者中,我们将最多地遇到能量保护,因为它对BRDF结果的可感知的真实性有很大的影响。

微面理论

  微面理论是用数学方法推导出BRDF来描述表面反射,特别是对于那些具有微面不规则性的表面,在每个尺度上都不是完全光滑平整的。我们假设我们有一个表面,其表面不规则性小于观察的尺度,但与光的波长相比很大。每一个点在局部都是一个完美的镜子;我们忽略了纳米级的不规则性

  这种完美的镜子将光(忽略折射)反射到一个出射方向,这取决于光的方向和微平面法线。 为了让光线进入我们的视点,这些微平面需要定向,以便它们反射到视线方向。

  为了实现这一点,它们的法线方向必须是半向量。半向量是光线方向和视图方向之间的一半。半向量是由lightDir和viewDir相加得到的,然后将结果归一化。

  阴影和遮罩(见图 8-11)会阻止一些微表面对出射光做出贡献。 阴影是指不规则性会产生一个峰值,从而遮蔽一些微平面。 掩蔽是当出去的反射被峰值阻挡时。 实际上,被阻挡的光会继续反弹,最终可能会离开表面。 但是微平面理论将这一点简化了。
在这里插入图片描述

图8-11。相对于现实,理论所使用的阴影和遮蔽近似值(光反弹)。

  从这些假设中,我们可以推导出这个方程式,它描述了一个微面镜面BRDF
在这里插入图片描述
  把它分成几个部分是很有用的,接下来讨论一下

菲涅尔

在这里插入图片描述
  这是指对于给定的物质,根据光的角度和法线,反射而不是折射的光的数量。角度和法线。我们在前面解释了菲涅尔,这告诉你它在实际BRDF中的位置。

正态分布函数

在这里插入图片描述
  它告诉我们有多少个微斑点是指向半矢量方向的,因为那些是我们唯一关心的,因为它们贡献了出射光。分布函数决定了亮点的大小和形状。你可能遇到的一些NDF是GGX、BlinnPhong和Beckmann。

几何函数

在这里插入图片描述
  这告诉我们有多少面没有被阴影和遮挡弄得一无是处。BRDF必须是能量守恒的。通常,Smith的阴影函数被用作几何函数。

  微面理论非常有用,但它不能模拟所有现象。它忽略了衍射和 干涉,这取决于光作为一种波的性质。

渲染方程(第二部分)

  在第一章中,我向你展示了渲染方程。我这样做不是为了吓唬你,我保证! 那是为了让你习惯于看到它。现在我们要把方程的每一部分映射到它的作用上。
在这里插入图片描述
首先,我们有出射光。
在这里插入图片描述
这就是我们想从方程中得到的东西。
那么我们就有了发射的光:
在这里插入图片描述
  这是由我们要着色的表面所发出的光。它不在BRDF中,因为它不是反射或折射的光,也不在积分中,所以它只被添加一次。
  然后我们就有了积分
在这里插入图片描述
  这将重复并将其中的所有内容加起来,对于半球的每个实体角度(dw)。
在这个积分中,我们有BRDF:
在这里插入图片描述
  它接收入射光线ωi 并返回反射和折射的光 ω0

然后我们就有了入射光线:
在这里插入图片描述
  这是进入表面的光线,我们要对其进行遮挡。
然后我们有法线衰减:
在这里插入图片描述
你从早期的照明模型实现中知道这一点。

Hacks实时渲染的需要

  渲染方程的整体部分还不能实时执行。正如多次提到的那样,间接光可以用很多技术来模拟–球面谐波、全局照明、光映射和基于图像的照明(反射探头、立方体地图等)。

  需要知道的一点是,如果你实现了一个新的照明模型,你可能需要改变全局照明的计算方式和立方体地图的处理方式。

  使用反射探针,从场景中获取一个立方体地图,为了使用基于图像的照明,立方体地图需要根据你所使用的BRDF进行处理。在实践中,Unity中内置的任何处理方法都可能是充分兼容的,不值得为你的BRDF改变配方。

  有一些开源工具可以被修改并用于为你的自定义BRDF处理立方体图,比如cmftStudio和旧的CubeMapGen。 你也可以在Unity中以计算着色器的方式实现这种处理。

HDR和色调映射

  当你的相机不是HDR的时候,你的光照值的比例就不能是真实的。你肯定想尽可能地使用HDR相机和RenderTextures。

  这样做的结果是,除非您只针对 HDR 屏幕,否则在某些时候您需要将这些 HDR 值转换回 LDR。 这是通过色调映射作为后处理效果来完成的。 色调映射会影响您的游戏风格,因此选择最佳的色调映射运算符很重要。 您可以将其视为电影库存对电影的作用。 捕获到胶片(即 HDR)的光线已被类比地转换为 LDR,具有特定于胶片成分的图案。

线性色彩空间

  你有没有想过你是在什么空间进行计算的?有可能在开始阅读这本书后,你会有这样的疑问,而且不止一次。渲染的一个明显问题,显然在很长一段时间内没有人注意到,那就是我们是在一个非线性空间中进行计算的。

  LDR屏幕上显示的颜色是在伽玛空间。伽马空间是一个非线性空间,0和255之间的中点不是128,而是187(见图8-12)。因此,所有涉及颜色的计算都有微妙的错误。转而使用线性空间是基于物理学的着色的另一个主要内容。它相对容易处理,特别是在Unity完全支持线性空间的平台上。

在这里插入图片描述

为什么基于物理的shading是有用的?

  在这一点上,你可能想知道基于物理的着色(PBS)是否值得所有的大惊小怪和所有的数学运算。如果你想在你的图形中获得真实感,PBS是无可比拟的。

  如果你想实现一些不一定需要任何真实性的艺术着色器,这听起来可能并不有趣,但PBR还有其他优点。例如,使用基于物理的光照模型,场景中的材质设置应该能很好地适应任何光照设置,大大减少了艺术家在改变场景的光照时需要进行的摆弄。你仍然可以通过使用后期处理或调整照明模型来实现渲染的风格。

总结

  本章简要介绍了你需要知道的大部分物理概念,以便理解基于物理的阴影的实际工作原理。希望这不会让你感到压抑。你可能会觉得有很多概念在你的脑子里跳来跳去,但不要担心,几乎不可能一下子就接受这些。除非你以前对光的物理学有一定的研究,否则你一定会需要更多的时间。在接下来的章节中,一些BRDF的实现将帮助你把本章的概念付诸实践。

  下一章将告诉你如何在Unity表面着色器中创建你的第一个基于物理的照明模型,将你所学到的知识付诸实践。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值