https://zhuanlan.zhihu.com/p/21961722

很多时候可以听到游戏玩家说,某某游戏看起来什么都是塑料做的。最近还听一个设计师说,你用Blinn-Phong吧,那东西渲染出来就是浓浓的塑料感的。

金属和塑料,区别在哪里,真的是因为BRDF模型吗?

Diffuse/Specular

就从Blinn-Phong模型入手。最简单的基于物理的Blinn-Phong是这样的:

其中分别是diffuse和specular的颜色,是表述光滑程度的。跟物体材质相关的,也就是这三项了。话句话说,决定一个物体看起来像什么,在Blinn-Phong模型里,就是通过调整这三项完成的。

那么,是光滑度造成的吗?不是。塑料也有粗糙和光滑,金属也有粗糙和光滑。并不会因为是金属就不那么粗糙。所以,现在的问题就是,什么决定了材质的diffuse和specular颜色。

回到基于物理的BRDF这个出发点,看看从物理的角度,diffuse和specular来自哪里。

上图来自于Real-time Rendering第三版。箭头根据颜色可以分成几种。简化起见,就看最终出射的情况。深蓝色和浅蓝色表示diffuse(分别来自于single scattering和multiple scattering,但这不重要),金黄色表示specular。原理上说,diffuse是光线折射入物体后,在内部经过散射,重新穿出表面的光。而specular是光线在物体表面直接反射的结果。并没有经过转换,还是原来的光子。

(从这张图还可以看出,因为物体的密度和材料不同,diffuse可能分布到一个很广的范围内,不是一个点,而是一个光斑。specular就是一个点。而且,这两者位置上不重合。不过这已经超出了实时渲染甚至离线渲染的范畴,这里不讨论)

然而,对于金属(导体)来说,折射入物体的光子会被完全吸收掉,就成了这个样子:

好了,这下明白了。对于金属来说,diffuse永远是0,材质的颜色来自于 specular。对于非金属来说,材质的颜色一部分来自于diffuse,一部分来自于specular。

颜色分布

既然如此,也就是说如果我们有能力控制diffuse和specular的颜色,就一定能在渲染上复现出金属(导体)和塑料(绝缘体)的区别,甚至介于其间的半导体。在此之前,先找一些现实中的材料,看看它们的diffuse和specular颜色分布究竟如何。

这里列举一下来自Physics and Math of Shading的几张表。

第一张是金属的specular颜色。前面说到金属的diffuse = 0,所以你看到的金属颜色,就是它的specular。从这张表可以看出,金属的specular非常强烈,而且各通道都几乎大于0.5。唯一的例外是金,蓝色通道较弱,而红色通道已经超出了sRGB的表达范围。(如此独特的反射曲线,也是金子为什么有着独特的文化和经济地位的原因之一吧)

再来看看绝缘体阵营

同样是specular颜色,非金属则显得弱了很多。塑料、玻璃、水这些常见的绝缘体,specular都低于0.04。而水晶、钻石这些绝缘体, 你们知道为什么贵了吧。另一个特点是,绝缘体的specular都是单色的。各个通道的光都会被等同地反射,而不像金属那样有着不同的吸收偏好。

而半导体呢?如你所想,介于两者之间。

有了这些信息,我们就可以进一步把它用于渲染了。

GBuffer

这几年的渲染引擎,几乎都是用的deferred rendering框架,其中一个兵家必争之地就是GBuffer。每年都有不同的文章在讲如何把更多的信息挤到GBuffer中,正因为GBuffer空间极其有限,而想放入的信息有越来越多。所以,如何利用信息之间的关系,把数据编码到有限的空间里,对deferred rendering来说非常重要。

如果按照前面的结论,需要放diffuse和specular颜色,则需要6个通道,完全超出了GBuffer可以承受的范围。GBuffer里留给diffuse和specular颜色的通道只有4个。所以游戏引擎常见的做法是,保存个diffuse颜色和specular的亮度。就当作specular是单色的来处理。这样显然对于金属不利,也是为什么会画面看着都像塑料的重要原因。

