目录

微表面材质模型

微平面理论 Microfacet Theory

BSDF(浅浅的提一下)

微表面BRDF的实现

Cook-Torrance BRDF

漫反射的BRDF

镜面反射的BRDF

1 法线分布函数 D

GGX分布简介

Trowbridge-Reitz 分布(GGX分布) 公式

表面粗糙度​编辑的取值

实现代码

2 阴影遮挡函数 G

Smith遮蔽函数

Disney实现方法

实现代码

UE4方法-SchlickGGX

实现代码

3 菲涅尔项 F

实现代码

参考


微表面材质模型

Microfacet Material,也是真实感材质模型,同时是PBR(Physicallly-Based-Rendering 基于物理渲染)基于的东西。

之前作业中涉及到的 BRDF,即Bidirectional Reflectance Distribution Function,双向反射分布函数,微表面模型就是基于物理的BRDF,也是最常用的一种物理BRDF。

微平面理论 Microfacet Theory

下面是我结合课程内容对微平面理论的一些理解。

现实生活中,物体表面都是不规则的,离近了看会有坑坑洼洼的感觉,这就意味着这些坑坑洼洼的小表面反射的光方向都不同。但对于每个小表面来说,入射的光线只会被分为反射光和折射光。基于此,微表面模型假设:①微表面的尺寸小于着色区域大于可见光波长;物体表面从远处看是外观(diffuse、glossy),近处看是一个个微小的、平的几何面,②这些平坦的几何面都符合几何光学定律,可以看成是一个个非常小的镜子;③光线只在微表面之间弹射一次(single-bounce),一次之后弹射的光线不改变着色结果。(关于假设③,这里不考虑下图所示的光线多次弹射的情况,次表面散射技术后面会单独开一贴讲讲)

有了这些假设,解微表面材质模型的关键在于:解微表面朝向的分布,具体来说就是微表面的法线分布。如下图,对于两种典型的材质与法线分布的关系:法线集中->glossy;法线发散->diffuse。

BSDF(浅浅的提一下)

BSDF(Bidirectional Scattering Distribution Function,S表示的就是“散射”),描述了光如何在物体表面散射,反映了光入射和出射强度的对应关系。之前我们涉及到的反射模型BRDF透射模型BTDF(T指Transmittance,透射)是BSDF分别只限制了反射和透射的模型结果。BSDF本身是BRDF和BTDF综合作用。

微表面BRDF的实现

一般常用Cook-Torrance BRDF来实现Microfacet:

Cook-Torrance BRDF

Cook-TorranceBRDF考虑了微表面的漫反射和镜面反射,公式如下:

其中:——折射光占入射光比例;

——反射光占入射光比例;

——漫反射(diffuse)的BRDF;

——镜面反射(specular)的BRDF;

漫反射的BRDF

上面截图均来自GAMES101课程的P17节:P17-GAMES101-现代计算机图形学入门-闫令琪.漫反射diffuse项用来刻画材质的着色,漫反射的BRDF是个常数项,漫反射朝半球方向均匀弹出,由课上老师介绍的推导过程,可以直接写出漫反射的计算式:

其中, 是个Vecotor3f向量,储存了颜色信息。

镜面反射的BRDF

公式如下:

其中,为入射方向;为出射方向;为半角向量(halfway vector),即二者中间向量;为菲涅尔项;为阴影遮挡函数;为法线分布函数。

值得一提的是,Cook-Torrance BRDF模型的镜面反射项(specular reflection)是根据Torrance-Sparrow BRDF描述的完整各向同性材质反射模型,再将他应用于图形学得到的这一项值用来刻画材质的高光。

接下来分别对法线分布函数、阴影遮挡系数和菲涅尔项做介绍。

1 法线分布函数 D

首先要明确一点的是,法线分布函数有Phong分布、Beckmann分布、GGX分布(Trowbridge-Reitz 分布),下文中将只结合GGX分布来介绍法线分布函数。

法线分布函数(Normal Distribution Fuction),NDF,记作:.关于法线分布函数的定义,How Is The NDF Really Defined? – Nathan Reed’s coding blog中是这么描述的:“NDF statistically describes the microscopic shape of the surface as a distribution of microfacet orientations.”,即:把微表面的形状描述为表面朝向的分布。目前,主流的法线分布函数已经从传统的Blinn-Phong分布和Beckmann分布,发展到更接近真实世界材质外观的GGX分布。

GGX分布简介

