基于物理的渲染 – 理论篇

基于物理的渲染,英文缩写PBR (physically based rendering),是一个渲染技术的集合,包含多种或多或少的利用物理来更真实的模拟现实世界的渲染技术,基于物理的渲染的目的是利用更接近实际物理理论的光照计算,生成比以前的Phong、Blinn-Phong算法更真实的画面,这项技术的好处不只是让画面看起来更好看了,也让我们(尤其是美工)可以简单的通过改变物体的几个物理属性就能渲染出想要的效果,而不用担心光照错误,这是非PBR渲染无法比拟的优势。

之所以叫做基于物理的渲染而不是物理的渲染,是因为渲染过程基于物理理论,尽管物理理论很接近现实,但毕竟不是现实。使用PBR光照模型要满足以下三条:

  1. 基于微表面模型;
  2. 能量守恒;
  3. 使用BRDF理论。

在这个PBR教程/介绍中,我们将会将会专注于迪士尼发明,Epic Games(这个公司开发的虚幻)率先使用的实时PBR方案,他们使用的基于金属度的区分方法广泛的适用于大部分流行引擎且效果非常的好。在系列教程结束的时候我们将可以制作出一些类似于下图的东西:

这里写图片描述

需要注意的是这个教程是进阶教程,建议有良好的OpenGL跟Shader基础的同学阅读,除此之外,还可能用到的一些基础有framebuffers, cubemaps, gamma correction, HDR and normal mapping,还可能会用到一些高级数学。基础一般的同学也不用担心,我会尽力的把每个概念解释清楚。