有了上一节的信息,直觉告诉我们一个想法,对于导体和绝缘体,应该分开用不同的保存方法。导体存specular颜色,因为它的diffuse是0。绝缘体存diffuse,因为specular非常弱,都用0.04这个常量表达就可以了。那么半导体呢?就需要一个“金属性”的系数,在两者之间插值。

用公式来表达,就是

diffuse = albedo * (1 - metalness)
specular = lerp(0.04, albedo, metalness)

其中,albedo就是3通道的反照率,metalness就是金属性系数。lerp是线性插值的意思。这样就用一个方法统一了导体、半导体、绝缘体的颜色分布。metalness = 0表示绝缘体,diffuse就是albedo,specualr = 0.04。metalness = 1表示导体,diffuse = 0,specular = albedo。这么一来,只要在GBuffer里面存albedo(3通道)和metalness(1通道)。

结果和总结

这么做的渲染结果如何呢?咱们来看看一组对比,用的是前面提到的基于物理的Blinn-Phong,用的同样的albedo。

粗糙的绝缘体

光滑的绝缘体

粗糙的导体

光滑的导体

从图上还是很容易分辨那些是绝缘体那些是导体。而且很明显可以看出,这件事情和光滑度无关,和BRDF模型也无关。

在来对比一下在引入albedo+metalness之前能达到的效果。

对比强烈吧,同样的参数,原先的做法看起来就是油腻的塑料。

最后,来一组金属性和粗糙度变化的阵列。

我们用albedo+metalness的方法,在没有增加存储空间,和几乎没有增加计算开销的情况下,实现了更高质量的金属渲染。从此,只要做一些微小的工作,调调材质,就能避免塑料感。

在KlayGE里面,GBuffer的格式也已经改成这里说的存储方式,材质系统也做了相应的修改,以更好地表达这样的材质分类。

在有些游戏引擎,比如Dying Light,用了一个有点区别的编码方式。那里面只有导体和绝缘体两种切分,没有metalness的系数可以做过渡。这样就可以把绝缘体的specular给编码进去。又因为绝缘体specular非常的小,只要占用很少的位数。空出来的位可以把translucent、皮肤、叶片等信息都编码进去。但对导体绝缘体的分析和本文相同。

