最近做了Ward BRDF的实现,相对于之前的lambert,phong来说,Ward是一个真正意义上的各向异性BRDF,但同样的,Ward模型也是一个基于经验的模型,并不是物理上正确的。它由ward本人于1992年在《Measuring and modeling anisotropic reflection》一文中首次提出,到目前为止它已经是图形学中广泛应用的一种BRDF了。有不少文章专门讲述了Ward的理论与实现,其中比较著名的是Bruce Walter在2005年写的《Notes on the Ward BRDF》,该文章从理论到实现都讲了一遍。我在做Ward实现的时候就主要参考了这篇文章。Ward的BRDF定义用到了half vector的概念,half vector定义为h=(wi+wo)/|wi+wo|,就是入射光向量与出射光向量求和再标准化。按照ward本人的描述,Ward BRDF有两个组成部分,一个是经典的漫反射部分ρd/π,另外一个部分有3个参数ρs,αx与αy。其实ρs就跟phong模型中的镜面反射系数是差不多的,而αx与αy控制了高光在x和y方向上的范围(也可以理解成表面在x和y方向上的粗糙程度)。当αxy的时候,该brdf描述的是一个各向同性的反射模型,其效果和phong很类似,反之则描述各向异性反射模型。接下来出场的是一个非常重要的函数:

f函数描述的是该表面上已知入射角向量i,那么得到出射角向量为o的概率是多少。由于BRDF具有对称性,所以反过来也是一样的,即已知出射角向量o,得到入射角向量为i的概率就是这个函数要求的东西。这其中的θi,θo,θh,Φh都是在表面局部坐标系下计算的,见下图:

(图中的向量v与z轴夹角写为θv,Φv则是v在平面xOy上的投影与x方向的夹角)

