游戏中基于物理的渲染简简明科普

1623 篇文章 22 订阅
1407 篇文章 2 订阅

http://tieba.baidu.com/p/3922888163




基于物理的渲染(PBR)是一个近几年时常见诸于各大 游戏行业技术交流、游戏开发商公关以及游戏媒体口中的词汇。这个词涵盖内容广泛,定义又十分模糊。目前人们所指的游戏中基于物理的渲染包括不少方面,例如线性空间,镜头模型,HDR等等,内容五花八门,极易让外行误解。本系列科普将重点介绍PBR的核心内容——双向分布反射函数,英语简称BRDF。什么是BRDF?BRDF是用来描述材质表面反射的函数,而更加贴近真实世界的材质效果正是PBR的最主要部分。在本文开头我们先不管BRDF的具体定义,而是通过几个具体例子来一步步深入游戏中PBR的基本理论。以下例子主要是对Siggraph上PBR course的翻译,个人认为这是个非常好的PBR入门介绍。

第一个例子,一杯清澈的水,当光线穿过杯子里的水时只有很少一部分光会被吸收和散射,所以我们能清晰地看到杯子后的物体。


第二个例子,一杯茶,当光线通过茶水时,一部分光被吸收,但是没有光线被散射,光线在茶水中始终保持基本一致的传播方向。所以我们看到的现象是,茶水中映出来背后物体的像变暗了,但依然清晰可见。


第三个例子,在一杯水里加些牛奶,当光线穿过液体时,大量光线被散射,部分被吸收,一部分被散射光线穿过牛奶到达我们眼睛。这种情况下,水杯后物体的像已经基本看不清了,但我们能观察到加入牛奶后液体显现的白色


第四个例子是杯可乐,此时通过液体的光线基本被完全吸收,我们看不到杯子背后物体的像,液体也完全变为黑色。


通过这四个例子我们简单复习了一下什么是散射什么是吸收。在接下来我们将把这种现象类比到两类最常见的材质种类——金属和电介质。
电介质便是那些基本不导电的物体,例如 石头和塑料,这些常见的不导电物体都是电介质。我们先以理想光滑表面为例,当光线入射到表面时,一部分被反射,一部分被折射,遵从我们最熟悉的反射和 折射定律


如果是金属的话,折射的那一部分会被立即吸收,只留下被反射的那部分光。


如果是电介质的话,折射的那部分光就不是被吸收了,而是被散射。


现在我们就可以引出 漫反射和表面下散射的概念了。如果被折射光进入电介质表面后,在被散射的情况下只“走”了极短的一段距离后就重新进入空气,并向各个方向均匀地散射开来的话,我们称这种现象为漫反射(diffuse),如图中蓝色射线所示。


如果光线在折射后被散射,在物体的表面下传播了一段明显的距离后,又重新从表面下回到空气中,我们称之为表面下散射(也就是常说的3S,很多国内文章翻译为次表面散射,个人觉得不妥)。


最为常见的表面下散射现象就是人的皮肤。


而对于金属,如上文所说,折射的那部分光被吸收,所以金属基本只有高光分量(specular),没有 漫反射分量。所谓高光分量此时也很清楚了,也就是入射光被反射后维持一定方向性,较密集地射入空气的现象。下图圆圈中圈起的就是高光分量。


金属的高光往往是带有颜色的,而电介质的反射光一般是白色,也就是入射光是什么颜色,反射光还是什么颜色,这是两种材质的另一个重要区别。


物体表面的粗糙程度决定了高光分量的密集程度,物体表面越粗糙,高光分量越不密集,反射的像也越模糊。所以清晰的反射像和模糊的高光本质上是一个东西。下图从右到左展示了材质表面粗糙度递增的现象以及对应的材质示例。


此外,材质表面越粗糙,高光“覆盖”的范围就会越广,而高光也会越暗,这是一种基本的能量守恒现象。



再来一组直观的例子来演示一下漫反射和镜面反射。下图是一块光源照射下的砖头


下图则是使用偏振镜头拍到的砖头表面的镜面反射分量


下图是偏振镜头拍下的砖头表面的漫反射分量


