最近工作上遇到了与捏脸换装相关的工作内容,由于涉及到了以前未接触过的领域,在这做个工作总结。
捏脸这部分市面上一般有四种解决方案:
1.基于骨骼调整:调整骨骼的Scale、Rotation、Position
2.基于MESH差值:制作两个最大和最小值的Mesh,然后根据差值计算中间的Mesh,运行的时候生产最终的mesh
3.基于材质:简单的来说通过shader与贴图来控制肤色、瞳孔颜色、唇色等。
4.替换Mesh:这个属于是最简单的,但对于美术来说会产生巨量的工作量,一般是用作特殊配件,比如发型、时装、额外的饰品等。
捏脸的系统要保证运行时效率的同时,预览的速度也要做保证,有时候这两者会有一些冲突,可以通过多方案支持、内存换效率之类的方式来进行优化。如果是手游,最好关注下极限情况下的渲染效率和内存消耗,毕竟如果有材质参数的修改是无法合批的,基于骨骼或者mesh的修改的话对于内存也有一定的额外消耗。
基于骨骼调整
其实基于骨骼调整捏脸比较有参考价值的是《Honey Select》中的捏脸系统
对模型资源的规格进行分析, 发现存在大量的morph动画. 也就是说, HS中的的头部骨骼, 全部是用于捏脸的, 表情动画使用MorphTargets(BlendShape)驱动.
对于头部来说这种方式非常便捷,因为HS作为一款端游卖点就是高精度自定义,如果是手机端的话可能可以做相应的取舍。
下面是身体部分
查看其蒙皮信息可以发现, 所有影响顶点的骨骼名字全部带有”_s_”字样, 其父骨骼都是不带”_s_”的同名骨骼. 也就是说, HS的身体骨架中, 父骨骼负责动画, 子骨骼负责蒙皮.
基础的美术工作到这就差不多,但当我们进行调节的时候应该有一个更加平白的表达方式,比如说调节鼻子骨骼的信息,我们的确只需要调节NoseBase的Y值就好了,我们需要做的就是根据滑杆在最大值和最小值之间进行线性插值.
对于”眉毛角度Z轴”的调节, 这时只调节一根骨骼就不对了, 需要左右对称着来. 也就是说, 有一些调节项需要同时调节左右对称的两根骨骼.
对于”眉毛左右位置”, 如果在直线上两个端点之间进行插值, 很容易就跟面部三角形穿插了. 所以这里的插值路径只有最大值和最小值已经满足不了需求了, 而是需要按照曲线进行位置插值, 并且配合旋转插值贴合面部的法线方向. 也就是说, 一个调节项的插值可能是基于曲线(或多个关键帧), 而且可以同时影响骨骼Transform的多个分量.
眼睛的大小调节是最复杂的, 一共影响6根骨骼. 也就是说, 一个调节项是可以对应多根骨骼的.
我们总结一下, 脸型(或体型)调整原理就是:
- 本质上修改的是骨骼的Local Transform(Translation, Rotation, Scale)
- 一次只修改Local Transform的某个分量(或多个):Tx/Ty/Tz/Rx/Ry/Rz/Sx/Sy/Sz
- 使用滑杆在预设的调节范围之间进行插值
- 插值不一定是线性的, 可能是有多个关键帧
- 每个调节项可能对应不只一根骨骼
对衣服的资源进行分析可以发现两点值得学习的地方:
- 每件衣服都配有一个剔除掉被遮住的三角形的裸模, 一方面可以提升绘制性能, 一方面能避免衣服和皮肤两层三角形的穿插
- 裙摆/披风/长衫等都是共用同样的8条物理骨骼, 算是比较传统的布料模拟做法
基于MESH差值
捏脸主要区域集中在正面,如果美术有能力统一脸部拓扑,使用Mesh差值通过顶点动画实现预设头更好的解决办法。取得新的顶点位置后,要重新计算Mesh法线。
即使头发使用mesh,头皮依然需要相应颜色的贴图映衬。对于短发寸头,通过对贴图改变发际线的形状也可以取得更多头发的多样性。
捏脸到底使用Mesh差值还是使用骨骼调整,具体还是要看引擎的要求。有的引擎对于Morph Targets优化更好,有的对于骨骼动画优化更好。同时这也取决于你的脸部动画是通过骨骼驱动的还是Morph驱动的。
如果没有性能要求,谁的效果好? 答案肯定是基于Mesh差值的结果。
关于楚留香传的捏脸系统,在额头附近同时调节两个控制器会造成异常的凸起。 这是因为两个控制器同时对相同一部分顶点造成位移而形成的的Double Transformation。可以在美术上normalize两个控制器的影响,或者在程序上限值两个控制器的调整范围。
捏脸是个系统工程,需要美术,程序,设计师多方面的讨论。
说一个不容易发现的细节:有的预设头如果眼睛的距离本身很近,那么控制器是在默认状态就会锁住你的范围,避免你捏出一个眼距过大过小的怪物。