简单介绍一下GGX这个符号,GGX我们经常在各种地方看到。其实GGX分布是Walter等人在论文Microfacet Models for Refraction through Rough Surfaces (cornell.edu)

中提到的一个新的微表面分布函数,该函数能够模拟出粗糙表面的透射效果,下图是论文中展示的利用GGX渲染出的一个玻璃球效果图:

GGX分布是Walter等人的提出的,其认为NDF遵循以下方程:

其中,——表示宏观(远处看)表面一小块平的区域;——方向是的所有小的平的区域的总面积。

这个公式就可以看出,NDF并不表示密度,而是单位面积、单位立体角的微平面的面积。对上式积分:

其中,——微表面投影到宏观表面上的面积;式右边表示正半球立体角的积分,左边表示在所有朝向的微平面面积和,且宏观表面所有方向上的微表面投影面积和等于。因此式右边应等于1.

此外,GGX分布还有一个限制条件:对于任意观察方向,有:

该式的几何意义如下图:

可以看到,在方向上,要想求在宏观表面上的投影面积,如果如上图所示中朝向为橙色箭头的微表面,求投影后会正负抵消,剩下的就是朝向是蓝色箭头的微表面的投影和。因此投影可以表示为

Trowbridge-Reitz 分布(GGX分布) 公式

又称为GGX分布,论文Microfacet Models for Refraction through Rough Surfaces中给的形式为:

化简后得到可以用于计算的式子:

其中:

:微表面粗糙度,一般在[0,1]之间,越大越粗糙;

:宏观表面法向量;

:微平面法向量,与上文相同,即入射方向和出射方向的中间向量。

表面粗糙度的取值

注意!这里对于微表面粗糙度的取值,无论是在GGX分布还是在迪士尼用的GTR分布里,都建议将宏观表面粗糙度roughness映射成真正的微表面粗糙度再进行运算,因此roughness在计算时实际上是4次方。

关于表面粗糙度的取值,参考文章中是这么说的:“在迪士尼原理着色模型Disney principled shading model中,推荐将粗糙度控制以暴露给用户,其中是0到1的用户界面粗糙度参数值,可以让GGX分布更线性的方式变化,且这种方式更加实用,不少使用GGX分布的引擎与游戏都采用了这种映射方式。”这里的表示,粗糙度.

实现代码

float DistributionGGX(float NdotH, float roughness) {float a = roughness * roughness;float a2 = a * a;float pi = 3.1415;float m = NdotH * NdotH * (a2 - 1) + 1;return a2 / (pi * m * m);//注意分母不能为0,真正使用需要给定一个最小值
}

了解到这里,已经足够写出GGX密度分布函数的代码了,如果想要深入了解公式如何推到的,可以细看论文中的推导过程。

到这里我们就能理解了:为什么说与Phong和Beckmann相比,GGX更接近真实情况呢?因为GGX可以更好的表现金属高光边缘的消散(拖尾)效果,这里可以参考图形渲染基础:微表面材质模型 - 知乎 (zhihu.com)一文中的解释:

由于GGX的高光有更长的拖尾,因此在表现真实金属表面的时候更胜一筹。

2 阴影遮挡函数 G

微表面是凸凹不平的,从不同观察方向看难免会产生一个表面被另一个表面遮挡的情况(如下图,图源水印)。其中,光照illumination遮挡称为自阴影;从视线viewing看过去被遮挡叫做自遮挡。

BSDF定义了一个几何函数  用以模拟微表面由于相互遮挡而导致光线的能量丢失的现象,这个函数就叫做阴影遮挡函数,从定义不难看出,这个函数的取值应该也是从[0,1]的。同时,几何函数有两种形式:

——微平面在单个方向(光照方向or视线方向)上可见比例,光照对应遮蔽函数 masking function;视线对应阴影函数 shadowing function.

——微平面在光照和视线方向共同可见的比例,称为联合遮蔽阴影函数 joint masking-shadowing function. 

其中,推导而来,同时一般微表面材质计算所说的几何函数就是指

Smith遮蔽函数

Smith遮蔽函数,即Smith masking function。由于自阴影本质与自遮挡是一样的,都是可见微表面才能对着色有贡献,因此Smith认为二者是相互独立的,有了如下的乘积的Smith Function:

其中 分别表示入射和出射方向,对应的话就是光源和观察方向。

Smith遮蔽函数对于随机表面的非常准确,但对于一些非随即表面、重复性的图案表现精度会降低(例如面料这种高重复性的结构)。因此在进行布料这种重复性结构图案一般会采用一些专门的shading model去计算。