至此我们就把电介质和金属这两类最主要的材质类型的基本材质现象给介绍完了,那么如何通过数学方式来描述这些材质反射现象呢?这里我们重新引出文章开头提到的BRDF——双向分布反射函数这一概念。BRDF就是一个描述入射光与反射光之间关系的函数,其定义为:


即反射光辐射亮度微元与入射光辐射照度微元的比值。
看不懂?不用担心,其实BRDF代表的是一个非常简单的概念。我们换一种形式来表述,如果,我们称某一方向上的入射光为自变量x,某一方向上的反射光为关于入射光的函数f(x),那么入射光与反射光的关系就是f(x)=k*x,而BRDF就是那个系数k,也就是多少比例的光被反射,仅此而已。只不过在不同的入射方向和反射方向上这个k都不一样,又因为方便测量等种种原因,BRDF被定义为如上形式。

如何得到或算出BRDF并应用到渲染中?我们可以把所有不同方向的入射光和反射光都测好,然后在游戏实时渲染中直接拿来用,但这样做的话数据量太过庞大,显卡吃不消。或者,我们可以从头开始,用基本物理原理精确重建出反射模型,但计算量太过庞大,显卡也吃不消。所以电影和游戏中都采取折中方案,通过一些可以容易测得的参数(贴图),以及相对简单的物理建模来重建表面反射模型,至此关于PBR的第一部分科普结束,下一篇文章中将介绍目前最为流行的BRDF模型理论——微平面理论。


http://tieba.baidu.com/p/3922948521

在第一部分中我们简单地介绍了基本的反射现象并且引入了BRDF这一概念。从这一部分开始我们将简单讲解目前最为流行的BRDF模型——微平面理论模型。
所谓微平面理论,就是把物体表面看作是一系列细小的平面所构成的宏平面,这些微平面我们肉眼不可见,但是又远大于光的波长,如下图所示


下面是一个能更加直观地理解微平面的例子。假设我们有一个如下图所示的粗糙表面


我们将表面上这些纹路的密度提高


再将密度提高


再提高


可以看到这些坑坑洼洼的纹路肉眼已经看不到了,此时它们变成了“微平面”。

每一个微平面都被视作理想镜面,对于计算光线入射理想镜面的反射和折射分量,自然而然地便会拿出菲涅尔公式。菲涅尔公式的具体形式在这里就不写了。我们在这里贴一张不同材质从0度入射角到90度入射角的反射分量曲线图


这里有个重要的现象要注意。在上图中,所有材质在光线平行于表面入射时几乎所有光线都被反射,而当入射角越来越小时,大部分金属依然能反射掉大部分的入射光,而大部分电介质材质都会吸收掉几乎所有的入射光,反射分量迅速下滑。这一现象造成了金属和电介质的不同外观。下图便是电介质的反射示意图,可以发现,越接近下图中球体的边缘,反射强度越高


作为BRDF微平面理论模型的第一个重要部分,我们称之为菲涅尔项(Fresnel Term)。

对于每一个微平面,并不是所有入射光都能到达此处,也不是所有反射光都能直接离开材质表面。原因在于,对于比较粗糙的表面,微平面都是坑坑洼洼高低不平的,一部分入射光和反射光会被其他微平面遮住,下图黑色部分就是被遮住的反射光


再来一张


这一描述有多少入射光和出射光会被遮住的项,我们称之为遮挡项或几何项(Geometry Term)

到此,我们先来整理一下微平面理论下BRDF的概念。还记得上篇我们将入射光和出射光的关系比作简单的f(x)=k*x的例子吗,这里我们可以简单地扩写一下这个式子
某一点在某一方向的反射光 = (几何项1:改点在入射光方向未被遮住的比例)*
(几何项2:改点在反射光方向未被遮住的比例)*
(菲涅尔项:在光滑的理想镜面微平面上反射光的比例)*
D*(某点在某方向上的反射光)
还有一个最后一个D项是什么?首先我们来简单复习一下理想镜面反射的情形。对于一个理想镜面,在满足什么条件下入射光能正正好好射入到我们的眼睛中?答案非常简单,就是在镜面向量正好指向视线向量和光线入射方向的半角向量时,如下图所示。


