前言
最近通关了《Alan Wake》(心灵杀手),整体感觉很不错,游戏虽然是2010年发行的,但是画面至今看来也还是不错的,尤其是游戏内的体积光效果,贯穿了整个游戏,因为光本身就是这个游戏中最强力的武器。
主人公是一位小说家,但是当你发现你所写的小说都变成了现实的时候,这肯定是一件细思极恐的事情。故事情节一波三折,颇有些美剧的感觉。
每次看到电锯,不由得想起被《生化危机》和《恶灵附身》支配的恐惧,好在这款游戏的电锯不太抗揍。其实《恶灵附身》跟这款游戏有不少相似的地方,都是在“意念”的世界中,所以游戏中经常出现走着走着天上掉下来辆火车啦,走着走着桥飞啦之类的情况。
游戏还是很给力的,我就不多剧透了,下面是本文的正题。之前的blog里面,大多是一些特殊效果以及屏幕后处理相关的内容,但是关于模型本身光照效果的比较少。今天刚好来玩一个简单,但是却很有意思的东东,叫做Matcap。
简介
Matcap,全称为Material Capture,翻译过来就是材质捕获。简单来说就是预先生成的一种存储了光照和反射等信息的贴图,运行时使用法线方向进行采样。Matcap的好处就是可以用很低的消耗来实现很多特殊风格的效果,但是Matcap也有一些缺陷,在于Matcap仅对于固定相机视角的情况较好,这也是Matcap的原理决定的。
Matcap主要是在Zbrush,Mudbox这些软件里面使用的,ZBrush里面雕模的时候有时候虽然没有贴图,但是效果看起来也挺好的,实际上就是Matcap的作用,而且这些美术大佬们不断在扩展这些matcap,积累了很多好玩的matcap效果,而使用这些效果却非常容易,只需要换一下贴图。
Matcap的原理
先来看一下Matcap的原理。先可以考虑一下CubeMap的原理,CubeMap是一个六面体,正常的反射采样时使用的反射对应方向上投影最近的面上进行采样,更简单一点的(应该算是一个Trick了),甚至可以直接使用法线方向进行采样,对于天空盒类型的反射也可以得到不错的效果,即不同法线所指向的方向有不同的效果。而Matcap将这一点发挥得更加淋漓尽致,因为Matcap只用一张图就可以。所以我们需要考虑怎样将这个法线转换到一个合适的区间来采样Matcap。
由于物体的法线是一个三维的朝向,但是我们最终采样到二维贴图也只有两个维度。我们需要去掉一个维度,在相机空间下的物体法线向量,我们可以不考虑Z轴的指向,即不考虑Z轴本身对屏幕空间的XY平面的贡献,因为法线是一个单位向量,如果法线在XY方向上的投影权重很大,那么说明在Z方向的权重就很小,对应到二维的Matcap上采样的位置越靠近边缘;而如果法线在XY方向的投影权重很小,那么Z方向的权重就很大,对应到二维的Matcap上的采样位置就越靠近中心。
接下来我们需要考虑的是在哪一个空间计算Matcap,如果是物体空间或者是世界空间,由于相机位置朝向不确定,不好确定法线的Z方向与屏幕空间的关系,我们不好确定舍弃哪一个维度。而相机空间下的物体在屏幕上的方位都已经大致确定,相机空间下相对运算要比屏幕空间更少一些。所以最合适的实际上就是相机空间下进行计算。
我们可以通过Unity的内置矩阵将法线从物体空间转化到视空间,然后对于是空间的法线方向,由于方向是(-1,1)区间,我们需要再将其*0.5 + 0.5变化到(0,1)区间,就可以实现使用这个xy方向采样Matcap贴图了。
Matcap的实现
上面了解了Matcap的原理,下面直接上代码: