4.2 材质效果
请问常见的材质效果有哪些,并简述如何在Unity 3D中实现对应效果。
问题分析
我们知道,物体的材料会影响人对物体的判断。比如有塑料感的物体就会给人很轻的感觉,而拉丝的反光效果就会给人顺滑的感觉,等等。为了达到不同的表现效果,美术人员在制作过程中会采用各种辅助方式。
从效果的实现原理的角度来看,可以按照是否使用PBR(Physically-Based Rendering)作为标准划分。即使用PBR流程组织美术资源的为一类,其他的为另一类。
对于常规美术流程,即4.1节贴图分类中提到的方式,也是目前绝大多数游戏采用的资源组织方式。它底层基于兰伯特模型(Lambert),通过点乘的方式来估计照度,并通过功能拆分对应的贴图,功能之间互不干扰,给美术更强的控制能力。这既是优点也是缺点。优点是由于这种标准已经在游戏行业中广泛使用,因此并不难找到能够上手的美术人员。缺点是由于美术人员对效果有很强的控制能力,因此整个效果的调整对美术人员的能力要求很高。
另一方面,PBR技术弥补了这一缺陷。它根据能量守恒的原理来计算光强,Unity 3D中默认的StandardShader就是基于这种方式实现的。它的好处是只要按照材质参数表,即可配置出效果正确的材质。图4.4是引自Unity 3D官方文档中提供的参数对照图。
图4.4
在这种流程下,对美术人员的能力要求略低。但由于目前使用这套流程的团队不多,并且美术人员还不太熟悉这种模式,因此反而在制作的过程中造成了困扰。另一方面,这套资源流程对引擎也有些要求。由于材质效果依靠计算,因此美术人员在PBR工具中制作出的效果,与导入引擎后运行的效果会有所不同。不论是Unity 3D还是Unreal,都需要对PBR对应的Shader或材质参数做适当修正,以保障效果的一致性,这对技术层面也提出了更高的要求。因此,目前基于PBR流程研发的游戏数量增长得十分缓慢,相信随着技术的进步会逐渐成为主流。
对于额外的材质效果,不太介意是否基于PBR。虽然乱改贴图会影响PBR的效果,但常规材质效果都已经包含在标准流程中了。如果在PBR流程中需要加入新的特殊效果,则可以在颜色计算好后再叠加。因此下面的这些效果在两种美术流程中都可以使用。
因为需要比较材质效果,所以这里选取了Unity-Chan和Space Robot Kyle的资源作为效果参考。资源的获取方式可参考序言中的相关链接,后面代码片段的完整版本也在资源包中。
边缘光
无论哪种渲染模式,光感的效果都是核心。对于卡通渲染最大的特点就是利落的边缘光或阴影。在Unity-Chan中我们可以明显看到类似的效果,例如,角色袖子上的边缘光效果如图4.5所示。
图4.5
把袖子上的边缘光去掉后,整个衣服的效果就完全不同了,效果如图4.6所示。
图4.6
边缘光的计算并不复杂,核心是使用一张渐变图做控制,然后根据照度在图上做强度的采样,相关代码如下:
float_t rimlightDot=saturate( 0.5 * ( dot( normalVec, i.lightDir ) + 1.0 ) ); falloffU=saturate( rimlightDot * falloffU ); falloffU=tex2D( _RimLightSampler, float2( falloffU, 0.25f ) ).r; float3_t lightColor=diffSamplerColor.rgb; // * 2.0; combinedColor +=falloffU * lightColor;
高光效果
另一个比较重要的光效是高光,物体的质感几乎完全取决于高光的效果。我们可以看到在UnityChan的袖口、胸、马甲的兜附近都有明显的高光,效果如图4.7所示。
图4.7
如果去掉高光,袖子就会显得没有层次,马甲也松松垮垮,如图4.8所示。
图4.8
具体代码逻辑是通过一张高光图记录反光的倍率与色值,然后再与标准高光计算出的结果相乘。核心内容如下:
float4_t reflectionMaskColor=tex2D( _SpecularReflectionSampler, i.uv.xy ); float_t specularDot=dot( normalVec, i.eyeDir.xyz ); float4_t lighting=lit( normalDotEye, specularDot, _SpecularPower ); float3_t specularColor=saturate( lighting.z ) * reflectionMaskColor.rgb * diffSamplerColor.rgb; combinedColor +=specularColor;
渐变贴图
渐变贴图(Ramp)或者叫衰减贴图(FallOff),与前面的应用范围不太一样,它更多是以一种加强色彩控制的形式出现。例如前面提到的采样用贴图也是渐变贴图的一种,这里拿出来单独说,是因为有时候它不太明显,效果会与固有色贴图混在一起,让人以为是画在固有色中的效果。最明显的例子就是角色的皮肤。在Unity的皮肤效果中,使用了一张长方形的渐变图,如图4.9所示。
图4.9
在这张图的影响下,皮肤的效果如图4.10所示。
图4.10
如果去掉渐变效果,皮肤就缺少了层次感,如图4.11所示。
图4.11
实现方面,使用视线与平面法线点乘的值作为标准,在渐变图中采样。最终,通过渐变图的透明通道作为插值标准,与固有色进行混合。核心代码如下:
float_t normalDotEye=dot( i.normal, i.eyeDir ); float_t falloffU=clamp( 1- abs( normalDotEye ), 0.02, 0.98 ); float4_t falloffSamplerColor=FALLOFF_POWER * tex2D( _FalloffSampler, float2( falloffU, 0.25f ) ); float3_t combinedColor=lerp( diffSamplerColor.rgb, falloffSamplerColor.rgb * diffSamplerColor.rgb, falloffSamplerColor.a ); combinedColor=diffSamplerColor;
自发光
自发光效果(Glow)其实算是后处理效果的一种,并不属于材质层。不过它的贴图和参数配置都可以放在材质上,因此也算与材质有关,因而把它放在这里一起说。
这种效果最大的优势是,可以使画面看起来有更多的光源,这在很多特效中都会用到,当然用在角色身上的例子也比比皆是。这里使用Kyle做了一个简单的例子,来说明效果。
首先引入Unity 3D的Effect资源包,接着新建一个场景,在摄像机上挂载Bloom脚本,并做如图4.12所示设置。
图4.12
接着使用绘图软件,绘制一张用于加强颜色的遮罩贴图,如图4.13所示。
图4.13
最后创建一个新的使用StandardMaterial的材质,将其自发光(Emission)参数更改为如图4.14所示的值。
图4.14
调整摄像机角度,即可看到如图4.15所示的效果。
图4.15
可以看出,使用自发光对画面效果有很大的提升。当然这些提升也是有代价的,最明显的就是资源量变大,每增加一张贴图,就代表增加了美术人员的工作量。另外,由于它的底层原理是后处理(Post-Effect),因此也会增加运行时的内存消耗。在后面的内容中,我们会介绍如何定制自己的辉光效果。
材质捕获贴图
材质捕获贴图(Material Capture),通常被称为MatCap,在很多3D软件中都可以生成。它最大的特点是能真实地表现反射效果,而不需要在场景中提供对应的灯光。从本质上讲,它是将所有的光照信息都存储到了贴图中的。代码实现也不复杂,在运行时,只需将法线从模型空间转到视口空间,再将对应UV映射到贴图上就可以了。
在AssetStore中有名为“Free MatCap Shaders”的插件,它比较直观地展示了这项技术的效果,有兴趣的读者可以自行下载查看。效果如图4.16所示。
图4.16
其中展示的模型依然为kyle,上面的方形贴图即为MatCap贴图。
总结
本节主要介绍了常见的材质效果,并结合代码和实现方式进行了分析。需要注意的是,上面只是说了一些主流的材质效果,真实项目中的材质可能会更多。正是因为美术效果层出不穷,所以我们才能看到各种令人惊叹的游戏。
扩展问题
要应用多种效果势必会增加贴图的数量,有什么办法进行优化吗([:texturepath])?