说到此处D项的意义就非常清楚了:在某一点,有多少比例的微平面的发线方向指向视方向和入射光方向的半角向量,从而能恰好将光线反射到我们的眼睛里。这一项我们称之为法线分布项(Normal Distribution Function,简称NDF)。NDF是最为重要的一项,他与菲涅尔项共同影响高光的衰减程度,同时又决定了高光的形状。

现在我们可以完整地写出在微平面理论下BRDF的形式了,如下所示


注意上式只是高光部分的BRDF,漫反射部分还没写。分子从左至右便是菲涅尔项,几何项和法线分布项,菲涅尔项和其他两项相互独立,三项都能被任意替换,这个模型被称之为Cook-Torrance模型,是目前最为常用的微平面BRDF形式。有人会问分母中的那两项是啥,其中一项的来源是因为,微平面理论定义在半角向量,而在渲染中则是在入射及反射光方向空间计算,需要乘上对应的雅可比行列式变换空间微元。这一项也至关重要,没有的话就无法模拟出一个称之为off-specular peak的现象:对于粗糙材质(尤其是金属),当光线以较大的入射角入射时,反射光最强的方向并不在镜面反射方向。对于微平面理论模型Blinn-Phong便是根据这一现象推导出来的。另一项是则是伴随几何项的修正项,具体推导略过。

简单介绍完微平面理论下BRDF的构成后,我们要开始填入更加具体的式子了。首先对于菲涅尔项,有个很常用的近似称之为Schlick近似,具体式子为:


这个近似有个好处在于电介质和导体(金属)通吃,无需分开来计算。式子中的Cspec便是高光颜色,也就是F0。
几何项受限于篇章,我在此处略去。对于NDF项就比较复杂了,各种模型五花八门,这里我们重点介绍最为常用的三种,Phong,Blinn-Phong和GGX。

Phong是最早也是最简单的一种光照模型(查了下Phong好像是个越南人)。在Phong光照模型下,高光反射永远关于镜面反射方向对称,在平面上其高光形状永远是圆形。如下图所示


Blinn将Phong的V*R改成了N*H,在曲面上Phong和Blinn-Phong很难看出区别,但在平面上,这一简单的改变却使高光形状发生了巨大的变化,使其从正圆形变成了狭长的椭圆形。如下图所示


上图中第一排便是在平面上Phong和Blinn-Phong的差别。Blinn-Phong在平面上所带来的这种椭圆形的狭长高光更加符合现实情况。在孤岛危机1(CryEngine 2)中虽然集成了多种光照模型,但主力模型仍是最为简单的Phong。到了CryEnigne 3,也就是孤岛危机2/3时,Crytek换成了Blinn-Phong模型。不过,使用更高级光照模型的孤岛危机2的材质表现反而被不少人诟病,原因何在?我们将在以后的部分探讨。


从2013年开始,不少次世代游戏开始换上了一种全新的NDF模型——GGX,也称为Trowbridge-Reitz。GGX最大的特点在于,从高光中心处高光相比Blinn会更快衰减,但是在远离高光中心后高光衰减却比Blinn-Phong的衰减要慢得多,这使得GGX的高光远比Blinn-Phong要狭长。GGX的高光有条常常的“尾巴”,这一点非常符合现实情况。尤其对于较为粗糙的材质,GGX的高光有非常柔和的衰减,使得Blinn-Phong/Phong时代“油腻腻”的材质现象大幅减少。
下图为Blinn和GGX在相同粗糙度下的效果对比,左为Blinn-Phong,右为GGX:


下图为Blinn-Phong,Phong,原始Cook-Torrance模型和采用了GGX的Cool-Torrance模型对比,GGX的长高光特性在这里非常明显。


另一个GGX和Blinn-Phong的直接对比。


一组在Cryengine中的对比图。上为CE3.5,使用Blinn-Phong,下为CE3.6,使用GGX。




再以教团1886为例,使用了GGX和更加精确的菲涅尔反射公式后,可以很轻松地做出逆光环境下的rim lighting效果,而在运用PBR前,模拟这类效果的方法一般是同时使用不同的BRDF在多个pass下完成。


