想做Web 3D捏脸?看了这篇文章你就会!

游戏里的人物捏脸见的多了,网页里的捏脸见过么?

3月6日完美世界手游上线,前期需要一个预创角营销活动进行预热。

与以往预创角活动不同的是,这次我们采用了Web 3D捏脸的形式为活动创造亮点,也取得了相对不错的数据。

这也是我首次在项目中实践Web 3D技术,边学边做,学到了不少东西,也有一些心得体会。

本篇文章作为项目总结和经验心得分享出来,希望能对Web 3D捏脸技术感兴趣的同学产生帮助。

目录:

  1. 项目展示
  2. 前期准备
  3. 捏脸技术实现
  4. 排期建议
  5. Web 3D展望

一、项目展示

活动已经结束,我截取了核心的3D捏脸部分单独生成了一个DEMO页面,大家可以先扫码查看项目效果:

3D捏脸在游戏中已经属于很常见和常规的操作,但是在H5中实现,可能是业界首次,相对比较新颖;加上负责资源推广的同事给到了不错的资源推广,两两相加,产生了相当不错的数据效果。

二、前期准备

相对传统H5,这里会多涉及一些3D方面的技术,所以前期在工具上需要准备至少下面3个:

  1. Three.js:
    一个 JavaScript 编写的WebGL库,可以方便的实现很多 3D 功能,你可以简单粗暴理解为WebGL方面的 jQuery 。
  2. 3DS Max:
    游戏研发侧给过来的 3D 模型 .max 源文件需要用 3DS Max 来打开进行编辑,所以也需要安一份,就像写页面需要安 Photoshop 一样的道理。
  3. sketchfab.com:
    网站上提供了很多素材,但是我们需要的是它提供的在线编辑器功能,编辑器有很多功能比3DS Max内更方便,但要注意免费用户如果需要下载你编辑后的3D模型需要进行发布,而发布意味着其他用户也能看到你的模型。

除了工具,还需要游戏研发侧提供相关的3D模型以及数据:

  1. 人物3D模型:
    需要给到面部绑定有骨骼和蒙皮的 3D 人物模型源文件,一般是 .max ,但也有可能是其他 3D 工具制作的模型。
    如果有身体部件需要动态更换(如挂饰动态切换),还需要提供到相应的部件源文件。
  2. 面部贴图素材:
    除基本的面皮外,眉毛、胡须、腮红、纹身、眼影、唇彩,这些部位的贴图也需要单独提供,用于动态更换时做面皮的合成,后续会讲到具体用法。
  3. 捏脸参数:
    因为需要和游戏内同步,所以相关参数也需要给到,比如嘴唇大小一共有0-31档可调整,那么每一档调整的幅度时多少,调整的方式是什么。
  4. 捏脸数据导出格式:
    最终捏脸数据是需要导出后给到游戏内适用,所以捏脸参数最终导出的格式需要和游戏内保持一致,具体数据格式规则需要在Web端同样实现一套。

三、捏脸技术实现

1. 利用 Three.js 搭建场景、镜头

Three.js的 3D场景、模型均通过WebGL渲染在Canvas之上,引入Three.js后,首先需要把场景、摄像机、灯光、渲染器运行起来,基础代码每一项就几行,使用不同的对象方法可以达到不同的效果,具体更多的使用方法可以参照官方文档

代码执行后,你应该会看到一张带有网格辅助的3D场景出现在页面中:

2. 载入模型

场景搭建完毕以后,需要载入3D模型,模型格式和我们常见的图片格式(JPG/PNG)一样,有很多种,3DS Max默认导出的格式为FBX。

相对FBX,Three.js官方更推荐GLTF,我在项目中对同样的模型进行了分别测试,GLTF在体积上要比FBX小许多,更利于网络传输,至于其他优点,可以查看这篇文章

如果需要获得GLTF格式的3D模型,可以通过装babylon插件来为3DS Max增加GLTF导出功能,也可以通过一些在线转换器、编辑器来在线转换,如sketchfab.com。

无论是FBX还是GLTF,都需要在加载Three.js后额外加载一个对应的格式加载器,如FBXLoader.js或GLTFLoader.js,这些加载器官方都有提供下载,直接引入即可。(FBX需要额外再引入一个inflate.min.js)

这里我们以GLTF示例,导出的二进制GLTF格式包含两个模型文件以及一堆贴图:

加载模型的代码也很简单,实例化GLTFLoader后调用load方法,方法第一个参数是模型路径,回调函数中返回的值就是模型,添加到场景中即可。