在表面局部坐标系下,z方向就是表面法线方向,x和y方向分别表示了表面的切向量和副法线向量方向(这其实是表面的切向空间,之前在介绍法线贴图的文章中已经讲过了,这里就不重复了,详情可以参考http://www.cnblogs.com/starfallen/archive/2013/03/29/2989277.html)。于是可以知道公式中的θi,θo,θh分别代表了入射向量i,出射向量o以及半角h与表面法向量的夹角,Φh则是h在物体表面上的投影与表面切向量的夹角。这里有一个必须要注意的问题,就是公式中的入射与出射向量i,o都是局部坐标系下的值,如果我们将世界坐标系中的相关向量带入进去则会出错。正确的做法是每次计算该公式前时做一次世界坐标系到局部坐标系的转换,在完成后再转换回去。所以这就是pbrt等开源构架在做bsdf采样的时候要求入射向量与出射向量都是基于局部坐标系下的原因。光有f函数显然是不够的,为了能使Ward BRDF应用在全局光照中,必须要能对其进行重要性采样,《Notes on the Ward BRDF》一文中详细介绍了其方法。Ward BRDF重要性采样的主要思想在于根据已知条件先确定半角h,再利用反射公式o=2*(i*h)h-i得到最终的出射向量。文中给出了h的具体求法:

其中u和v是两个不相关的0~1间的随机数,由于θh的公式中包含有Φh项,所以在实际计算的时候应当先算Φh。在计算Φh的时候,有一个必须注意的地方,就是要保证2πv和Φh在同一个象限,因为在程序设计时,我们通常用到的atan函数得到的结果是在-π/2~π/2之间的。

另外,在编写程序的时候,还有一个细节值得注意,那就是重要性采样函数在某些情况下得出的向量o可能不在法线一边,通俗地说就是光线与表面作用后穿透到物体内部去了。为了更好地说明这一现象出现的根源,我用一个示意图来解释它:

该图描述了在物体表面某处的各个向量的情况,绿色的向量z是表面法向量,红色的i是已知的入射向量,蓝色的h是随机采样得到的半角向量,由于h一定会与法向量z有一定夹角(那种h刚好与z重合的情况实在是太罕见了),那么就一定存在着采样得到的出射向量o位于法向量另一侧的情况(这种情况出现的几率随着i与z的夹角的增大而增大)。这一问题有很多处理方法,最简单的,也是我采用的方法是忽略这样的采样值,认为它被表面吸收了。实际上这样处理并不会导致错误,随着采样值的增多,最终结果会逐渐收敛到正确的解。在这个问题上,我们不用过多地担心,因为Ward模型本身是一个经验上的模型,并不保证物理上的正确性。实际上即使是phong模型,当入射角度与法线夹角很大的时候也会出现这种情况。

再说αx与αy两个参数,一般我们会在0-1之间取值,取值越大,得到的高光区域越大。如果说对于一个点光源,当αxy的时候,高光呈现圆形的话,αx≠αy时高光就是椭圆形的,而且αx与αy的比例越大,椭圆越扁。当αx与αy其中一项取值为1的时候,高光在这个方向上的范围为无限大(理论上如此,但实际上会受限于表面大小等因素)。下面一组图中我实验了比较有代表性的三种情况:

由此可见,我们可以很方便地调节这两个参数来模拟各类各向异性材质。实际上,Ward BRDF很适合被用来模拟各向异性高光,以及各向异性反射,比如各种磨光的金属表面。

最后,放上一张我渲染的含有Ward模型的结果:

Ward BRDF实现心得的更多相关文章

  1. Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF

    在实时渲染中Physically-Based Rendering(PBR)中文为基于物理的渲染它能为渲染的物体带来更真实的效果,而且能量守恒 稍微解释一下字母的意思,为对后文的理解有帮助,从右到左L为 ...

  2. 我的MYSQL学习心得(一) 简单语法

    我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  3. NoSql数据库使用半年后在设计上面的一些心得

    NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...

  4. 我的MYSQL学习心得(二) 数据类型宽度

    我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  5. 我的MYSQL学习心得(三) 查看字段长度

    我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  6. 我的MYSQL学习心得(四) 数据类型

    我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(五) 运 ...

  7. 我的MYSQL学习心得(五) 运算符

    我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  8. 我的MYSQL学习心得(六) 函数

    我的MYSQL学习心得(六) 函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

  9. 我的MYSQL学习心得(七) 查询

    我的MYSQL学习心得(七) 查询 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

随机推荐

  1. 记2012-2013年一路的Windows Phone历程

    昨天和秦春林同学小聚一次,不厌其烦的唠叨各种认识了许多年的纪念,感觉他仍然保持着那份对技术的追求和梦想,而我却已经变得逐利,每个人享受幸福的方式不一样,因此追逐幸福的过程也就是没有办法一样了,你无法知 ...

  2. 加密算法使用(一):用CRC32来压缩32uuid字符串

    CRC32相比MD5重复率较高, 不过我们仍然可以使用CRC32然后转长整形的方式将32位的UUID字符串压缩成更短的整形唯一标识. /** * * @Title: getCRC32Value * @ ...

  3. 完成一个MVC+Nhibernate+Jquery-EasyUI信息发布系统

    一.最近学习了Jquery-EasyUI框架,结合之前用过的MVC3+Nhibernate做一个信息发布系统,对工作一年半的自己做一个总结吧!(也正好 供初学者学习!) 二.先上截图(系统简介),让大 ...

  4. File类和RandomAccessFile类

    目录 File类     File类常用操作     (1)创建文件     (2)删除文件     (3)创建文件夹     (4)列出指定目录全部文件     (5)删除目录 RandomAcce ...

  5. QT cannot open output file debug\OpencvTest.exe: Permission denied

    问题:调试运行QT的时候遇到这个问题,发现时是由于没有正常关闭程序所致,导致后台有之前运行的程序在跑(电脑环境win7 64 Qt5.2.1 opencv2.4.6). 目前解决办法:手动关闭已在运行 ...

  6. 深入探索Java 8 Lambda表达式

    2014年3月,Java 8发布,Lambda表达式作为一项重要的特性随之而来.或许现在你已经在使用Lambda表达式来书写简洁灵活的代码.比如,你可以使用Lambda表达式和新增的流相关的API,完 ...

  7. Html中metra的含义

    from: http://dev.csdn.net/article/60/60902.shtm meta是用来在HTML文档中模拟HTTP协议的响应头报文.meta 标签用于网页的<head&g ...

  8. 喝咖啡写脚本,顺便再加一点点CSS语法糖 1.选择环境

    经过对前端开发的初步了解,大体上发现了以下几点,前端开发需要使用脚本语言,主要是JavaScript,需要Html,需要CSS,这些东西相信很多人已经很熟了.但是仅仅只是学习一点简单的JS,配合Htm ...

  9. 多个相同name的文本输入框,输入其中一个后,使剩下的不能输入值

    可以用blur或keyup事件响应: 实现一: <body> <input type="text" id="AfterOtOt1" name= ...

  10. bootstrap tooltip 显示提示信息

    参照网上文档,是这样说的, <a data-toggle="tooltip" data-placement="top" title="这是要提示 ...