GGX可以在和Blinn-Phong差不多的运算量下实现比Blinn-Phong要好得多的效果,这使得GGX迅速成为最为流行的光照模型。虚幻4, Cryengine 3.6开始的版本,教团1886,神秘海域4,寒霜引擎2015年开始的所有游戏等等,都将GGX作为主力光照模型。还有一些游戏在游戏开始制作时使用Blinn-Phong,难以在制作中途换到GGX,就通过修改材质粗糙度的方法来拟合GGX,例如声名狼藉:次子。在模拟多层材质上GGX也有良好的近似效果,Ryse,教团1886,神秘海域4都将GGX作为皮肤的高光模型。下图为Ryse中Marius的人头模型。


相比高光反射,游戏中在漫反射模型方面使用的模型就要简单得多。一般很多游戏直接使用最为简单的Lambertian模型,各个方向的反射光强度均匀,也就是这样:


一些游戏会用到更复杂的漫反射模型,目前比较流行的便是Oren-Nayer模型,Oren-Nayer也是通过微平面理论来描述漫反射的,可以模拟出在光线贴近表面入射粗糙材质时模糊的高光效果,很适合哑光材质。CE3,虚幻4都将Oren-Nayer作为漫反射模型。
讲完了高光反射和漫反射,最后一种材质反射现象便是表面下散射。表面下散射在实时渲染中尚无法精确算出,目前游戏中常使用基于屏幕空间的方法,具体我会在另一篇文章中科普。 
至此,PBR的第二部分科普就结束了。在第三部分中我们将探讨IBL和面光源的问题。


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Physics Modelling for Game Programmers 游戏编程物理建模(文删节版) 后记】 我将这本书界定成 3D 游戏开发的入门书籍,其实一直来我都有一个疑问,起初的时候我看 了很多 3D 开发方面的书籍也做了一些例子程序,但是对 3D开发还是有许多未知,自从我 见到这书以后,我终于明白我缺少的是什么了?其实就是需要一条线把我所学过的这些知识 全部串起来,反观当下无论是纸皮书还是电子书往往都是将 3D 开发分成若干块,专门讲一 块或是几块,开发是一个整体,所以我看了那么多书似乎前面还是有一层纱捅不破。 如果你是个新手,那绝对在此书会找到很多你感兴趣的东西,如果对于 DirectX 你已经足够 了解但就是不知从何开始,这本书可以整理你的思路,带你走出山谷奔向另一座高峰。 大概因为作者是一名老师的缘故,论述有些拖泥带水,文涉及到的 c++以及 Direct3D 基 础知识我都没有翻出,我相信你轻易就能找到相应的替代品,对于 15 章和 16 章的实例分 析没有翻,我想任何具备高物理程度的人都不难推导出这些公式,所以传言说老外的应用 科学的普及教育做得奇差,大概是真的。 本书只能作为免费传播,请勿用于商业,谢谢,最后我非常希望我的努力能换来你的赞许, 如果真是这样,那我将会很荣幸! 底层模式:HAL 和HEL(删除) 高层模式:DirectX 组件(删除) COM对象(删除) 使用DirectX 初始化 DirectX 的硬件方法 使用DirectX 向导初始化 Direct3D 使用物理建模框架初始化 Direct3D 小结(删除) 第三节:3D 编程和物理学的数学工具(删除) 三角几何(删除) 2D坐标系(删除) 3D和4D坐标系(删除) 物理单位(删除) 矢量 代码实现的矢量:物理建模的数学库 矢量与标量的乘除法 点积 叉积 单位化矢量 投影 Direct3D 的矢量 矩阵 特性 加法和减法 乘法和除法 矩阵相乘 转置 行列式 逆矩阵 小结(删除) 第四节:2D 变换和渲染 2D变换 主动和被动变换 平移 旋转 缩放 组合变换 变换实现:一个三角形的自旋 使用物理建模的框架 设定几何体 更新帧(Frame) 渲染帧 将所有的步骤放置到一起(删除) 小结(删除) 第五节:3D 变换和渲染 3D变换 齐次坐标 平移 缩放 旋转 3D管道 局部坐标转世界坐标 世界坐标转观察坐标 观察坐标转投影坐标 投影坐标转屏幕坐标 3D渲染 例子1:3D 自旋三角形 例子2:自旋的圆椎 小结(删除) 第六节:网格(Mesh)和 X 文件 纹理 从文件创建纹理 设定纹理 材质 装载一个网格 获取纹理和材质 渲染网格 清除网格 d3d_mesh类 载入一个网格 渲染一个网格 d3d_mesh类的引用计数 小结(删除) 第二部分:3D 对象,运动和碰撞 第七节:动态粒子 点状粒子 一维运动力学 速度(删除) 速度的导数求法(删除) 加速度(删除) 力 2D 和 3D 运动力学(删除) 质点模型 介绍d3d_point_mass类 使用d3d_point_mass类 游戏的质点 小结(删除) 第八节:粒子碰撞 碰撞检测 包围球 包围圆柱 包围盒 空间分隔的优化 碰撞响应 动量守恒 能量 弹性碰撞 刚性碰撞 补偿系数 2D和3D 的粒子碰撞 球的碰撞 实现 小结(删除) 第九节:刚体动力 刚体 重心 2D 刚体旋转 2D 刚体的粒子 转矩和惯性力矩 3D刚体 3D转矩 3D 的平行轴定理 主轴线 定向 3D 刚体的实现 d3d_rigid_body类 初始化 d3d_rigid_body对象 更新d3d_rigid_body对象 渲染d3d_rigid_body对象 小结(删除) 第十节:刚体碰撞 碰撞检测 粗糙近似 碰撞检测的改进 碰撞响应 线性碰撞响应 角度碰撞响应 组合碰撞响应 更新物理建模框架 小结(删除) 第十一节:重力和抛射体 牛顿万有引力法则 抛射体轨迹 抛射体运动模型 冲力与恒力之间的差异 滚动 小结(删除) 第十二节:质量与弹力系统 实现弹力所需的事 头发与马尾辫 织物 一切从周期运动开始 胡克定律 衰减周期运动 实现织物 升级质点 弹力 织物类 初始化织物 更新和渲染织物 进行调整 增加织物的表现力 小结(删除) 第十三节:水体与波纹 水体与浮力 水的特性 浮力产生的原理 求取压强和密度 运动阻力 对摩擦力的观察 粘性阻力 水体的流向 波 实现水体 低开销实现的技巧 3D水体 在水体放置对象 为刚体增加浮力 它会浮起来吗? 小结(删除) 第三部分:3D 模拟 第十四节:为游戏开发需做的准备 重新设计物理建模的框架 单程序的初始化 添加一个游戏类 设置高效的矩阵变换 恢复丢失的设备对象 使用质点重新定义刚体 网格原点和重心 DirectInput 介绍(删除) 初始化 DirectInput(删除) 获取键盘和鼠标输入(删除) 关闭DirectInput(删除) DirectX 的摄像机运动(删除) 小结(删除) 第十五节:汽车,气垫船,船只以及小舟(删除整章) 汽车 能量,力,加速度和摩擦 车辆的空气阻力 制动 车辆拐弯 实现一个基本的车辆模型 气垫船和无引力飞船 气垫船是如何工作的 气垫船的空气阻力 气垫船拐弯 船只和小舟 船只和小舟的包围边界 船体容积的计算 船只和小舟的续航能力 质量和有效质量 阻力和小舟 空气阻力 流速和波 小结 第十六节:飞机和宇宙飞船(删除整章) 飞行模拟的单方法 低空飞行或是无物理影响 实现一个单的飞行模拟 与飞机相关的物理学 飞机的主要部件 基本的动力 飞机建模:具备适合的地点和动力 与宇宙飞船相关的物理学 宇宙的空战 火箭 月球着陆器 其他行星已知的物理学 其他行星待论证的物理学 结束语(删除) 附录 A 术语(删除) 附录 B C++的一个简明介绍(删除) 附录 C window编程基础(删除) 索引(删除)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值