Disney实现方法

参考上图, 定义函数,,表示法线方向为的微表面们在观察方向上未被遮挡的比例。根据上述已经讨论过的一个GGX的规定,对于任意观察方向,有:

那么就有:

其中,用来剔除背向观察方向的微表面。

记下来为了简化的计算,假设其与微表面朝向无关,可以把它提出来。再通过与视线夹角大于和小于的微表面面积和都表现出来,分别命名为,得到:

根据该式,结合能推导出准确的.

其中:,将粗糙度重映射以减少光泽面的极端增益,使粗糙度变化更加平滑。

实现代码

//对G1的实现
float SmithG_GGX(float NdotV, float roughness) {float r = 0.5 + roughness / 2.0f;float m = r * r + (1 - r * r) * NdotV * NdotV;return 2.0f * NdotV / (NdotV + std::sqrt(m));
}//光源方向和观察方向分别计算ggx1和ggx2,相乘得到G
float GeometrySmith(Vector3f N, Vector3f V, Vector3f L, float roughness) {float NdotV = std::max(dotProduct(N, V), 0.0f);float NdotL = std::max(dotProduct(N, L), 0.0f);float ggx1 = SmithG_GGX(NdotL, roughness);float ggx2 = SmithG_GGX(NdotV, roughness);return ggx1 * ggx2;
}

UE4方法-SchlickGGX

UE4采用的方法是用Schlick近似Smith来计算几何函数,具体怎么算的可以参考这篇文章:

图形学|PBR:Schlick近似方法 - 知乎 (zhihu.com)

其中:

实现代码

float GeometrySchlickGGX(float NdotV, float roughness) {float r = roughness + 1;float k = r * r / 8;float m = NdotV / NdotV * (1.f - k) + k;return NdotV / m;
}//光源方向和观察方向分别计算ggx1和ggx2,相乘得到G
float GeometrySmith(Vector3f N, Vector3f V, Vector3f L, float roughness) {float NdotV = std::max(dotProduct(N, V), 0.0f);float NdotL = std::max(dotProdoct(N, L), 0.0f);float ggx1 = GeometrySchlickGGX(NdotL, roughness);float ggx2 = GeometrySchlickGGX(NdotV, roughness);return ggx1 * ggx2;
}

除了以上两种方法还有其他的,想了解的话可以看看这篇文章:PBR GGX Specular G 几何函数 - 掘金 (juejin.cn)

3 菲涅尔项 F

就是计算反射光占比。对于菲涅尔效应和菲涅尔项的计算在作业5中有介绍,这里就不赘述了,直接贴代码,想要了解的可以移步GAMES101作业5-从头到尾理解代码&Whitted光线追踪_flashinggg的博客

实现代码

这里直接贴出框架中菲涅尔项的计算函数:

    //菲涅尔方程,与作业5相同void fresnel(const Vector3f &I, const Vector3f &N, const float &ior, float &kr) const{float cosi = clamp(-1, 1, dotProduct(I, N));float etai = 1, etat = ior;if (cosi > 0) {  std::swap(etai, etat); }// Compute sini using Snell's lawfloat sint = etai / etat * sqrtf(std::max(0.f, 1 - cosi * cosi));// Total internal reflectionif (sint >= 1) {kr = 1;}else {float cost = sqrtf(std::max(0.f, 1 - sint * sint));cosi = fabsf(cosi);float Rs = ((etat * cosi) - (etai * cost)) / ((etat * cosi) + (etai * cost));float Rp = ((etai * cosi) - (etat * cost)) / ((etai * cosi) + (etat * cost));kr = (Rs * Rs + Rp * Rp) / 2;}

看到这里,实现作业7中的微表面材质提高部分就没问题了,会另开一贴介绍具体的实现代码.

以及之后会再总结一下微表面材质学习引出的其他拓展内容,例如PBR除了微表面其他的内容是什么?Disney Principle是什么?等等...

参考

图形渲染基础:微表面材质模型 - 知乎 (zhihu.com)

【基于物理的渲染(PBR)白皮书】(四)法线分布函数相关总结 - 知乎 (zhihu.com)

