之前的错误和欠缺

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. keyFile 巩固练习

    系统 : Windows xp 程序 : noodles-crackme2 程序下载地址 :http://pan.baidu.com/s/1mhJ4Ems 要求 : 编写KeyFile 使用工具 : ...

  2. Java(二)

    课后,我查阅相关学习资料和Java API制作了以下界面,界面包含了单选按钮(JRadioButton).复选框(JCheckBox).组合框(JComboBox).单行文本输入框(JTextFiel ...

  3. runtime 初入

    一.runtime简介 RunTime简称运行时.OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制. 对于C语言,函数的调用在编译的时候会决定调用哪个函数. 对于OC的函数,属于 ...

  4. 关于discuz“终于解决“头像保存过程中发生网络错误,请重试"”的解决方法

    1 php.ini里面allow_url_fopen = On2 将php.ini中的;upload_tmp_dir = 该行的注释符,即前面的分号“:”去掉,使该行在php.ini文档中起作用.up ...

  5. 关于scrolltop 兼容 IE6/7/8, Safari,FF的方法

    1.各浏览器下 scrollTop的差异IE6/7/8:对于没有doctype声明的页面里可以使用  document.body.scrollTop 来获取 scrollTop高度 :对于有docty ...

  6. SQL --Chater03 聚合与排序

    数据说明: +-----------+------------+---------------+--------------+--------------+------------+ | shohin ...

  7. linux标准io的copy

    ---恢复内容开始--- 1.linux标准io的copy #include<stdio.h> int main(int argc,char **argv) { if(argc<3) ...

  8. Eclipse 关于“The type * is not accessible due to restriction on required library”问题的解决办法

    The type * is not accessible due to restriction on required library”的错误, 意思是所需要的类库由于受限制无法访问. 解决办法: 1 ...

  9. 计算机启动boot

    原创博文:转载请标明出处:http://www.cnblogs.com/zxouxuewei 零.boot的含义 先问一个问题,"启动"用英语怎么说? 回答是boot.可是,boo ...

  10. FPGA书籍

    Xilinx FPGA开发实用教程(第2版) 徐文波,田耘 著