本系列文章由@浅墨_毛星云出品
概要:本文主要介绍了Unity5中的标准着色器,并且也涉及到了基于物理的着色、延迟渲染等高级着色技术,而在文章后半部分,也对屏幕水幕特效的实现方法进行了讲解与分析。
依然是附上一组本文配套工程的运行截图之后,便开始我们的正文。如下图。
打开水幕特效的效果图:
原始的城镇场景:
需要说明,这里的水幕特效是动态的水流效果。本来准备传GIF上来展示动态的效果,但受图片尺寸2M的限制,无法出色地表现出动态效果(帧数有限,图片清晰度也会大打折扣)。建议感兴趣的朋友们下载这里提供的游戏场景的exe,自己在机器上体验水幕效果,比看博文中贴出的图片效果好太多。
【可运行的本文配套exe游戏场景请点击这里下载】
提示:在此游戏场景中按F键可以开关屏幕特效。
在文章末尾有更多的运行截图,并提供了源工程的下载。
好的,正文开始。
一、认识Unity5中的Standard Shader
Unity5中重点推出了一套基于物理的着色(Physically Based Shading,PBS)的多功能Shader,叫做标准着色器(Standard Shader)。这套Shader的设计初衷是化繁为简。想用这样的一个多功能Shader,来代替之前多种多样的Shader各司其职,对于不同的材质效果,需要不同的Shader的局面。
Unity 5中目前有两个标准着色器,一个名为Standard,我们称它为标准着色器的标准版,另一个名为Standard(Specular Setup),我们称它为标准着色器的高光版,它们共同组成了一个完整的PBS光照明模型,且非常易于使用。其实这两个Shader基本差不多,只是有细微的属性参数上的区别。标准版这边的_Metallic(金属性)、_MetallicGlossMap(金属光泽贴图),被高光版的_SpecColor(高光颜色)、_SpecGlossMap(高光颜色法线贴图)所代替。
标准着色器主要是针对硬质表面(也就是建筑材质)而设计的,可以处理大多数现实世界的材质,例如石头、陶瓷、铜器、银器或橡胶等。同时,它也可以非常出色地处理一些非硬质表面的材质,例如皮肤、头发或布料等。
如下的一个Unity官方放出的名为VikingVillage的场景中,所有的物体材质都是使用的标准着色器,标准着色器的广泛适用性可见一斑。
而在Unity5的官方放出的演示demo视频中,也是用一个标准着色器,Standard(Specular Setup),就完成了游戏场景中绝大多数物体的材质显示。
Unity5 PBS技术的演示Demo截图:
下面稍微对Standard shader中核心的概念――基于物理的着色做一个大概的了解。
1.1 基于物理的着色(Physically Based Shading)技术概览
基于物理的着色(Physically Based Shading,简称PBS)就是以某种方式模拟现实中材质和光照的相互作用的一种着色方法。这种方法在需要光照和材质更加直观和逼真地协同工作的场合下优势非常明显。基于物理的着色模拟了光线在现实中的行为,实现了在不同的光照条件下的逼真效果。为实现这种效果需要遵循各种物理原理,包括能量守恒(也就是物体反射出去的光量不可能超过所接收的光量),Fresnel反射(所有表面反射在掠射角(grazing angles)处更加强烈),以及物体表面是如何自我遮挡等原理。
其实,PBS技术在多年前于虚幻三游戏引擎中就已经被广泛使用,而Unity直到最近刚发布的第五代,才将此特性作为官方的特性实现出来。而在Unity5发布之前,Unity的Asset Store中,已经有不少的第三方插件,在Unity中实现了PBS技术。
关于PBS技术,知乎上有一个专栏,专门介绍PBS技术的一些相关原理,在这里推荐一下:
基于物理着色(一)
基于物理着色(二)- Microfacet材质和多层材质
基于物理着色(三)- Disney和UE4的实现
这边贴一张专栏中的配套渲染图,效果非常出色:
1.2 如何使用标准着色器
可以在Unity5中任意材质的Shader选项中的最前面看到两个Standard Shader字样的选项。其中第一个是普通版,第二个带Specularsetup是高光版。
标准着色器标准版材质界面:
标准着色器的高光版材质界面:
不难得知,标准着色器引入了新的材质编辑器,它使PBS的材质编辑工作比以前的非PBS材质更简单。新的编辑器不但简洁,还提供了材质的所有可能用到的选项。在新编辑器中,我们不需要选用不同的着色器来改变纹理通道;不会再出现 “texture unused, please choose another shader” 这样的提示;也不再需要通过切换着色器来改变混合模式。
所有的纹理通道都是备选的,无需强制使用,任何一个闲置通道的相关代码都会在编译时被优化掉,因此完全不用担心效率方面的问题。unity会根据我们输入到编辑器中的数据来生成正确的代码,并使整个过程保持高效。
另外,我们可以用ctrl+点击纹理的方式预览大图,并且还可以分别查看颜色和Alpha通道。
ctrl+点击纹理,得到的纹理放大的预览:
OK,关于Unity5中的StandardShader的概念,大概先就讲这么多。更多细节可以参考Unity官方文档:
以及这里Unity5 Standard Shader的官方文档论坛翻译版:
1.3 理解标准着色器的组成
上面说了很多标准着色器的强大之处,其实,作为一个着色器,它也没有什么神秘的地方,无非就是两个Shader源文件,加上一堆CG头文件组成的两个功能稍微复杂全面一些的Shader而已。其中,两个Shader源文件里,又按渲染路径分为了很多的SubShader,每个SubShader里面又分为了很多Pass。而CG文件中,主要包含了Shader的支持函数,相关的宏等为Shader源文件提供支持的代码。
Unity5中标准着色器的组成,归纳概括如下:
两个Shader源文件七个CG头文件一个脚本文件(用于自定义材质编辑器UI)
下面分别对每个文件进行一个简单的介绍。
1)两个Shader源文件
Stardard.shader着色器源文件 - 标准着色器的标准版StardardSpecular.shader着色器源文件 - 标准着色器的高光版
2)七个CG头文件
UnityStandardBRDF.cginc头文件-用于存放标准着色器处理BRDF材质属性相关的函数与宏UnityStandardConfig.cginc头文件-用于存放标准着色器配置相关的代码(其实里面就几个宏)UnityStandardCore.cginc头文件-用于存放标准着色器的主要代码(如顶点着色函数、片段着色函数等相关函数)UnityStandardInput.cginc头文件-用于存放标准着色器输入结构相关的工具函数与宏UnityStandardMeta.cginc头文件-用于存放标准着色器meta通道中会用到的工具函数与宏UnityStandardShadow.cginc头文件-用于存放标准着色器阴影贴图采样相关的工具函数与宏UnityStandardUtils.cginc头文件-用于存放标准着色器共用的一些工具函数
在包括本文在内的接下来的几次更新中,本系列文章将试着花篇幅来剖析这两个Shader源文件,和依附的几个CG头文件的源码,从而一窥Unity5中新版Shader书写体系的究竟。
3)一个脚本文件
StandardShaderGUI.cs脚本文件――定义了特定的自定义编辑器UI界面
标准着色器对应材质的编辑器外观不同于一般的Shader,就是因为在Shader末尾书写了如下的代码:
//使用特定的自定义编辑器UI界面
CustomEditor "StandardShaderGUI"
标准着色器对应材质的编辑器外观如下:
一般的着色器对应材质的编辑器外观如下:
二、Unity5标准着色器源代码剖析之一:架构分析篇
上文已经提到过,标准着色器源代码的剖析是一个小小的马拉松,完全解析起来篇幅会很长,所以本系列文章将对剖析的过程进行连载,此节为连载的第一部分。
在这里先贴出经过浅墨详细注释的标准着色器标准版的源代码,并对架构进行简单的分析,而对每个通道的剖析在稍后的更新中会进行。