之前的错误和欠缺

1. 过于简单的划分diffuse和specular,非常光滑的非金属材料也是很能反光的
2. 费奈尔效应的处理,F0的选取也比较随意
3. 没有GI,更不支持AO

正确划分diffuse和spcular

之前我的PBR实现非金属无论怎样光滑都是没有反光的,这显然很不对。完全忽略了非金属的反射

金属性越高,反射率越高,分给Specular计算的Albedo越多。1.0的金属会反射所有的光,也就没有diffuse。但是非金属不太一样,0.0的非金属也仍旧又一定的反射能力,这个就是电介质反射率需要参与计算的地方。

在UnityStandardUtils.cginc中可以找到下面的分离方法,实际上是将Matellic的数值remap到[DielectricSpec,1]的范围。

inline half OneMinusReflectivityFromMetallic(half metallic)
{
  // We'll need oneMinusReflectivity, so
  // 1-reflectivity = 1-lerp(dielectricSpec, 1, metallic) = lerp(1-dielectricSpec, 0, metallic)
  // store (1-dielectricSpec) in unity_ColorSpaceDielectricSpec.a, then
  // 1-reflectivity = lerp(alpha, 0, metallic) = alpha + metallic*(0 - alpha) =
  // = alpha - metallic * alpha
  half oneMinusDielectricSpec = unity_ColorSpaceDielectricSpec.a;
  return oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
} inline half3 DiffuseAndSpecularFromMetallic (half3 albedo, half metallic, out half3 specColor, out half oneMinusReflectivity)
{
  specColor = lerp (unity_ColorSpaceDielectricSpec.rgb, albedo, metallic);
  oneMinusReflectivity = OneMinusReflectivityFromMetallic(metallic);
  return albedo * oneMinusReflectivity;
}

unity_ColorSpaceDielectricSpec里面存的是Unity选用的电介质反射率,alpha通道是1-dielectricSpec

Matellic:0 Gloss:0.5 的效果
)
从左至右:PBR1.0,Standard, PBR2.0, Standard

F0的选取

F0是入射角为0时的反射光,也就是分配给Specular计算的Albedo。之前的PBR实现实现会会整体偏亮就是因为Matellic肯定比正常的F0要大的多。

Matellic:0 Gloss:0.5 的效果


从左至右:PBR1.0,Standard, PBR2.0, Standard

过亮的问题看起来解决了,但是整体感觉更粗糙一些。

为什么我的shader颜色偏黑

这是Gloss:0,Matellic:0~1的对比图。关闭了场景的环境光。第一行是CustomPBR,第二行是Standard

最早是发现经过之前两个调整之后,整体颜色偏暗。经过几个对比测试之后确定是Specular部分偏低。也就是上图Matellic0.0和Matellic1.0对比在Diffuse为主的非金属上颜色基本正常,只有Specular的金属上色彩偏差最大。

这个问题让我非常迷惑,在一些对比测试中将公式改为和Unity一致也没有解决这个问题。进一步看到在Unity中对GammaSpace的Specular进行了一次开方修正。
同样的在CustomPBR中进行处理之后效果就正常了。

对Gamma这块我还不是很明白,搜了一下Gamma这个修正坑很深。以后再研究,要是哪位有相关的资料分享那就太好了。

没有GI怎么行

没有GI的情况下物体在场景里面实在是太突兀,先将Unity 的GI整合进来,学习一下Unity的GI。

UnityGI的处理

环境光照也是光照,也分为diffuse和specular。无论计算过程多么复杂,最后都是要得到环境光照的这两个分量,然后和基本光照叠加。

Unity的叠加方式。这里是简化说明,本体在UnityStandardBRDF.cginc中

//indirectDiffuse 就是GI的diffuse
diffuse = (indirectDiffuse + directDiffuse) * diffuesColor; //directF:计算了Fresnel的specularColor
//indirectSpecular:GI的specular部分,包括各种Probe
//indirectF:计算了GI的Fresnel的SpecularColor
specular = lightColor * directSpecularTerm * directF + indirectSpecular * indirectSpecularTerm * indirectF;

整合UnityGI

会用到的struct在UnityLightingCommon.cginc里。
Unity的GI运算在UnityGlobalIllumination.cginc里。
我们要用的方法是这个

inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn)

我们所需要的间接diffuse 和间接specular就在UnityGI.indirect

需要作的也就是给这个方法凑参数,构造一个UnityGIInput。这个结构体的大部分都很直观。

i_ambientOrLightmapUV
有lightmap的时候没有ambientColor,没有lightmap的时候只有ambientColor。这两个肯定是互斥的。

box和probe
在Unity中会有两个SpecCube生效,unity_SpecCube0,场景的反射源。unity_SpecCube1,当前的reflectionProbe,一起提供了IBL所需要的数据(其实应该是IBL的结果吧……待研究)

整合效果

Matellic:1.0 Gloss:0.7 Ambient:Red 在红色方块附近有一个ReflectionProbe