(原文:https://learnopengl.com/#!PBR/Theory, 翻译:coldkaweh)

微表面理论

所有的PBR技术都是基于微表面的。这个理论是说任何表面都可以用无数微小的镜面来描述,表面的粗糙程度越高这些微小的镜面的朝向区别越大。

这里写图片描述

对于一个物体表面来说更粗糙意味着微表面的朝向更无序,当我们讨论光线的高光反射时,这些镜子一样的微表面会将相同方向的入射光线朝着不同方向反射出去,形成一个更为宽广的镜面反射区域。而对于光滑表面来说,入射光线基本沿着同一方向反射出去,形成更清晰的反射画面。

这里写图片描述

从微观角度来说,没有任何表面是完全光滑的。我们这里使用粗糙度这个统计近似数值,来衡量那些比一个像素的覆盖范围还小的微表面的粗糙程度。我们根据表面的粗糙度,可以计算得到单个微表面的半角向量(halfway vector)平行于平均半角向量的概率,半角向量是指位于入射光 l 与眼睛向量正中间的单位向量。计算公式如下:

h=l+vl+v

越多的微表面半角向量相互平行,高光反射则越清晰和强烈。我们使用统计近似把微表面的各种对齐情况统一到0到1之间,形成一个粗糙度参数。

这里写图片描述

我们可以看到粗糙度越高的物体高光部分就越大越模糊,而光滑表面的高光小且亮。

(原文:https://learnopengl.com/#!PBR/Theory, 翻译:coldkaweh)

能量守恒

微表面模型采用一种近似的能量守恒:反射出去的光的能量不应该超出入射光的总能量(发光体除外)。从上图中可以看出,随着粗糙度的增加高光范围的逐渐增大,亮度是在逐渐降低的,假如无论高光的范围多大亮度都一样,那么这个粗糙表面发射的能量就有些太多了,违反了能量守恒定律。这就是为什么光滑的平面高光更强粗糙表面更朦胧的原因。

为了实现能量守恒我们需要先弄清楚高光和漫反射之间的区别。当一束光打在平面上,将会分成反射和折射两部分,被反射的部分不会进入物体而是会被物体表面直接反射出去,这就是我们平常所说的高光,剩下的光会被折射穿透表面被物体吸收,这就是我们所说的漫反射。

这里写图片描述

一般来说,一次碰撞并不能将所有能量全部吸收,剩下的光会以随机的角度散射出去继续跟其他的粒子继续碰撞或者从物体表面离开,通过表面离开的这部分光则算作部分漫反射颜色。在基于物理的渲染里我们将其简单化一下,我们假设所有所有的折射光都在物体表面的某一点上被吸收而没有散射。使用次表面散射技术可以计算这部分光照,在一些需要考虑这部分光的特殊着色器里,比如渲染皮肤,大理石和蜡等材质的时候,这部分光对效果有非常显著的提高,不过耗费的性能也是很可观的。

在金属表面上反射和折射有一些微小的不同,金属表面对光的反应与非金属(电介质)表面是不一样的。他们也遵从同样的反射和折射原理,但是所有的折射光都会被直接的吸收而没有散射,只有反射或者说高光,金属表面是没有漫反射颜色的。因为在这点上金属和电介质有着明显的不同,因此在PBR渲染管线上也得区别对待,我们后面的章节会进一步讨论。

如果从能量的角度来描述反射光和折射光之间的关系,可以总结成一句话:他们是互斥的。反射光的能量就是没有被物质本身吸收的部分,因此,作为折射光进入物体表面被吸收的部分就是入射光能量减去被直接反射掉的部分。

我们保持能量守恒利用的就是这种关系,先计算高光部分占整个入射光能量的百分比,折射光所占的比例就可以利用高光因子通过下列等式计算而来。

float kS = calculateSpecularComponent(...); // reflection/specular fraction
float kD = 1.0 - ks;                        // refraction/diffuse  fraction

根据能量守恒定律我们只要知道入射光和反射光就的能量就能计算出折射光的能量。使用这个方法计算得到的折射(漫反射)和反射(高光)能量的总和是不可能超过1.0的,这保证了出射光的能量总和永远不会超过入射光的能量。这是传统的光照模型保证不了的。

(原文:https://learnopengl.com/#!PBR/Theory, 翻译:coldkaweh)

反射方程

这一节我们要说的是渲染方程式,这是天才们精心构造的,目前为止最好的光照模拟模型。基于物理的渲染依赖的就是其中一项名为“反射方程”的等式,这是一个更适合我们使用的渲染方程式。

Lo(p,ωo)=Ωfr(p,ωi,ωo)Li(p,ωi)nωidωi

反射方程看起来非常可怕,但是我们会一步步慢慢的剖析它,你也将会慢慢的理解它。为了更好的理解这个方程,我们需要了解一点辐射度量学(radiometric)知识,辐射度量学通常用来度量电磁辐射(包括可见光),其中有几个量可以用来测量光照射物体表面和其方向,但是这里我们只讨论与反射方程有关的一个叫做辐射度(radiance)东西,使用大些字母 L 来表示。辐射度是用来量化方向光强度或者说长度的量,对于初次接触的人来说要理解辐射度是由多个物理量组合而成是很有难度的,我们将会先着重讲一下这个:

辐射通量:辐射通量 Φ 是用瓦特为单位计量光源的辐射能量,光是所有不同波段能量的集合,而每种波长都对应一种特定的颜色,因此光源发射出来的能量可以用不同波长的函数集来表示,一般将波长在390nm~700nm之间的作为可见光谱,这些波长是人眼可以感知(看到)的。下图中你将可以看到阳光中不同波长对应的能量和颜色。

这里写图片描述

辐射通量函数就是要计算不同波长的总面积。直接将这个波长计算函数用于计算图形学是不切实际的,所以我们通常使用简化版的表达方式,辐射通量不再是关于不同波长的函数,而是将光分解成RGB三个分量(也就是我们常说的灯光颜色(light color)),这种表示方式丢失了非常多的信息,但是从视觉的角度来看影响微乎其微。

立体角:立体角 ω 用来衡量投影到单位球上的形状的尺寸或者面积。投影到这个单位球上的形状的面积就是我们所说的立体角,可以将立体角想象成下图所示:

这里写图片描述

想象自己作为一个观察者站在单位球的中心看向正方形方向,你的视线画出的实线的尺寸就是立体角。

辐射强度:辐射强度衡量每一单位立体角的辐射通量,或者说光源照射在一立体角在单位球上的投影区域的强度。给定一个均匀辐射的全方向光强度,我们就可以计算到每一立体角的能量强度。

这里写图片描述

辐射强度方程定义如下:

I=dΦdω

其中辐射强度 I 等于辐射通量 Φ 除以立体角 ω

有了辐射通量,辐射强度和立体角的知识我们终于可以定义辐射度等式了,它定义的是辐射强度为Φ的光通过立体角ω辐射在区域A的可被观察到的总能量。

L=d2ΦdAdωcosθ

这里写图片描述

辐射度是一个区域内光照量的辐射学度量,按照光的入射(或者来源)角与平面法线的夹角θ计算cosθ。越是斜着照射在平面上光越弱,反之越是垂直照射在表面上的光越强,类似基础光照中的漫反射颜色计算,cosθ直接等于光的方向和表面法线的点积。

float cosTheta = dot(lightDir, N);  

光照亮度方程非常的有用,里面包含了大部分我们感兴趣的物理方程式。如果我们将立体角跟区域A都看作无限小,那么我们就可以使用辐射度来分析一束光线打在空间上一个点的通量,这种关系使我们能够计算单束光线对单个(片元)点的辐射度影响,我们将立体角转化为方向向量,将区域A转化成点P,因此我们可以在shader中直接使用辐射度来计算单束光线对每个片元的贡献。

事实上,当谈到辐射,我们通常关心的是所有射入点P的光线,这些光的辐射度总和称为辐照度。有了辐射度和辐照度的知识,我们可以回到反射方程:

Lo(p,ωo)=Ωfr(p,ωi,ωo)Li(p,ωi)nωidωi

我们知道在渲染方程式中 L 代表某个点P的辐射度,而无限小的入射光的立体角 ωi 可以看作入射光方向向量 ωi ,我们将用来衡量入射光与平面法线夹角对能量的影响的cosθ分量移出辐射度方程,作为反射方程的单独项 n⋅ωi 。反射方程是 P 点的所有反射光 Lo(p,ωo) 沿着 ωo 方向出射的辐射度的总和,或者我们换个说法:Lo 计算的是在 ωo 方向的眼睛观察到的 p 点的总辐照度。

反射方程里面使用的辐照度,必须要包含所有以 p 点为中心的半球 Ω 内的入射光,而不单单是某一个方向的入射光,这个半球指的是围绕面法线n的那一半:

这里写图片描述

为了计算这个区域内的所有值,在我们这里是这个半球,在反射方程中我们使用了一个称作为积分的数学符号 ,来计算半球Ω内所有的入射向量 dωi 。积分计算面积的方法,有分析和渐近(analytically or numerically)两种方法,我们没有可以满足渲染计算的分析法,所以只能选择离散渐近的方式来解决这个积分问题。就具体问题来说,做法是将半球内的所有入射角归到相隔很近的离散点上,然后加总平均离散点各自的结果,这就是我们所说的黎曼和,下面是简单的伪代码表述:

int steps = 100;
float sum = 0.0f;
vec3 P    = ...;
vec3 Wo   = ...;
vec3 N    = ...;
float dW  = 1.0f / steps;
for(int i = 0; i < steps; ++i) 
{
    vec3 Wi = getNextIncomingLightDir(i);
    sum += Fr(P, Wi, Wo) * L(P, Wi) * dot(N, Wi) * dW;
}

dW的值越小结果越接近正确的积分函数的面积或者说体积,衡量离散步幅的dW可以看作反射方程中的dωi。积分计算中我们用到的dωi是线性连续的符号,跟代码中的dW并没有直接关系,但是这种方式有助于我们理解,而且这种离散渐近的计算方法总是可以得到一个很接近正确结果的值。细心的读者会注意到我们可以通过增加步骤数来提高黎曼和的准确性。

反射方程加总了所有的,以各个方向ωi射入半球Ω并打中点P的入射光,经过反射函数fr进入观察者眼睛的所有反射光Lo的辐射度之和。入射光的来源可以是我们熟知的光源,也可以是使用IBL技术利用360度的环境贴图作为来源。

现在只剩下 fr 项是我们不知道的了,这是双向反射分布函数(Bidirectional Reflectance Distribution Function,BRDF),衡量的是表面的材质属性如何影响入射辐照度。

(原文:https://learnopengl.com/#!PBR/Theory, 翻译:coldkaweh)

BRDF

双向反射分布函数(Bidirectional Reflectance Distribution Function,BRDF)是一个使用入射光方向ωi作为输入参数的函数,输出参数为出射光ωo,表面法线为n,参数a表示的是微表面的粗糙度。BRDF函数是近似的计算在一个给定了属性的不透明表面上,每个单独的光线对最终的反射光有多少贡献。举个栗子,如果表面是绝对光滑的(比如镜子),对于所有入射光ωi BRDF函数都将会返回0.0,除非出射方向的角度跟入射方向的角度以面法线为中轴线完全对称,则返回1.0。

BRDF对于材质的反射和折射属性的模拟基于之前讨论过的微表面理论,想要BRDF在物理上是合理的,就必须遵守能量守恒定律。比如反射光永远不应该超过入射光。技术上来说,Blinn-Phong光照模型跟BRDF一样使用了ωi 跟ωo作为输入参数,但是没有像基于物理的渲染这样严格遵守能量守恒定律。BRDF有好几种模拟表面光照的算法,然而,基本上所有的实时渲染管线使用的都是Cook-Torrance BRDF

Cook-Torrance BRDF同时包含漫反射和高光部分:

fr=kdflambert+ksfcooktorrance

其中kd是我们之前提到过的,入射光中被折射的比例,ks是另外一部分被反射的入射光。BRDF等式左边的flambert表示的是漫反射部分,这部分叫做朗伯蒂安漫反射(Lambertian diffuse)类似于我们之前的漫反射着色,是一个恒定的算式:

flambert=cπ

其中c代表的是albedo(表面)颜色,有些类似以前的面的漫反射纹理。除以pi是为了规格化漫反射光,为后期的BRDF积分做准备。

你可能会好奇这里的朗伯蒂安漫反射跟我们以前用的漫反射之间有什么关系:
以前的漫反射是用表面的漫反射颜色乘以法线与面法线的点积,这个点积依然存在,
只不过是被移动到了BRDF外面,写作n⋅ωi放在反射方程靠后位置。

有些别的BRDF漫反射等式可以让效果看起来更真实,但是随之而来的是更高的复杂度更多的系统开销,最后被Epic Games使用的朗伯蒂安漫反射,已经足够满足实时渲染的要求了。

BRDF中的高光部分相对复杂些:

fcooktorrance=DFG4(ωon)(ωin)

Cook-Torrance高光算法中包含了3个部分和一个归一化因子。DFG三个字母分别模拟了一种表面材质的反射属性。D 代表了正太分布函数(normal Distribution function),F 是菲涅尔方程(Fresnel equation),最后的 G 代表几何函数(Geometry function):

  • 正太分布函数:近似的计算受粗糙度影响的微表面,有多少跟半角向量对齐了。这是模拟微表面的最主要的函数。
  • 几何函数:描述的是微表面的自阴影属性,相对粗糙的表面上,微表面可能遮挡其他微表面从而减少灯光的反射。
  • 菲涅尔方程:菲涅尔方程描述的是不同的观察角上表面的反射率。

这些函数每个都模拟了一种物理现象,每个现象你都能找到很多个不同版本的模拟函数,有的更接近真实,有些更更高效,你可以随意的挑选最适合你的版本。Epic Games公司的Brian Karis做了很多相关的研究,我们这里选择Epic Games在Unreal 4上使用的方案:D选择Trowbridge-Reitz GGX, F选择the Fresnel-Schlick approximation,G选择the Smith’s Schlick-GGX。

正态分布函数

正态分布函数D或者叫高光分布,使用统计近似得到微表面对其半角向量h的概率。举个例子,假如有35%的微表面对其了半角向量h,那么以h为输入参数的正态分布函数NDF将会返回0.35。有非常多的NDF函数可以求出这个值,我们这里使用的是一个叫做Trowbridge-Reitz GGX的函数:

NDFGGXTR(n,h,α)=α2π((nh)2(α21)+1)2

这里的h是用来测量微表面的半角向量,a代表的是表面的粗糙度。
如果我们将h放到面法线和光线方向之间,并使用不同的粗糙度作为参数,我们可以得到下面的效果:

这里写图片描述

当粗糙度低(就是表面很光滑),那么在一个很小的范围内会有大量的微表面跟半角向量是对齐的,对这种高集中度NDF处理出来的结果就是一个很亮的光斑。然而,在粗糙的表面上,微表面的朝向更随机,你会法线能对齐h的微表面所在的范围就大了很多,低集中度也给了我们更偏向于灰色的图案。
使用GLSL实现Trowbridge-Reitz GGX正态分布函数的代码应该是这样的:

float D_GGX_TR(vec3 N, vec3 H, float a)
{
    float a2     = a*a;
    float NdotH  = max(dot(N, H), 0.0);
    float NdotH2 = NdotH*NdotH;
    float nom    = a2;
    float denom  = (NdotH2 * (a2 - 1.0) + 1.0);
          denom  = PI * denom * denom;

    return nom / denom;
}

几何函数

几何函数模拟微表面相互遮挡导致光线的能量丢失的现象。

这里写图片描述

类似NDF,几何函数也使用粗糙度作为输入参数,更粗糙意味着微表面产生自阴影的概率更高。几何函数使用由GGX和Schlick-Beckmann组合而成的模拟函数Schlick-GGX:

GSchlickGGX(n,v,k)=nv(nv)(1k)+k

这里k是使用a计算而来的,用于直接光照和IBL光照的几何函数参数:

kdirect=(α+1)28

kIBL=α22

需要注意的是这里a的值取决于你的引擎怎么将粗糙度转化成a,在接下来的教程中我们将会进一步讨论如何和在什么地方进行这个转换。

为了有效的模拟几何体我们需要同时考虑两个视角,眼睛方向(几何遮挡)跟灯光方向(几何阴影),我们可以用Smith函数将两部分放到一起:

G(n,v,l,k)=Gsub(n,v,k)Gsub(n,l,k)

使用Schlick-GGX作为Smith函数中的G可以得到下图的效果:

这里写图片描述

几何函数的是一个在区间[0.0, 1.0]之间的乘法器(multiplier),白色或者1.0表示没有微表面自阴影,黑色或者0.0表示完全被自阴影遮挡。
将几何函数转化成GLSL代码大概是这样的:

float GeometrySchlickGGX(float NdotV, float k)
{
    float nom   = NdotV;
    float denom = NdotV * (1.0 - k) + k;

    return nom / denom;
}

float GeometrySmith(vec3 N, vec3 V, vec3 L, float k)
{
    float NdotV = max(dot(N, V), 0.0);
    float NdotL = max(dot(N, L), 0.0);
    float ggx1 = GeometrySchlickGGX(NdotV, k);
    float ggx2 = GeometrySchlickGGX(NdotL, k);

    return ggx1 * ggx2;
}

菲涅尔方程

菲涅尔方程(Fresnel)定义的是在不同观察方向上,表面上被反射的光除以被折射的光的比例。在一束光击中了表面的一瞬间,菲涅尔根据表面与观察方向之间的夹角,计算得到光被反射的百分比。根据这个比例和能量守恒定律我们可以直接知道剩余的能量就是会被折射的能量。

当我们垂直观察每个表面或者材质时都有一个基础反射率,当我们以任意一个角度观察表面时所有的反射现象都会变得更明显(反射率高于基础反射率)。你可以从你身边的任意一件物体上观察到这个现象,当你以90度角观察你的桌子你会法线反射现象将会变得更加的明显,理论上以完美的90度观察任意材质的表面都应该会出现全反射现象(所有物体/材质都有菲涅尔现象)。

菲涅尔方程同样是个复杂的方程,但是幸运的是菲涅尔方程可以使用Fresnel-Schlick来近似:

FSchlick(n,v,F0)=F0+(1F0)(1(nv))5

F0表示的是表面基础反射率,这个我们可以使用一种叫做Indices of refraction(IOR)的方法计算得到。运用在球面上的效果就是你看到的那样,观察方向越是接近掠射角(与正视角相差90度),菲涅尔现象导致的反射就越强:

这里写图片描述

菲涅尔方程中有几个微妙的地方,一个是Fresnel-Schlick算法仅仅是为电介质表面定义的算法,对于金属表面,使用他们的折射率来计算基础反射率是不合适的,我们需要用别的菲涅尔方程来计算。对于这个问题,我们需要预先计算表面在正视角(即以0度角正视表面)下的反应(F0),然后就可以跟之前的Fresnel-Schlick算法一样,根据观察角度来进行插值。这样我们就可以用一个方程同时计算金属和电介质了。

表面在正视角下的反映或者说基础反射率可以在这个数据库中找到,下面是Naty Hoffman的课程笔记中列举的一些常见值:

这里写图片描述

这里有个有趣的现象(不是定律),所有的电介质表面的基础反射率都没有超过0.17,而金属的基础反射率则高的多,大部分位于0.5到1.0之间。金属对不同颜色(波段)的光线的反射率是不一样的,这也是为什么反射率要分成RGB写的原因,这种现象我们只在金属表面发现过。

相比于电介质表面,金属表面的这些特殊属性引出了所谓的金属工作流,让我们通过一个名为金属度的额外参数来管理表面的材质,这个参数描述的是表面是金属还是非金属。

理论上来说表面金属度应该是一个布尔参数,要么是金属要么不是金属,是互斥的。
然而,大多数渲染管线允许表面金属度参数的范围在0.0到1.0之间,这主要是因为
材质纹理的精度不足以高到可以描述表面的灰尘之类的微小粒子,通过线性的金属
度来表现这些细小的非金属颗粒,让我们可以得到更好的视觉效果。

使用预先计算好的导体和电介质的F0值,我们就能用同一个Fresnel-Schlick算法来模拟这两种类型的表面了,但是在金属表面上我们必须要对基础反射率着色,通常的做法类似下面的代码:

vec3 F0 = vec3(0.04);
F0      = mix(F0, surfaceColor.rgb, metalness);

我们定义一个电介质的基础反射率(0.04),这个值是通过电介质的常见基础反射率推测的一个经验参数,虽然不是准确的,但是能在降低了大量的材质管理复制度的同时实现很不错的效果。然后,根据表面的金属度来混合电介质的基础反射率和材质的本身基础反射率,因为金属会吸收所有折射光所以并没有漫反射颜色,我们可以直接使用表面的颜色来存储它的基础反射率.

(原文:https://learnopengl.com/#!PBR/Theory, 翻译:coldkaweh)

Fresnel Schlick近似算法写成代码:

vec3 fresnelSchlick(float cosTheta, vec3 F0)
{
    return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
}

其中cosTheta是面法线n和观察方向v的点积。

Cook-Torrance反射方程

Cook-Torrance反射方程中的每一个部分我们我们都用基于物理的BRDF替换,可以得到最终的反射方程:

Lo(p,ωo)=Ω(kdcπ+ksDFG4(ωon)(ωin))Li(p,ωi)nωidωi

这个方程完整的定义了一个基于物理的渲染模型,这个方程是就是我们一般所说的基于物理的渲染。如果你还没有完全弄明白也别担心,我们将会把所有讨论的数学方法转化成代码。在下一个教程里,我们将要探索如何利用反射方程渲染出更好的光照效果,所有的知识碎片都会慢慢的融合到一起。

编辑PBR材质

对PBR数学模型有了基本了解之后,我们最后要讨论的是美工应该生成怎样的材质属性,让我们可以直接用在PBR渲染管线里。PBR管线中需要的所有材质参数都可以使用纹理来定义或者模拟,使用纹理我们可以逐像素控制制定的面如何跟光线交互:这个点是否是金属,粗糙度如何又或者表面对不同波长的光有什么反映。
下面你将会看到一些经常在PBR渲染管线中用作输入的纹理:

这里写图片描述

反射率(Albedo):反射率纹理指定了材质表面每个像素的颜色,如果材质是金属那纹理包含的就是基础反射率。这个跟我们之前用过的漫反射纹理非常的类似,但是不包含任何光照信息。漫反射纹理通常会有轻微的阴影和较暗的裂缝,这些在Albedo贴图里面都不应该出现,仅仅只包含材质的颜色(金属材质是基础反射率)。

法线(Normal):法线纹理跟我们之前使用的是完全一样的。法线贴图可以逐像素指定表面法线,让平坦的表面也能渲染出凹凸不平的视觉效果。

金属度(Metallic):金属度贴图逐像素的指定表面是金属还是电介质。根据PBR引擎各自的设定,金属程度即可以是[0.0,1.0]区间的浮点值也可以是非0即1的布尔值。

粗糙度(Roughness):粗糙度贴图逐像素的指定了表面有多粗糙,粗糙度的值影响了材质表面的微表面的平均朝向,粗糙的表面上反射效果更大更模糊,光滑的表面更亮更清晰。有些PBR引擎用光滑度贴图替代粗糙度贴图,因为他们觉得光滑度贴图更直观,将采样出来的光滑度使用(1-光滑度)= 粗糙度 就能转换成粗糙度了。

环境光遮挡(AO):AO贴图为材质表面和几何体周边可能的位置,提供了额外的阴影效果。比如有一面砖墙,在两块砖之间的缝隙里Albedo贴图包含的应该是没有阴影的颜色信息,而让AO贴图来指定这一块需要更暗一些,这个地方光线更难照射到。AO贴图在光照计算的最后一步使用可以显著的提高渲染效果,模型或者材质的AO贴图一般是在建模阶段手动生成的。

美工可以直接根据物体在真实世界里的物理属性,来设置和调整用于渲染的基于物理的材质。基于物理的渲染管线最大的优势在于,材质的物理属性是不变的,无论环境光怎么样设置都能得到一个接近真实的渲染结果,这让美工的人生都变得美好了。基于物理管线的材质可以很简单的移植到不同的渲染引擎,不管光照环境如何都能正确的渲染出一个自然的结果。

(原文:https://learnopengl.com/#!PBR/Theory, 翻译:coldkaweh)

进一步阅读

• Background: Physics and Math of Shading by Naty Hoffmann: there is too much theory to fully discuss in a single article so the theory here barely scratches the surface; if you want to know more about the physics of light and how it relates to the theory of PBR this is the resource you want to read.
• Real shading in Unreal Engine 4: discusses the PBR model adopted by Epic Games in their 4th Unreal Engine installment. The PBR system we’ll focus on in these tutorials is based on this model of PBR.
• Marmoset: PBR Theory: an introduction to PBR mostly meant for artists, but nevertheless a good read.
• Coding Labs: Physically based rendering: an introduction to the render equation and how it relates to PBR.
• Coding Labs: Physically Based Rendering - Cook–Torrance: an introduction to the Cook-Torrance BRDF.
• Wolfire Games - Physically based rendering: an introduction to PBR by Lukas Orsvärn.

原文链接:https://learnopengl.com/#!PBR/Theory

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值