Ward BRDF实现心得
最近做了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方向上的粗糙程度)。当αx=αy的时候,该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之间取值,取值越大,得到的高光区域越大。如果说对于一个点光源,当αx=αy的时候,高光呈现圆形的话,αx≠αy时高光就是椭圆形的,而且αx与αy的比例越大,椭圆越扁。当αx与αy其中一项取值为1的时候,高光在这个方向上的范围为无限大(理论上如此,但实际上会受限于表面大小等因素)。下面一组图中我实验了比较有代表性的三种情况:

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

Ward BRDF实现心得的更多相关文章
- Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF
在实时渲染中Physically-Based Rendering(PBR)中文为基于物理的渲染它能为渲染的物体带来更真实的效果,而且能量守恒 稍微解释一下字母的意思,为对后文的理解有帮助,从右到左L为 ...
- 我的MYSQL学习心得(一) 简单语法
我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
- NoSql数据库使用半年后在设计上面的一些心得
NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...
- 我的MYSQL学习心得(二) 数据类型宽度
我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
- 我的MYSQL学习心得(三) 查看字段长度
我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
- 我的MYSQL学习心得(四) 数据类型
我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(五) 运 ...
- 我的MYSQL学习心得(五) 运算符
我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...
- 我的MYSQL学习心得(六) 函数
我的MYSQL学习心得(六) 函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...
- 我的MYSQL学习心得(七) 查询
我的MYSQL学习心得(七) 查询 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...
随机推荐
- WP老杨解迷:评论数和下载量、榜单的关系
书接上回,继续研讨评论系统的深层经验,这次从另外一个角度看清榜单关系,提升装逼水准2个加号,如果你能看懂本文,并活学活用,足可在Win10之前醉卧隆中,通晓Windows Phone市场风云变幻,哪些 ...
- C#中成员初始化顺序
http://blog.csdn.net/huangcailian/article/details/25958967 一.成员初始化整体顺序 1.成员赋值初始化先于构造函数: 2.成员赋值初始先从子类 ...
- python 控制 cmd 命令行颜色
基于win7 + python3.4 import ctypes import sys '''Windows CMD命令行颜色''' # 句柄号 STD_INPUT_HANDLE = -10 STD_ ...
- python下RSA 加密/解密,签名/验证
基于win7 + python3.4 原文是py2环境,而我的环境是py3,所以对原代码做了修改:decode(), encode() import rsa # 生成密钥 (pubkey, privk ...
- Android ViewPager使用详解
这是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api.而viewpager就是其中之一利用它,我们可以做很多事情,从最简单的导航,到页面菜单等等.那如 ...
- 记一次w3wp占用CPU过高的解决过程(Dictionary和线程安全)
项目上线以来一直存在一个比较揪心的问题,和一个没有信心处理的BUG,那就是在应用程序启动时有可能会导致cpu跑满99%或持续在一个值如50%左右,这样一来对服务器的压力是非常大的,经常出现服务器无法远 ...
- 让C#开发更简单,抽象增删改
相信经常做一些MS,CRM 项目的童鞋非常有体会,大部分时间都是在复制和粘贴,大部分项目框架都是建一个三层,首先是DAL建一些增删改查,然后呢是BLL业务层再建一些增删改查,然后UI层再调用增删改查, ...
- 去除a标签单击后的虚线框
设置a标签属性outline即可 如: a { outline: none; } a:focus { outline: none; } 在firefox测试通过,webkit内核浏览器无此问题
- (旧)子数涵数·Flash——初识ActionScript
一.什么是AS(ActionScript) ActionScript,简称AS,中译为"动作脚本语言". 用于在Flash上实现一些光用Flash无法实现的功能. 在Flash界面 ...
- JS中decodeURI()与decodeURIComponent()区别
decodeURI()定义和用法:decodeURI() 函数可对 encodeURI() 函数编码过的URI 进行解码. 语法:decodeURI(URIstring) 参数 描述:URIstrin ...