零基础学习渲染--PBR(基于物理渲染)

看到一个名字PBR,给人高大尚的感觉,下面我和大家一起扫雷,给不了解和想要了解的人学习学习。

PBR(Physicallly-Based-Rendering), 基于物理的渲染,有时也叫PBS(Physicallly-Based-Shading),(其实Unity自带的Standard就是一个完整的PBR,实际中需要对官方的性能调优)。为什么叫基于物理的,因为目标是基于与现实世界的物理原理基本相符的理论构成渲染技术。这样美术就可以直接以物理参数为依据来编写材质,不论光照如何材质看上去都是正确的。

PBR光照模型的三个条件:
① 基于微平面的表面模型;
② 能量守恒;
③ 应用基于物理的BRDF。

1. 微平面模型:

PBR基于微平面理论,即达到微观尺度后任何平面都可以用被称为微平面的细小镜面来描绘。平面越粗糙,微平面的排列越混乱,镜面反射时就会向完全不同的方向发散开来。我们可以用统计学的方法估算粗糙程度,而粗糙程度表示微平面上平均取向和半程向量(下段介绍半程向量)的方向一致的概率。

Blinn-Phong模型不依赖于反射向量,而是采用了所谓的半程向量,即光线与视线夹角一半方向上的一个单位向量。当半程向量与法线向量越接近时,镜面光分量就越大。当视线正好与(现在不需要的)反射向量对齐时,半程向量就会与法线完美契合。所以当观察者视线越接近于原本反射光线的方向时,镜面高光就会越强。如图:

(Blinn-Phong与冯氏模型唯一的区别就是,Blinn-Phong测量的是法线与半程向量之间的夹角,而冯氏模型测量的是观察方向与反射向量间的夹角。除此之外,冯氏模型与Blinn-Phong模型也有一些细微的差别:半程向量与表面法线的夹角通常会小于观察与反射向量的夹角。所以,如果你想获得和冯氏着色类似的效果,就必须在使用Blinn-Phong模型时将镜面反光度设置更高一点。通常我们会选择冯氏着色时反光度分量的2到4倍。)

半程向量:H = (L + V)  /   || L + V ||    ;


所以,粗糙度越大,微平面上平均取向和半程向量(下段介绍半程向量)的方向一致的概率越小,那反射的轮廓就会越大。

2. 能量守恒

出射光线的能量永远不能超过入射光线的能量(发光面除外)。当一束光线碰撞到一个表面的时候,它就会分离成一个折射部分和一个反射部分。反射部分就是会直接反射开来而不会进入平面的那部分光线,这就是我们所说的镜面光照。而折射部分就是余下的会进入表面并被吸收的那部分光线,这也就是我们所说的漫反射光照。

(并非所有能量都会被全部吸收,而光线也会继续沿着随机的方向发散,然后再和其他的粒子碰撞直至能量完全耗尽或者再次离开这个表面。而光线脱离物体表面后将会协同构成该表面的(漫反射)颜色。不过在基于物理的渲染之中我们进行了简化,假设对平面上的每一点所有的折射光都会被完全吸收而不会散开。次表面散射(Subsurface Scattering)技术的着色器技术将这个问题考虑了进去。)

金属表面所有折射光都会被直接吸收而不会散开,只留下反射光或者说镜面反射光。亦即是说,金属表面不会显示出漫反射颜色。所以金属和非金属材料在PBR中需要区别处理。

基于能量守恒,可以得到:

float ks = CalculateSpecular();//  反射/镜面 部分

float kd = 1.0 - ks;//  折射/漫反射 部分

3. PBR , 反射率方程


L:辐射率,单一方向上发射来的光线的大小或者强度。

Φ :辐射通量,表示的是一个光源所输出的能量,以瓦特为单位。一个光源所放射出来的能量可以被视作这个光源包含的所有各种波长的一个函数。)

ω :立体角,它可以为我们描述投射到单位球体上的一个截面的大小或者面积(人在球心观察)。投射到这个单位球体上的截面的面积就被称为立体角(Solid Angle)。

辐射强度(Radiant Intensity)表示的是在单位球面上,一个光源向每单位立体角所投送的辐射通量。

辐射强度:I = d Φ / d ω

一个拥有辐射强度Φ的光源在单位面积A ,单位立体角 ω 上的辐射出的总能量:


θ 为入射光线和平面法线间的夹角。

反射率方程:

P:将上述的A转换为了点。即可以计算单束光纤对meig每个片段的作用;

ω i :入射方向向量, n⋅ω i 即cosθ ;

ωo :表示观察方向,也就是出射方向;

 ∫  :反射率公式中的符号,它的运算包含了半球领域Ω 内所有入射方向上的dω i 。

