最近做了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. C语言 百炼成钢19

    /* 题目55: 有一个字符串符合以下特征(”abcdef,acccd,eeee,aaaa,e3eeeee,sssss,";),要求写一个函数(接口),输出以下结果 1) 以逗号分割字符串, ...

  2. string与stringBuilder的效率与内存占用实测

    using UnityEngine; using System.Diagnostics; using System.Text; using UnityEngine.UI; public class s ...

  3. 对RESTful Web API的理解与设计思路

    距离上一篇关于Web API的文章(如何实现RESTful Web API的身份验证)有好些时间了,在那篇文章中提到的方法是非常简单而有效的,我在实际的项目中就这么用了,代码经过一段时间的磨合,已经很 ...

  4. 第十二章 process.tar.gz中代码的运行

    第一部分:process 第二部分:env 第三部分:fifo 第四部分:pipe 第五部分:signal

  5. apply、call、callee、caller初步了解

    在javascript中这四货通常一起出现介绍,楼主记忆力实在是太差经常忘记用法,故记此文. apply和call apply和call是函数原型的一个方法,调用者的类型必须是函数.官方解释:应用某一 ...

  6. HoloLens开发手记 - Known issues 已知问题

    本文主要提及一份问题清单,这些问题都可能对我们开发HoloLens应用造成困扰. Visual Studio 在使用VS 2015 Update 1连接HoloLens时,可能会有些小问题.但是这些小 ...

  7. 删除 windows 下 node_modules 过深的目录

    本文同步自我的个人博客:http://www.52cik.com/2015/11/13/node-modules-del.html 说到 node 的模块,确实既好用又蛋疼.相信无数人吐槽 node_ ...

  8. WINDOWS8.1安装ORACLE客户端及配置

    1.官方网站下载: instantclient-basic-win32-11.2.0.1.0.zip instantclient-sqlplus-win32-11.2.0.1.0.zip instan ...

  9. Android应用程序模拟手机按键

    记得以前在做一个C++项目时,需要在某一步操作之后人为用代码模拟敲键盘上的回车键(Enter)效果. 出于好奇,这几天研究了一下Android中手机(或平板)上各种按键的键值.模拟方法及最终效果. 1 ...

  10. [USACO2005][POJ2226]Muddy Fields(二分图最小点覆盖)

    题目:http://poj.org/problem?id=2226 题意:给你一个字符矩阵,每个位置只能有"*"或者“.",连续的横着或者竖的“*"可以用一块木 ...