然后你就可以在网页中看到你加载后的模型,灯光很简陋,所以模型是黑乎乎的一片,大家后续可以参照官方文档中的灯光部分慢慢调整。

这里要注意,之前的渲染方法renderer.render(scene, camera);,在这里要改为加载模型完毕后在调用,否则先渲染,后加载模型,是不会显示出模型文件的。

3. 调用模型动画使模型动起来

刚才加载的模型时静态的,如果需要让模型动起来,需要使用Three.js中的动画播放器AnimationMixer。当然,前提是美术同学已经在模型中制作了动画。

我们需要先在模型加载完毕后的回调函数中为模型添加播放器,并生成动画实例,然后调用play方法执行播放操作。

因为动画是不间断执行的,所以需要有一个循环函数(animate)不断的推荐播放器的时间(mixer.update)来更新动画,循环函数中也需要不断的渲染3D场景(renderer.render),最终就得到了动画的播放效果。

4. 通过骨骼点来进行捏脸

3D捏脸实现原理是通过代码来更改3D模型面部的骨骼点,对骨骼点进行旋转、缩放、位移可以达到面部样式的修改。

上图是美术同学在3DS Max中设置的骨骼点,当模型文件通过Three.js加载到网页中以后,这些骨骼点会以对象的形式返回,通过traverse方法遍历模型的所有对象元素,并筛选类型为骨骼,可以找出所有的骨骼对象。

 

每一个骨骼一般美术同学都会标注一个名字,可以粗暴的理解为Photoshop里的图层名称,找美术同学要一份对照表,找到对应的骨骼就可以修改对应的部位。

比如我们这里修改嘴巴的大小,首先过滤到嘴巴具体的骨骼点,展开对象后可以看到position、rotation、scale,通过修改这些值,就可以调节面部细节了。

比如我们更改scale:

 可以通过下图对比看到右侧的模型嘴部明显变大了(请忽略这鬼畜的灯光,不是重点……)。

依次筛选出眼睛、鼻子、颧骨、眉毛等各个部位的骨骼点,然后根据游戏研发侧给到的数值表来对照调整,就可以做到和游戏内一致的捏脸效果。

5. 面部元素的皮肤合成

面部皮肤贴图包含“面皮、眉毛、胡须、眼妆、腮红、纹身、唇彩”等多种皮肤元素,且多个元素都是可进行颜色修改的,但对应的模型只是一个面部模型。

所以用户更改所选面部区域的对应贴图后(如选了不同的眉毛),需要动态的更改整张脸的贴图。

这里的实现方案是:

  1. 根据用户所选分别加载不同形状的部件图片,如“胡须样式_4.png、眉毛样式_2.png”等……
  2. 根据用户所选颜色,利用Canvas对部件图片进行像素着色。
  3. 将所有部件通过Canvas拼合到一起并附加到3D模型上。

    效果展示:

6. 毛发颜色的更改

头发的颜色修改相对简单,对应的对象中有一个color对象,里面包含了R/G/B三原色的键值百分比,直接修改这个值,就可以更改头发模型的颜色。

比如你可以在PS里找到一组37/81/121的颜色值,然后37/255=0.145,挨个填进去就行。

而眉毛、胡须的颜色修改是修改具体贴图的颜色,更改方法在第5点钟有介绍,是通过Canvas对图片像素点逐个修改,最后拼合成一张皮肤贴图附加到面部模型上的。

7. 捏脸参数

需要Web端捏脸数据和游戏数据互通,即Web端创角后,待游戏正式上线时,用户使用预创角的账号登录游戏,就可看到自己的捏脸形象。

所以需要同步游戏研发侧的捏脸参数,这里根据游戏研发侧提供的参数Excel表格进行各个幅度的对应修改,保证和游戏内的效果一致。

Excel表格中列出了对应的每一个骨骼需要调整的范围,以及调整的方式(position/rotation/scale)。

在Web界面中,根据表格中参数调整滑动条每一个刻度的值,从而达成和游戏内一致的效果。

比如根据表格,嘴巴大小涉及的骨骼是“Mouth”,需要修改的参数类型是“scale”,然后范围是3 – 10,一共分为31档调节,那么每一档就是(10-3)/31=0.226,用户在UI界面调整滑动条时,代码中就根据滑动条调整的刻度乘以0.026进行调整即可。