反射率方程概括了在半球领域Ω  内,碰撞到了点p 上的所有入射方向 ωi 上的光线的辐射率,并受到fr 的约束,然后返回观察方向上反射光的Lo 。

4. BRDF

 fr 被称为BRDF,或者双向反射分布函数(Bidirectional Reflective Distribution Function) ,它的作用是基于表面材质属性来对入射辐射率进行缩放或者加权。

BRDF可以近似的求出每束光线对一个给定了材质属性的平面上最终反射出来的光线所作出的贡献程度。它接受入射(光)方向ω i ,出射(观察)方向 ωo ,平面法线n 以及一个用来表示微平面粗糙程度的参数a 作为函数的输入参数。

BRDF分为两部分,折射部分(漫反射)+ 反射部分(高光反射),很多种BRDF都可以近似为下面的公式:


kd 是入射光线中折射部分的能量所占的比率,而ks是反射部分的比率。BRDF的左侧表示的是漫反射部分,用flambert 来表示。BRDF的右侧表示的是镜面反射。



D:正态分布函数(法线分布函数),估算在受粗糙度影响下,取向方向与中间向量一致的微平面的数量。

F:菲尼尔反射,描述在不同的表面角下表面所反射的光线所占的比率。

G:几何函数(阴影-遮掩函数),描述了微平面自成阴影的属性。即平面表面上的微平面挡住其他微平面从而减少表面所反射的光线。

Unity5.3以后使用GGX模型(这种模型的DFG采用了GGX特定的函数形式,因为每个函数不止一种形式)。

最终,我们得到Cook-Torrance反射率方程:


那如何编写PBRcai材质呢?

美术师一般是如何编写一个我们可以直接输入PBR的平面物理属性的。PBR渲染管线所需要的每一个表面参数都可以用纹理来定义或者建模。使用纹理可以让我们逐个片段的来控制每个表面上特定的点对于光线是如何响应的:不论那个点是金属的,粗糙或者平滑,也不论表面对于不同波长的光会有如何的反应。输入PBR渲染管线一个纹理列表,就会得到相应的视觉输出,纹理列表如下:

反照率(Albedo)纹理:为每一个金属的纹素(Texel)(纹理像素)指定表面颜色或者基础反射率。这和我们之前使用过的漫反射纹理类似,不同的是所有光照信息都是由一个纹理中提取的。漫反射纹理的图像当中常常包含一些细小的阴影或者深色的裂纹,而反照率纹理中是不会有这些东西的。它应该只包含表面的颜色(或者折射吸收系数)。

法线贴图纹理:法线贴图使我们可以逐片段的指定独特的法线,来为表面制造出起伏不平的假象。

金属(Metallic)贴图:逐个纹素的指定该纹素是不是金属质地的。根据PBR引擎设置的不同,美术师们既可以将金属度编写为灰度值又可以编写为1或0这样的二元值。

粗糙度(Roughness)贴图:可以以纹素为单位指定某个表面有多粗糙。采样得来的粗糙度数值会影响一个表面的微平面统计学上的取向度。一个比较粗糙的表面会得到更宽阔更模糊的镜面反射(高光),而一个比较光滑的表面则会得到集中而清晰的镜面反射。某些PBR引擎预设采用的是对某些美术师来说更加直观的光滑度(Smoothness)贴图而非粗糙度贴图,不过这些数值在采样之时就马上用(1.0 – 光滑度)转换成了粗糙度。

环境光遮蔽(Ambient Occlusion)贴图或者说AO贴图为表面和周围潜在的几何图形指定了一个额外的阴影因子。比如如果我们有一个砖块表面,反照率纹理上的砖块裂缝部分应该没有任何阴影信息。然而AO贴图则会把那些光线较难逃逸出来的暗色边缘指定出来。在光照的结尾阶段引入环境遮蔽可以明显的提升你场景的视觉效果。网格/表面的环境遮蔽贴图要么通过手动生成,要么由3D建模软件自动生成。

美术师们可以在纹素级别设置或调整这些基于物理的输入值,还可以以现实世界材料的表面物理性质来建立他们的材质数据。这是PBR渲染管线最大的优势之一,因为不论环境或者光照的设置如何改变这些表面的性质是不会改变的,这使得美术师们可以更便捷的获取物理可信的结果。在PBR渲染管线中编写的表面可以非常方便的在不同的PBR渲染引擎间共享使用,不论处于何种环境中它们看上去都会是正确的,因此看上去也会更自然。

写一个PBR并不难,网上很多,这里只讲原理。

参考:https://learnopengl-cn.github.io/和Unity shader入门精要。

来源:CSDN,作者:淡泊以致远,转载此文目的在于传递更多信息,版权归原作者所有。
原文:https://blog.csdn.net/jfy307596479/article/details/84104220
版权声明:本文为博主原创文章,转载请附上博文链接!

推荐阅读