找回密码
 立即注册
查看: 457|回复: 0

[简易教程] [深入浅出] PBR x BRDF 原理与Unity实现

[复制链接]
发表于 2021-11-29 16:40 | 显示全部楼层 |阅读模式
各位同学大家好。在今天的课程当中呢,我将给大家介绍,目前在游戏渲染领域被广泛使用的PBR技术,翻译成中文叫基于物理的渲染。那么什么是PBR呢?它在游戏开发领域究竟有什么作用呢?
简而言之,PBR就是用来替代我们传统的局部光照技术的,它可以帮助我们来实现照片级或者漫画级的高质量实时渲染。
不管是写实风格的渲染还是二次元卡通风格的渲染,作为游戏开发者、技术美术,掌握PBR。通过今天的课程,我将带大家深入浅出的理解PBR整体的框架和思路。
<hr/>

本文版权属“优梦创客”所有,遵守CC-BY4.0协议,可以转载但须注明出处,并保留完整原文。
如果你学习过程中感觉有难以理解的地方,可以随时跳转我们的详解视频
<hr/>

主题:


  • 基本知识
  • 传统光照模型
  • 传统光照模型的高光效果加强
  • BRDF
  • 微表面的概念
  • BRDF中的可见性函数
  • BRDF中的菲涅尔函数
  • 更加物理的BRDF
  • Unity引擎中的BRDF
  • 标准材质的光照参数在着色器代码的实现
  • BRDF学习精要
<hr/>

在谈及PBR基于物理的光照以及其中核心的BRDF函数之前,我们要先回顾一下光照的历史,以及PBR的由来(现在先将PBR和BRDF的概念等同,稍后会讲到这两者的关系)
上图中,采用了PBR光照模型的Shader(上右侧图)明显比只采用非写实渲染的Shader(上左侧图)跟环境能更好的融合
所以,即使是非写实渲染(NPR)的光照,也能从PBR中获益!这是我们要厘清的一个误区——PBR只能用于写实光照渲染,其实大量的PBR Shader被用于风格化渲染(详见我的教程)。
那么PBR为什么会出现呢?他究竟解决了什么问题呢?这还要从传统光照模型说起:

  • 首先,传统的局部光照模型

    • 只计算直接光照
    • 直接光=环境+漫反射+高光反射
    • 由于局部光照模型没有考虑环境中光线能量粒子的反弹,以及其他PBR要考虑的光线的物理特性,因此效果是比较局限的

  • 全局光照模型

    • 计算直接光+间接光
    • 更加真实

  • 另外,不管是计算直接光还是间接光,我们都需要考虑到光线的物理特性

    • 传统局部光照模型基于经验/感性,得到的光照效果可能不符合光的能量守恒定律,因此不真实
    • 而基于物理的光照则充分考虑了光的物理特性,更加真实

<hr/>



特点:

  • 局部光照,不考虑光线反弹
  • 基于视觉感受,不考虑光能量的传递、反弹等特性
公式:

  • 光照=环境光+漫反射+高光
  • 漫反射计算模型:

    • Lambert
    • Half-Lambert

  • 高光计算模型:

    • Phong
    • Blinn-Phong

参见:《Unity小白的TA之路》→渲染流水线→光照模型→三种局部/经验/传统光照模型



半兰伯特光照模型解决了兰伯特模型物体背面没有细节的问题



布林冯模型解决了冯模型高光有明显边缘的问题


要理解光照计算,首先要知道点乘(dot)和余弦(cos)的概念,不过这都是中学数学知识,在此不再赘述,需要了解可以参考我们的Unity小白的TA之路
在这里,我们约定:

  • cosθ_l:表示灯光和法线的夹角系数(夹角越小系数越接近1,夹角越大系数越接近0,超过90度的夹角忽略)
  • cosθ_v:表示视方向和法线的夹角(夹角越小系数越接近1,夹角越大系数越接近0,超过90度的夹角忽略)
  • cosθ_:表示视半角方向和法线的夹角(夹角越小系数越接近1,夹角越大系数越接近0,超过90度的夹角忽略)
下面要讨论到的光照计算都跟这几个夹角相关
<hr/>要理解PBR的光照模型,首先我们要了解传统光照模型:
传统光照模型由:

  • 漫反射颜色
  • 高光反射颜色
组合而成(Blinn-Phong模型)


<hr/>为了让光斑越小越亮,我们增加下图第二行公式的


第二行的新公式的变化主要有三点:

  • Diffuse光增加了一个(1/π)的系数,它会让我们在给光源设置Diffuse的时候更加直观,不过很多时候引擎会将这个步骤在内部预先进行处理。
  • 高光也增加了一个系数 (m+8) / 8π ,这个系数很有意思:在原公式中,m越大高光的光斑越集中,加上这个参数后我们发现,m越大除了让光斑越集中,还能让高光更亮。这是很合理的物理现象,光的能量越密集,单位面积上的强度就越大,总能量不变。这个做法叫“归一化”。
  • 此外高光部分还增加了与cosθL相乘的部分,有点类似Diffuse了。这个其实是更接近真实的情况,因为所有光线照射的效果都需要考虑受光面倾斜的情况,只是老公式认为在高光部分这个影响不明显,于是省略掉以节省性能开销。
