Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF
在实时渲染中Physically-Based Rendering(PBR)中文为基于物理的渲染
它能为渲染的物体带来更真实的效果,而且能量守恒
稍微解释一下字母的意思,为对后文的理解有帮助,
从右到左
L为光线方向,H为半角向量,L是和V的中间,N为法线方向,V为我们眼睛的观察方向(相机看的方向),R为反射方向
Torrance-Sparrow光照模型的镜面反射公式
D为法线分布函数(NDF)
F为反射函数(Fresnel 函数)
G为阴影遮罩函数(几何函数),未被shadow或mask的比例
此处的E就是上面的V
Cook-Torrance光照模型的镜面反射公式
接下来我们只用Cook-Torrance光照来做实验
通常来说BRDF是关于表面多种属性的反射结果之间的线性组合(在实时渲染中一般只考虑diffuse和specular两种即可)
这是unity的specular
看起来是不是特别像塑料?还是粗糙的塑料
接下来我们就来讨论D函数的不同带来的specular的不同
BlinnPhong的分布函数
Call of Duty : black Ops 2/使命召唤:黑色行动2就使用了它
在http://segmentfault.com/blog/wwt_warp/1190000000436286中说明
Microfacet
微平面模型是广泛应用的对rough surface建模的工具,
blinn,ward,beckmann都属于microfacet的推导结果。基本思想也很简单,就是用很小的微平面的组合去模拟粗糙的物体表面。而这
些微小的平面元则可以当做完美的反射或者折射表面。每个microfacet把一个入射方向的光反射到单独的一个出射方向,这取决于microfacet
的法向m。当计算BRDF的时候,光源方向l和视线方向v都得给定。这意味着在表面上的所有microfacet中,只有刚好把l反射到v的那部分对
BRDF有贡献。在下图中,我们可以看到这些有效microfacet的表面法向m正好在l和v的中间,也就是h。
D
为法线分布函数(NDF),在大部分表面上,microfacet的方向不是均匀分布的。Microfacet的法线越接近宏表面的法线,就越光滑。这个
分布由microfacet的法线分布函数D(m)来定义。函数D()决定了specular高光的大小、亮度和形状。
法线分布函数一般有类似于“粗糙度”这样的参数。
F为反射函数(Fresnel 函数),计算光学上的反射比率。
分母4(n•l)(n•v)是个校正因子,用来校正从microfacet的局部空间转到整体表面的数量差异。
V为能见度函数,阴影遮罩分类为透视缩减
关于G ,
http://www.klayge.org/wiki/index.php/%E5%9F%BA%E4%BA%8E%E7%89%A9%E7%90%86%E7%9A%84BRDF
给出了解释
G为阴影遮罩函数(几何函数),未被shadow或mask的比例
在
上半部分,平的宏表面为绿色,粗糙的微观表面为蓝色。m = h的
microfacet标记为红色。宏表面投到视线方向就是左上角的绿线。同时,投出来的单个红色的microfacet显示成独立的红线。左下图表示在没
有遮挡项的情况下,红色的microfacet加起来的面积,结果就是有效面积大于总面积,所以BRDF的反射能量错误地大于了接收能量。右下图里红色区
域考虑了遮挡,重叠的区域不再计算多次,所以有效面积小于总面积。
α为Specular的强度,Specular的强度是根据光泽度gloss确定的
Schlick提出的fresnel方法:
rf0是反射颜色,也是roughness粗糙程度
遮挡项使用了Schlick-Smith提出的方法
处于能量守恒考虑,漫反射多了镜面反射就要少,反之亦然
所以:
效果如下:
看起来很像抛光的大理石效果吧
主要代码如下:
插入代码:
- #define PIE 3.1415926535
- float4 frag(v2f i) :COLOR
- {
- float3 viewDir = normalize(i.viewDir);
- float3 lightDir = normalize(i.lightDir);
- float3 H = normalize(lightDir + viewDir);
- float3 N = normalize(i.normal);
- float d = (_SP + 2) / 8 * pow(dot(N, H), _SP) / 4 * PIE;
- float f = _SC + (1 - _SC)*pow((1 - dot(H, lightDir)), 5);
- float k = 2 / sqrt(PIE * (_SP + 2));
- float v = 1 / ((dot(N, lightDir)*(1 - k) + k)*(dot(N, viewDir)*(1 - k) + k));
- float all = d*f*v;
- float3 c = tex2D(_MainTex, i.uv_MainTex);
- float3 diff = dot(lightDir, N);
- diff = (1 - all)*diff;
- return float4(c *(diff+all), 1) * _LightColor0;
- }
_SC 为specular color,_SP 为specular power
Phong的分布函数
为D值(NDF)
cosθ值为N与H的点积,以下皆是如此,H为半角向量,也就是light direct光线方向和view direct视角的一半。α即为本函数的specular power
这是不同specular power的实现曲线,越高代表约粗糙,越低代表约光滑
效果也很不错
核心代码如下:
- float d = (_SP + 2) / 8 * pow(dot(N, H), _SP)/(2*PIE);
Beckmann的分布函数
secθ为1/cosθ;
曲线如下
本曲线为α值为0.75时,局部出现了0的0次方,这与phong不同,使得粗糙表面的统一分部可行
如果超过了0.75就会出现上面这种不该出现的情况,局部出现了近似0的最小值
这是Beckmann和phong的对比(粉色为Beckmann,蓝色为phong)
左面的图是关于粗糙表面的曲线,两者都差不多,对于右侧光滑的表面,两者相差很多。
效果如下:
主要代码如下:
- float cosT = dot(N, H);
- float secT = 1 / cosT;
- float d = pow(E, -((1 - pow(cosT, 2))*pow(secT, 4) / _AB))*pow(secT, 4) / (PIE*pow(_AB, 2));
Trowbridge-Reitz(GGX)的分布函数
为实现方程
曲线如下:
左侧是参数值较低的情况,右侧是参数值较高的情况
左侧有点像Beckmann(越高越粗糙),右侧也是像Beckmann出现了最粗糙的地方
这是与phong的比较
他们两个差不多,但是Trowbridge-Reitz高的地方比较尖,矮的地方拖尾较长
与phong的最终比较。
效果如下:
个人感觉这是效果第二好的方法
核心代码如下:
- float cosT = dot(N, H);
- float d = pow(_SP, 2) / (PIE *pow((1 + (-1 + pow(_SP, 2))*pow(cosT, 2)), 2));
Shifted Gamma Distribution的分布函数
没错,就是这么长,
alpha和gamma都是外部可控变量
效果如下:
个人认为效果最好的方法,可控变量多,出来的效果多,但是感觉计算起来很消耗啊
代码如下:
- #define E 2.71828
- float4 frag(v2f i) :COLOR
- {
- float3 viewDir = normalize(i.viewDir);
- float3 lightDir = normalize(i.lightDir);
- float3 H = normalize(lightDir + viewDir);
- float3 N = normalize(i.normal);
- float cosT = dot(H, N);
- float secT = 1 / cosT;
- float d = (pow(E, -(_SP*_SP + (1 - cosT * cosT)*secT *secT) / _SP))* pow(_SP, -1 + _TP)*pow(secT, 4)
- *pow(_SP*_SP + (1 - cosT *cosT)*secT *secT, -_TP)
- / (PIE * _GM);
- float f = _SC + (1 - _SC)*pow((1 - dot(H, lightDir)), 5);
- float k = 2 / sqrt(PIE * (_SP + 2));
- float v = 1 / ((dot(N, lightDir)*(1 - k) + k)*(dot(N, viewDir)*(1 - k) + k));
- float all = d*f*v;
- float3 c = tex2D(_MainTex, i.uv_MainTex);
- float3 diff = dot(lightDir, N);
- diff = (1 - all)*diff;
- return float4(c *(diff + all), 1) * _LightColor0;
- }
最后放上一个全家福
参考:
1. Mathematica Notebook for the SIGGRAPH 2013 talk “ Background: Physics and Math of Shading”
2. PhysicallyBased Lighting in Call of Duty: Black Ops
----- by wolf96
Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF的更多相关文章
- Unity3d 基于物理渲染Physically-Based Rendering之最终篇
前情提要: 讲求基本算法 Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF plus篇 Unity3d 基于物理渲染Physically-B ...
- unity3d 基于物理渲染的问题解决
最近1个月做了unity 次世代开发的一些程序方面的支持工作,当然也是基于物理渲染相关的,主要还是skyshop marmoset的使用吧,他算是unity4.x版本 PBR的优秀方案之一了但在使用以 ...
- PBR:基于物理的渲染(Physically Based Rendering)+理论相关
一: 关于能量守恒 出射光线的能量永远不能超过入射光线的能量(发光面除外).如图示我们可以看到,随着粗糙度的上升镜面反射区域的会增加,但是镜面反射的亮度却会下降.如果不管反射轮廓的大小而让每个像素的镜 ...
- Unity3d 基于物理渲染Physically-Based Rendering之实现
根据前文的例子http://blog.csdn.net/wolf96/article/details/44172243(不弄超链接了审核太慢)弄一下真正的基于物理的渲染逃了节课= =,弄了一下.公式和 ...
- 基于物理渲染的渲染器Tiberius计划
既然决定实现一个光栅化软件渲染器,我又萌生了一个念头:实现一个基于物理渲染的渲染器.
- Physically Based Rendering
Microfacet Models for Refraction through Rough Surfaces 这篇论文...名字被我忘记了 找了好久...之前存电脑里的 ggx beckmann 找 ...
- Thinking in Unity3D:基于物理着色(PBS)的材质系统
关于<Thinking in Unity3D> 笔者在研究和使用Unity3D的过程中,获得了一些Unity3D方面的信息,同时也感叹Unity3D设计之精妙.不得不说,笔者最近几年的引擎 ...
- Physically Based Render in Game 序
基于物理渲的渲染理论,从SIGGRAPH06被Naty Hoffman等人提出后,近年来也越来越多的被各大游戏公司所采用,几乎已经是次世代游戏的标准特性,也是每个3D游戏工作者所必备的知识,尽管每年S ...
- Physically Based Shader Development for Unity 2017 Develop Custom Lighting Systems (Claudia Doppioslash 著)
http://www.doppioslash.com/ https://github.com/Apress/physically-based-shader-dev-for-unity-2017 Par ...
随机推荐
- FWT 学习总结
我理解的FWT是在二元运算意义下的卷积 目前比较熟练掌握的集合对称差卷积 对于子集卷积和集合并卷积掌握不是很熟练(挖坑ing) 那么就先来谈一谈集合对称差卷积吧 所谓集合对称差卷积 就是h(i)=si ...
- SULogger:iOS日志可视化工具
前言 debug对于咋们程序员来说家常便饭,但有时候我们会遇到一种情况:开发某个功能时,需要在某个特定场景下进行调试,而这个场景并没有MacBook来进行连接debug,偏偏我们需要获得调试时的一些信 ...
- Axel linux下多线程下载工具
Axel 是 Linux 下一个不错的HTTP/FTP高速下载工具.支持多线程下载.断点续传,且可以从多个地址或者从一个地址的多个连接来下载同一个文件.适合网速不给力时多线程下载提高下载速度.比如在国 ...
- MSRA面试总结
http://blog.renren.com/share/405984844/16014442499 注:以下内容纯凭记忆,由于已经过去一个多月,不保证准确性.由于面试前没有签保密协议,本文透露了比较 ...
- [UVA315]Network(tarjan, 求割点)
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- tomcat web.xml配置
关于Tomcat 中 web.xml 文件的配置问题: 1.下面的配置是合法的 <servlet> <servlet-name>test</serv ...
- poj 1061 青蛙的约会(扩展gcd)
题目链接 题意:两只青蛙从数轴正方向跑,给出各自所在位置, 和数轴长度,和各自一次跳跃的步数,问最少多少步能相遇. 分析:(x+m*t) - (y+n*t) = p * L;(t是跳的次数,L是a青蛙 ...
- 函数flst_remove
移除 node, node->prev直接指向node->next /*********************************************************** ...
- QWidget、QDialog、QMainWindow的异同点
简述 在分享所有基础知识之前,很有必要在这里介绍下常用的窗口 - QWidget.QDialog.QMainWindow. QWidget继承于QObject和QPaintDevice,QDialog ...
- UVa 10288 (期望) Coupons
题意: 每张彩票上印有一张图案,要集齐n个不同的图案才能获奖.输入n,求要获奖购买彩票张数的期望(假设获得每个图案的概率相同). 分析: 假设现在已经有k种图案,令s = k/n,得到一个新图案需要t ...