本系列文章由@浅墨_毛星云 出品,转载请注明出处。
文章链接: http://blog.csdn.net/poem_qianmo/article/details/55803629
渲染本文配图使用的Unity3D版本: 5.5.0
这篇文章将基于MatCap的思想,在Unity中实现了具有高度真实感的MatCap车漆Shader。采用MatCap思想的Shader,用低廉的计算成本,就可以达到类似PBS非常真实的渲染效果,可谓是在移动平台实现次时代渲染效果的一种优秀解决方案。
本文以车漆Shader为例,但MatCap思想能实现的,并不局限于车漆Shader。本来准备给本文取名《一种基于MatCap的低计算成本、高真实感移动平台Shader解决方案》的,但这个名字太大了,遂改之。
先看一下最终的效果图。
Material Capture(材质捕获),通常被简称为MatCap,在Zbrush、Sculptris、Mudbox等3D软件中有比较多的使用。
MatCap Shader的基本思路是,使用某特定材质球的贴图,作为当前材质的视图空间环境贴图(view-space environment map),来实现具有均匀表面着色的反射材质物体的显示。考虑到物体的所有法线的投影的范围在x(-1,1),y(-1,1),构成了一个圆形,所以MatCap 贴图中存储光照信息的区域是一个圆形。
基于MatCap思想的Shader,可以无需提供任何光照,只需提供一张或多张合适的MatCap贴图作为光照结果的“指导”即可。
上图来自(http://digitalrune.github.io/DigitalRune-Documentation/html/9a8c8b37-b996-477a-aeab-5d92714be3ca.htm)
不像一般的Shader,需要提供光照,需要在Shader代码中进行漫长的演算,基于MatCap思想的Shader相当于MatCap贴图就把光照结果应该是怎样的标准答案告知Shader,我们只用在试卷下写出答案,进行一些加工即可。
需要注意,MatCap Shader有一定的局限性。因为从某种意义上来说,基于MatCap的Shader,就是某种固定光照条件下,从某个特定方向,特定角度的光照表现结果。
正是因为是选择的固定的MatCap贴图,得到相对固定的整体光照表现,若单单仅使用MatCap,就仅适用于摄像机不调整角度的情形,并不适合摄像机会频繁旋转,调节角度的情形。但我们可以在某些Shader中,用MatCap配合与光照交互的其他属性,如将MatCap结合一个作为光照反射的颜色指导的Reflection Cube Map,就有了与光照之间的交互表现。这样,就可以适当弥补MatCap太过单一整体光照表现的短板。
关于MatCap,《UnityShaders and Effects Cookbook》一书的Chapter 5: LightingModels中,The Lit Sphere lighting model一节也有一些涉及。
需要使用基于MatCap Shader,合适的MatCap 贴图必不可少。显而易见,MatCap贴图的获取,一般来说有两种方式。
1. 自己制作。对着3D软件中的材质球截图。
2. 从网络上获取。在网络上使用“matcap“等关键字搜索后获得。
这边提供几个可以获取MatCap贴图的网址:
[1] https://www.pinterest.com/evayali/matcap/
[3]http://pixologic.com/zbrush/downloadcenter/library/#prettyPhoto
关于基于MatCap思想实现Physicallybased Shading,这篇文章(http://blog.csdn.net/ndsc_dw/article/details/50700201)提供了一定的思路,简单来说,就是用几张MatCap贴图来提供PBS需要的光滑度和金属度,来模拟出PBS的效果。继续展开下去就脱离本文的主线了,有兴趣的朋友可以深入进行了解。
此车漆Shader,除了用到MatCap,主要还需要提供一个Reflection Cube Map作为反射的颜色指导,就可以适当弥补MatCap太过单一的整体光照表现的短板,实现非常真实且高效的车漆Shader效果。
此Shader赋给Material后,Material在Inspector中的属性表现如下:
其中的MatCap贴图为:
Shader源码如下:
Shader注释已经比较详细,下面对代码中也许会不太理解,需要注意的地方进行说明。
要使用MatCap贴图,主要是将法线从模型空间转换到视图空间,并切换到适合提取纹理UV的区域[0,1]。(需要将法线从模型空间转换到视图空间,关于一些推导可以参考http://www.lighthouse3d.com/tutorials/glsl-12-tutorial/the-normal-matrix或者http://www.cnblogs.com/flytrace/p/3379816.html)
Unity内置的矩阵UNITY_MATRIX_IT_MV,是UNITY_MATRIX_MV的逆转置矩阵,其作用正是将法线从模型空间转换到观察空间。于是顶点着色器vert中的这两句代码就很容易理解了:
而得到的视图空间的法线,区域是[-1,1],要转换到提取纹理UV的区域[0,1],就需要乘以0.5并加上0.5,那么顶点着色器vert中接下来的的这句代码也就可以理解了:
稍后,在片元着色器frag中,用在顶点着色器vert中准备好的法线转换成的UV值,提取出MatCap的光照细节即可:
此Car Paint Shader其他实现,主要就是一些基本的Shader知识点的配合,如顶点坐标转换,反射,漫反射,细节纹理的计算,都是比较基础的内容,这里就不再赘述,直接看Shader源码即可。
最后看几张截图,然后就是相关Shader与MatCap资源的下载:
从Github下载:
[1] http://wiki.unity3d.com/index.php/MatCap
[2] https://www.assetstore.unity3d.com/en/#!/content/8221
[3] http://blog.csdn.net/cubesky/article/details/38682975
[4] https://www.assetstore.unity3d.com/en/#!/content/76361
[5] http://www.cnblogs.com/flytrace/p/3379816.html
[6] http://www.cnblogs.com/flytrace/p/3395911.html
[8] https://forum.unity3d.com/threads/_object2world-or-unity_matrix_it_mv.112446/
[9]http://www.lighthouse3d.com/tutorials/glsl-12-tutorial/the-normal-matrix
With Best Wishes.