How Is The NDF Really Defined? – Nathan Reed’s coding blog (reedbeta.comd

基于物理的渲染:微平面理论(Cook-Torrance BRDF推导) - 知乎 (zhihu.com)

GAMES101作业7提高-实现微表面模型你需要了解的知识相关推荐

  1. GAMES101作业7及课程总结(重点实现多线程加速,微表面模型材质)

    目录 闲言碎语 最终全部效果展示(均为1024×1024×512ssp) 课程总结与理解(Path Tracing) 框架梳理 任务一:迁移相关代码 任务二:实现path tracing 任务三:多线 ...

  2. 粗糙表面的微表面模型——Physically Based Material

    关于文章 Microfacet Models for Refraction through Rough Sufaces的一点笔记,欢迎指正. BSDF BSDF(Bidirectional Sactt ...

  3. 微表面模型Beckmann–Spizzichino distribution的概率密度函数推导

    微表面的法线分布定义如下: 得到:                         (1)式      看Beckmann–Spizzichino中,各向同性的分布定义: 根据(1)式,p(θ, φ) ...

  4. 微表面模型GGX/Trowbridge-Reitz概率密度函数的推导

    先说明一下,我们平常说的GGX的正确技术名称就是trowbridge-Reitz. 各向同性GGX 微表面的法线分布定义如下: 其中D(h)是法线分布函数,cosθh是N dot h. 根据概率密度函 ...

  5. Games101 作业6 提高内容(SAH算法)

    本文只应用于个人学习总结. 目录 一.模型分析 1.按空间平均分配(NAIVE) 2.按物体平均分配 二.SAH 1.原理分析 2.代码实现 在作业7​​​​​​中的BVHAccel模块中已经分析了B ...

  6. 基于物理的渲染—更精确的微表面分布函数GGX

    原文链接:https://blog.uwa4d.com/archives/1582.html 在上次介绍的微表面模型文章中,我们曾提到过模型中有一个模拟物体表面反射高光的函数 Rs .在该函数中,有一 ...

  7. GAMES101作业7-路径追踪实现过程代码框架超全解读

    目录 Path Tracing算法过程讨论 蒙特卡洛积分 直接光照 direct illumination 间接光照 indirect illumination ​编辑 合成全局光照 解决一些存在的问 ...

  8. Games101--现代计算机图形学入门 作业3笔记(渲染管线、着色模型、双线性插值)

    一.渲染管线 一.作业要求 在这次编程任务中,我们会进一步模拟现代图形技术.我们在代码中添加了ObjectLoader(用于加载三维模型),VertexShader与FragmentShader,并且 ...

  9. GAMES101作业5-从头到尾理解代码Whitted光线追踪

    目录 Whitted Ray-Tracing Whitted光线追踪 What Why How 1 发射主射线primary ray 实现步骤 (1)定义相机 (2)计算primary主射线的方向 R ...

最新文章

  1. 用JavaScript来实现链表LinkedList
  2. 【 FPGA 】设计一个通用移位寄存器
  3. 【面试虐菜】—— 常用SQL语句
  4. 旅行商问题(Traveling Saleman Problem,TSP)
  5. eclispe使用外部tomcat总结
  6. RSACryptoServiceProvider加密解密签名验签和DESCryptoServiceProvider加解密
  7. sqlalchemy与mysql区别_sqlite3和sqlalchemy有什么区别?
  8. 超乎想象,数据揭示自学成才的码农为何备受青睐
  9. C语言的soap报文处理转义字符,webservice传递特殊字符时的解决办法
  10. 4.SOA架构:服务和微服务分析及设计--- Web服务及微服务的分析与建模
  11. 标准工时管理软件VIOOVI助力企业数字化转型
  12. wamp mysql 密码_WAMP中的mysql设置密码
  13. BGP路由技术详解(一)
  14. 【Endnote X9服务器运行失败】
  15. 为什么要给软件做测试?如何测试呢?
  16. java架构图软件,如何画好IT项目中的各种架构图
  17. Windows应用程序安装向导制作
  18. 银行 结算 清分清算 对账
  19. 【NOIP2013模拟】Freda的传呼机
  20. 科创板|龙软科技国科环宇等4公司中止审核

热门文章

  1. starUML建模C++【逆向工程】
  2. [华语][张国荣][16CD][1978-1987][APE+CUE][3.94G][115][sqhhj0622#HD2PT]
  3. MES汽车行业实施方案
  4. LPC1788在外部RAM调试总结
  5. [小黄书管理平台]登录页面和模型驱动表单
  6. 爬虫逆向基础,认识 SM1-SM9、ZUC 国密算法
  7. 用jQuery控制键盘上下左右键切换选择元素
  8. SQL查询语句起别名
  9. 关于PyQt5在Label标签插入图片并且实现图片的拖拽和缩放
  10. 获取全国火车车站信息