<hr/>

我们看括号里的部分,这就是一个BRDF。
BRDF不是一个公式,是一类公式,学名“双向反射分布函数”(Bidirectional Reflectance Distribution Function),说人话就是:给一个入射角度和一个观察角度,它能给出一个决定最终射向观察角度的光的强度的系数(这样的说法并不严谨,但在本文中按这样理解没太大毛病),凡是干这个事情的都叫BRDF函数,有的BRDF函数离真实物理法则更接近,有的则很假。常用的Unity引擎中就包含了三套BRDF公式,用作不同性能机型的适配。
fBRDF分成漫反射和高光反射部分:
第一部分是一个Lambert光照公式,用来计算Diffuse,纳尼?好像还缺个cosθL?注意注意,这个已经被抽取到括号外了,也就是BRDF公式之外,所以括号中的BRDF部分中,我们认为Lambert光照就是第一部分。
第二部分是高光部分:它的作用前面已经讲过了,是控制高光产生的光斑的集中度。以一个球体为例,越接近光斑中心,半角向量和法线的夹角越小,高光越亮,越到光斑外围,半角向量和法线的夹角越大,高光越弱。听上去挺合理,但翻开物理课本回顾一下就会发现:理论上只有半角向量和法线完全重合的时候才有反射光线被视线接收到,凭什么这里还能允许它们存在夹角?而且夹角的变化还导致反射光线强度的变化,这个怎么来的?
这里又有一个新的名词出现了:微表面。
<hr/>


我们在渲染中是逐个像素进行处理的,每个像素虽然足够小了,但在这个像素覆盖的范围内还有无数细微的起起伏伏的物理结构,有起伏,就会有变化的法线。我们渲染时用到那个像素法线只能算是所有细微面的法线的平均值,实际上这个像素点内部朝各个方向的法线都是有的,只是所占比例有所不同。
在渲染的时候我们当然不会把像素内部的法线逐个取出来再去计算光照,这么做也未免太耗费性能了,我们只需要把能反射到视线的法线所占的比例找出来,用它将高光强度修正一下就好了。其实我们常说的“半角向量”就是指能反射到视线的法线
而我们讨论的BRDF的高光部分干的就是这个事,它根据半角向量和平均法线的夹角,计算出指向半角向量方向的微表面法线的比例。这么牛逼的事情一定要有个牛逼的名词来描述它,就叫“法线分布函数”,缩写为“NDF”,文中我们以D来表示
法线分布函数能解释表面上细微的凹凸不平对光的反射产生的影响,但是有一个前提:微表面上所有的点都能够接受到光线,并且能够反射出光线,事实上真实的物理表面大部分是达不到这样的条件的,如图所示:
<hr/>

在这样的凹凸的表面上,由于自身的遮挡,有很多点根本无法接受到入射光线,也有很多点反射的光线无法射出表面。因此,我们此处再定义一个函数叫“可见性函数”
它的作用就是根据给定的入射光线和出射光线的方向,计算出不被自身挡的光线的比例。
回头看看我们的BRDF公式里,貌似没有啊?没关系,可以将没有V的BRDF函数视为V=1的BRDF函数——现在的BRDF还不是最终的BRDF,我们先将V想象成占位符,后面逐步替换成基于物理的可见性函数
最后只剩一个东西要讲解一下了,就是高光强度Cspec,在公式中,这是个常量,但却不是符合真实物理规律的。
<hr/>


在物理书讲反射与折射的章节上我们学过,在一个反射面上:

  • 入射角度越“倾斜”,反射的光线越多,折射的光线越少;
  • 入射角度越“直”,   折射的光线越多,反射的越少
这个现象叫做菲涅尔现象。
所以这里的高光强度需要用一个函数来表示,本文写做F。在原公式中我们可以机智的认为它把这个函数也用一个常量函数来表示。
同样的,我们先将F想象成占位符,后面逐步替换成基于物理的可见性函数
<hr/>

在这里,PBR光照有三点是突破我们基于传统的“局部光照”的认知的:

  • 高光集中度对光斑亮度有影响
  • 受光面夹角对光斑亮度有影响
  • 高光颜色不是常量
因此,我们需要一个更加物理的BRDF
<hr/>

前面我们使用的光照模型有4点问题:

  • 法线分布函数的自变量基于一个没有太大物理意义的m。
  • 菲涅尔函数是高光常量,表示完全没有考虑入射光线角度不同带来的反射变化。
  • 可见性函数是常量1,表示所有微表面上的光线完全没有自遮挡。
  • 漫反射和高光之间完全独立,没有考虑能量守恒的关系。
这四点问题,我们会在后面的学习中予以改进
<hr/>


如果你想知道更多关于PBR和BRDF的知识,包括但不限于:

  • 如何在Unity引擎中使用和定制BRDF?
  • Standard Shader / Lit Shader面板参数的代码实现?
  • Shader Graph跟PBR什么关系?
  • 为什么BRDF很重要?
  • BRDF怎么学?
  • TA是一个岗位还是多个岗位?
请大家保持关注我们



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-5 18:26 , Processed in 0.094142 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表