当然也存在一个骨骼需要同时调整position/rotation/scale的情况,也存在不同的位置调整涉及的是同一骨骼的情况,这时就需要记录之前的调整值,基于这个值继续调整。

8. 捏脸数据导出格式

同样,为了保证和游戏内一致,需要同步游戏研发侧的捏脸数据导出格式,这里介绍的是完美世界的捏脸数据导出格式,每一款游戏的导出格式会不太一样,仅做参考。

完美世界游戏侧的人物创建最终导出时会将所有的十进制参数值转为二级制的方式进行数据存储。

首先,根据可调节的范围,制定每一个参数值的二级制位数,如调节范围最多为31个档位,那么二进制位数就为5位,因为5位二进制(11111)刚好可存储31档。

然后,将每一项调节数据的参数值进行排列然后转为二进制的方式(不足位数的前面补0)再进行排列。

最后,每32位二进制作为一个分隔,最终形成游戏内可用的捏脸数据。

如:

3D模型各项调整参数值为:
[12, 7, 13, 12, 11, 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 14, 0, 7, 8, 11, 13, 2, 20, 0, 6, 16, 21, 16, 3, 10, 12, 6, 15, 8, 31, 22, 11, 4, 30, 7, 7, 9, 7, 0, 21, 18, 16, 18, 8, 16, 3, 13, 13, 10, 0, 0, 0, 2, 2]

最终得出的提交游戏内的格式为:
[347485420,8192,0,0,2699063488,403310805,2560737968,1172039801,2162768380,1883545898,42676,132,0,0,0]

以上就是这次3D捏脸项目的核心技术点,剩下的类似灯光的调整、模型加载优化、代码管理等细节限于篇幅就不展开了。

四、排期建议

从各主流浏览器开始支持WebGL到现在已经有好几年的光景了,但是在团队中的应用还是不多。Web 3D在日常业务的应用难度确实要高于日常需求,但其实只要解决了两个核心关键点就行。

一是和游戏研发侧建立良好沟通,3D需求中的各类3D模型和参数就类似日常需求中的设计稿一样重要,没有这些,巧妇难为无米之炊。二是对Web 3D技术进行相关的学习,扩展新的知识点。

针对第一点,相对于常规需求,3D需求因为需要游戏研发侧的支持,也就等于多了一个需求环节,在排期上会多占用一些时间,而且和游戏研发侧的沟通很多时候需要一对多,你不仅需要跟美术同学沟通需要的3D模型素材,还需要和开发同学沟通3D模型的一些捏脸参数和毛发等颜色的色卡搭配。当然,如果这些环节如果后续可以尽量的标准化成为一个常规需求的流程,那就可以节省下不少的时间。

针对第二点,我们建议在项目初期有一个预研的过程,大概1-2周,首先确定具体Web 3D需求,然后进行一个最简单的,判断是否可行的DEMO制作。比如3D捏脸,先索要一个3D模型,然后询问研发侧同学他们在游戏内的捏脸实现方式(这次的“完美世界”是更改模型骨骼),我们根据游戏侧的实现方式,在Web端进行同样的实现。这个过程其实就是Web 3D技术的不断储配。

当第一点我们做到尽量流程标准化,第二点我们对Web 3D技术的掌握达到了常规需求的认知程度,那么Web 3D项目就可以也变成我们一个信手拈来的、可以支持大量需求的常规业务了。

五、Web 3D展望

目前Web 3D项目在我们的日常应用长还不多,而我们的游戏绝大多数都属于3D游戏,适当展望一下,是不是很多场景都可以通过3D来更好的展现呢?

官网的职业介绍页可以考虑展示3D人物模型,技术能支持到的情况下,甚至技能特效也可以在Web端进行预览,提前让玩家从各个角度查看人物技能。

MOBA类游戏的录像回放功能,是否可以考虑在Web端做一个免开游戏的简版回放?载入3D地图模型,导入各个英雄,搭配回放日志,自动播放当时的战况,用户可以在Web端进行各个视角的切换,不受视频回放的固定视角制约。

FPS类游戏经常需要针对各个地图进行战略要点的布局,可以考虑在Web端做一个地图战略布局工具,用户在实际的3D场景中进行各类标记,然后还可以分享和导出,远比2D地图来得方便和直接。

参考&资源:
https://threejs.org/docs/index.html
https://www.bgteach.com/article/132
https://doc.babylonjs.com/resources/3dsmax_to_gltf
https://sketchfab.com

技术研究
原文地址:https://tgideas.qq.com/gicp/news/475/7353659.html?from=list