弓箭效果

下一步

1. 研究GI,看看能不能自己实现一个。现在GI方面有很多不明
2. Gamma修正,这个对最终画面影响很大,不能不看

PBR实现2.0的更多相关文章

  1. huawei USG防火墙子接口技术的应用案例

    网络拓扑: 在中小企业的办公网络的设计中,通常为了安全考虑,需要将不同部门之间的互访的流量经过防火墙中转,同时结合vpn stance将业务进行隔离,在本例中,使用两台USG防火墙做HA作为整个办公网 ...

  2. 【腾讯Bugly干货分享】人人都可以做深度学习应用:入门篇

    导语 2016年,继虚拟现实(VR)之后,人工智能(AI)的概念全面进入大众的视野.谷歌,微软,IBM等科技巨头纷纷重点布局,AI 貌似将成为互联网的下一个风口. 很多开发同学,对人工智能非常感兴趣, ...

  3. Python虚拟环境工具-Virtualenv 介绍及部署记录

    在开发Python应用程序时,系统默认的Python版本可能会不兼容这个应用程序, 如果同时开发多个应用程序, 可能会用到好几个版本的python环境, 这种情况下,每个应用可能需要各自拥有一套&qu ...

  4. 从TensorFlow0.12升级到TensorFlow1.13

    sudo pip install --upgrade tensorflow-gpu $ sudo pip install --upgrade tensorflow-gpu[sudo] password ...

  5. 记一次成功部署kolla-ansible ocata版本过程

    1.安装的docker版本 [root@controller ~]# docker --versionDocker version 17.09.1-ce, build 19e2cf6 2.安装的ans ...

  6. 记一次安装kolla遇到DockerException: Error while fetching server API version: Timeout value connect was Timeout的问题

    1)环境信息: docker版本:17.09,当docker的版本是12.06时,也会报这个错误 [root@localhost ~]# docker --version Docker version ...

  7. OpenStack基础知识-项目打包的步骤

    学习过包管理相关的知识后,我们就要以OpenStack的方法来创建一个我们自己的项目.这个项目的名称是webdemo,就是一个简单的web服务器.这个项目会贯穿这个系列文章.在本文中,我们首先要创建w ...

  8. 当前,我们的DJANGO项目的requirements.txt文件

    晒一晒,看用得多不多..:) amqp==1.4.7 anyjson==0.3.3 billiard==3.3.0.21 celery==3.1.19 celery-with-redis==3.0 c ...

  9. Python(七) —— mock接口开发

    mock接口开发 接口开发有很多框架,诸如 Django,flask,相比较而言,flask 是轻量级web开发框架,用来开发 mock 接口的不二之选.那你可能会问,什么叫 mock 接口呢?moc ...

随机推荐

  1. 几个常见的布局的多种实现方式及margin负值总结

    第一部分:几个常见的布局实现方式 一.左右两边固定, center中间自适应未知 html代码中 center 部分首先要放在box的最前部分.然后是left,right 圣杯布局: <div ...

  2. C# 的各种排序

    http://www.cnblogs.com/jiajiayuan/category/302446.html

  3. New XAMPP security concept:错误解决方法

    New XAMPP security concept:错误解决方法 (2014-03-06 16:07:46) 转载▼   分类: php 在Linux上配置xampp后远程访问域名报错: New X ...

  4. noConflict

    var _avalon = window.avalon avalon.noConflict = function(deep) { if (deep && window.avalon = ...

  5. PAT (Advanced Level) Practise:1001. A+B Format

    [题目链接] Calculate a + b and output the sum in standard format -- that is, the digits must be separate ...

  6. 集成ShareSDK,分享成功后QQ和空间回调不执行的可能原因

    AndroidMainifest.xml中的如箭头所示的id与assets下ShareSDK.xml中配置的QQ的AppId一定要相同.

  7. Spring任务调度器之Task的使用

    Spring Task提供两种方式进行配置,正如大家所想吧,还是一种是annotation(标注),而另外一种就是XML配置了.但其实这里我觉得比较尴尬,因为任务调度这样的需求,通常改动都是比较多的, ...

  8. TYVJ 1117 BFS

    无限WA..参考了一下题解和同学写的....... 可以在bfs的基础上改一下.. 读入的时候平地权值是2 草地是0 bfs的时候如果搜到的是平地,那么直接加入,如果搜到的是草地,那么记录是草地. 从 ...

  9. Linux下的网卡驱动程序的编写过程(转)

    工作需要写了我们公司一块网卡的linux驱动程序.经历一个从无到有的过程,深感技术交流的重要.Linux作为挑战微软垄断的强有力武器,日益受到大家的喜爱.真希望她能在中国迅速成长.把程序文档贴出来,希 ...

  10. mysql order排序

    使用order by  可以对结果进行排序, 默认情况下,order by 以升序进行排序,因此ASC 子句是可选的. DESC 是降序排列. 升序 select * from emp where d ...