金属,塑料,傻傻分不清楚相关推荐

  1. 潜龙号开启水下机器人_蛟龙、海龙、潜龙傻傻分不清?全面解密国内最先进水下机器人...

    原标题:蛟龙.海龙.潜龙傻傻分不清?全面解密国内最先进水下机器人 正在执行中国大洋49航次业务化调查任务的"向阳红10号"带上了一件探海利器--潜龙二号.它是我国自主研发的4500 ...

  2. 雷电3 or USB Type-C?看完这篇文章从此不再傻傻分不清楚

    如果你身边有喜欢计算机硬件的朋友,这样的争论你应该听过不止一次.他们说的好像都有道理,但又好像都有点问题.到底谁说的是对的呢?其实这就涉及到接口规格(即下文中提到的"接口")与数据 ...

  3. JS魔法堂:属性、特性,傻傻分不清楚

    一.前言 或许你和我一样都曾经被下面的代码所困扰 var el = document.getElementById('dummy'); el.hello = "test"; con ...

  4. ASP.NET MVC涉及到的5个同步与异步,你是否傻傻分不清楚?[下篇]

    关于ASP.NET MVC对请求的处理方式(同步或者异步)涉及到的五个组件,在<上篇>中我们谈了三个(MvcHandler.Controller和ActionInvoker),现在我们来谈 ...

  5. 科普 | Shell中傻傻分不清楚的TOP3

    近来小姐姐又犯憨憨错误,问组内小伙伴export命令不会持久化环境变量吗?反正我是问出口了..然后小伙伴就甩给了我一个<The Linux Command Line>PDF链接.感谢老大不 ...

  6. 国家电网和南方电网还傻傻分不清?

    参看:都2020年了,国家电网和南方电网还傻傻分不清? 一.名称不同 一个叫南方电网,一个叫国家电力电网,虽然都是电网,但是区别还是很大的 而且成立时间不一样:国家电力电网有限公司成立于2002年12 ...

  7. cdn厂商 同兴万点_同兴万点:TXNetworks和CDNetworks让我们傻傻分不清

    原标题:同兴万点:TXNetworks和CDNetworks让我们傻傻分不清 在2008年2月25日成立的同兴万点,公司全称为同兴万点(北京)网络技术有限公司(TXNetworks),一直专注于CDN ...

  8. 2021年了,`IEnumerator`、`IEnumerable`接口还傻傻分不清楚?

    IEnumerator.IEnumerable这两个接口单词相近.含义相关,傻傻分不清楚. 入行多年,一直没有系统性梳理这对李逵李鬼. 最近本人在怼着why神的<其实吧,LRU也就那么回事> ...

  9. 动态ram依靠什么存储信息_ROM、RAM、DRAM、SRAM和FLASH傻傻分不清

    ROM.RAM.DRAM.SRAM和FLASH各类储存器在电脑.手机.电子设备.嵌入式设备及相应的开发中普遍应用的,但是很多还是傻傻分不清楚.下面就简单介绍下这几个吧! ROM和RAM ROM:只读存 ...

  10. Executor 与 ExecutorService 和 Executors 傻傻分不清

    转载自  Executor 与 ExecutorService 和 Executors 傻傻分不清 java.util.concurrent.Executor, java.util.concurren ...

最新文章

  1. EDA电子设计技术与应用
  2. Apache源代码全景分析第二卷——HTTP请求处理
  3. C/C++基础知识点(二)
  4. Yii的Where条件
  5. 认识计算机ppt课件游戏,《认识计算机》PPT课件
  6. 【Mail】telnet收发邮件过程
  7. HTML5营销代理商设计机构网站模板
  8. python如何并发运行2个软件_如何利用并发性加速你的python程序(二):I/O 绑定程序加速...
  9. WAV文件格式终极解析
  10. java 多线程 临界区_【Java并发性和多线程】竞态条件与临界区
  11. 验证码的旋转与放缩代码
  12. mcafee迈克菲官网由于验证缺陷,导致暴力破解到企业授权号获取到所有企业用户的Grant number
  13. request请求 下载附件
  14. 阿里云ECS和WorldPress + Nginx实现固定连接策略
  15. 如何在CSDN博客中上传图片
  16. 云聚创新力量,助力多云互联:Tungsten Fabric在联通沃云峰会2019上分享开源SDN
  17. 520,用Python定制你的《本草纲目女孩》
  18. linux系统下 USB 摄像头1080分辨率采集帧率低问题的解决方法
  19. Android基础知识点学习总结
  20. 闲扯测试工程师之发展(觉得不错,拿来与大家分享)

热门文章

  1. 无法安装 计算机缺失,还原安装程序Windows缺失的文件 - Windows Client | Microsoft Docs...
  2. 加工中心宏程序生成器_宏程序G1铣锥度螺纹NPT
  3. 离散数学及其应用怎么样_有名气的冲击式移动破碎站效果怎么样?
  4. ol+天地图+geoserver_GeoServer的WMS服务加载到天地图
  5. 同一列两行数据怎么合并成一行_经常加班怎么办?两分钟学会这4招,让同事刮目相看!...
  6. android 魅族短信拦截,如何防护手机里的个人信息?魅族18系列教你如何防范隐私泄露...
  7. php 窗体移动,窗体处理 - My Labs! PHP - PHP博客
  8. python中type为什么有main_python中 __name__及__main()__的妙处
  9. arma matlab函数,MATLAB中ARMA模型预测差分问题
  10. linux内核关闭igmp,Linux kernel IGMP多个安全漏洞