如何让3D角色动起来

1,295 阅读8分钟

前言

先看看这张图,那是在2023年以ChatGPT为首的AI技术开始火爆互联网的时候,我们做过的一个AI技术应用场景探索,回头发现很多设想都已经在市面上实现并产品化了。那时我很想把虚拟小助手应用里面的智城IP小Z做出来,实现一个立体的、有动作的形象, 苦于当时能力没能投入。时隔1年多,AI能力又有了许多涌现,除了最初的语言大模型,AI在生成图像和生成3D模型方面有非常大的能力提升,甚至已经可以辅助把这个立体生活的角色形象实现,我觉得是时候动手了。

image.png

经过这几天的摸索,终于实现了在网页上展示小Z的3D形象,并控制它做出各种指定动作,下面我来有所侧重地分享整个工作流程。

xioaoz2.gif

实现思路

  1. 设计小Z的形象轮廓,提供正面、侧面、背面三视图
  2. 使用SD生成质感的角色图
  3. 角色建模,可以人工建模也可以AI辅助生成
  4. 模型骨骼绑定,在动作库挑选动作合并入模型
  5. 使用three.js调用模型

Honeycam_2024-09-14_18-24-29.gif

使用工具

工具版本说明
illustrator2020角色线稿绘制
StableDiffusion简称SD,AI生图工具,可以根据线框图,生成立体的、有质感的角色图片
blender4.2角色建模,绑定骨骼,添加动作
autoRig3.70blender插件,用于自动绑定骨骼,生成姿态控制器
quad remesher1.2blender插件,模型的网格优化工具(非必须)
mixamoAdobe官方的3D角色动画工具网站,可以提供各种各样的角色姿态和动作
wander3DAI工具,1张图片生成高质量3D模型(非必须)
three.js0.157经典的前端3d引擎,用于加载和控制模型

具体步骤

  1. 设计小Z的形象轮廓,提供正面、侧面、背面三视图,设计的时候需要注意各个身体部件在后面的步骤里能够实现。这里我就踩了一个坑,小Z最初是形象一个章鱼腿,后来在建模的时候发现做成手办会站不稳,才在第二版改成了阿童木的靴子腿。

    %E6%96%B9%E6%A1%88.2.0_0.png

  2. 将正面图片导入StableDiffusion,使用插件ControlNet辅助生成质感的角色图,网上已经有很多教程了,这里碍于篇幅就不赘述,AI生图的诀窍就是要耐心、且不断调整提示词抽卡和局部重绘,最终达到理想的效果。

    image 1.png

  3. 根据三视图对小Z角色进行建模,如果不会建模可以用Wander3D,本文的示例模型是我曾经的好同事刘睿博帮忙创建的,他还顺便帮我用3D打印机把模型打印出来了(他哭死,我真的),这里着重表扬他。

    image 2.png

  4. 将模型导入blender,可以用quad remesher进行网格优化,再进行稍微的调整、UV帖图

    image 3.png

  5. 贴图,最省事的做法是使用视角投影贴图。模型朝向正面,全选顶点后按U,选择“从视角投影”,但是这样的话贴图会直接映射在正面和背面模型上,不适合会展示到背面的场景。拆分组件后各自UV贴图,虽然费时间,但产出的模型精细化程度高;需要注意的是组件接缝处如果面没没有封闭好,可能会因为做动作出现破面的问题,可以适当把关节对接处延长。

    image 4.png

    Honeycam_2024-09-09_17-54-49.gif

  6. 使用autoRig进行骨骼自动绑定,导出FBX格式的文件备用,这里看后面小技巧部分。

  7. 打开mixamo,上传FBX文件成功后,即可选择并下载各种姿态动作。我们只需要下载一个蒙皮的动作,其余的动作全部选择不带皮的就可以了,这样文件体积更小容易下载成功。

    image 5.png

    image 6.png

  8. 使用blender合并动作到一个模型上,并导出模型文件FBX或gltf,使用系统自带的3D查看器就可以看到动作被合成进来,具体教程可以看参考链接

    image 7.png

  9. 使用three.js调用模型,核心操作就是加载模型和控制动作切换两个,源代码我放在这里了

    // 加载模型
    import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';
    const loader = new FBXLoader();
    loader.load("../static/gltf/xiaoz.fbx", function ( object ) {
        const size = 0.05
        object.scale.set(size, size, size);
    		//
        const index = object.children.findIndex(v=>v.name=="Light")
        object.children.splice(index, 1)
    
        object.children.forEach(element => {
            const {material ,name } = element
            if(['Retopo_ball','Retopo_face'].includes(name)){
                const material = element.material
                material.transparent = false
            }
        });
    
        scene.add( object );
        createGUI(object, object.animations)
    } );
    
    function createGUI(model, animations) {
      const states = animations.map(v=>{
          return v.name
      });
    
      gui = new GUI();
      mixer = new THREE.AnimationMixer(model);
      actions = {};
    
      for (let i = 0; i < animations.length; i++) {
        const clip = animations[i];
        const action = mixer.clipAction(clip);
        actions[clip.name] = action;
      }
    
      const statesFolder = gui.addFolder("States");
      const clipCtrl = statesFolder.add(api, "state").options(states);
      clipCtrl.onChange(function () {
        fadeToAction(api.state, 0.5);
      });
      statesFolder.open();
      activeAction = actions[states[0]];
      activeAction.play();
    }
    
    /**
     * @description 切换动作
     * @param name {String} 动作名
     * @param duration {Number} 切换过渡时间
     */
    function fadeToAction(name, duration) {
      previousAction = activeAction;
      activeAction = actions[name];
    
      if (previousAction !== activeAction) {
        previousAction.fadeOut(duration);
      }
    
      activeAction
        .reset()
        .setEffectiveTimeScale(1)
        .setEffectiveWeight(1)
        .fadeIn(duration)
        .play();
    }
    
  10. 页面实现的效果如下图

    xioaoz1.gif

小技巧

在绑定骨骼时如何创建镜像

  1. 选择想要复制镜像的骨骼,修改骨骼中各关节的命名,注意目前是在人体的右边,所以命名以R.开头,比如R.hand如下图所示。否则无法正常生成对称的骨骼。

    image 8.png

  2. 在编辑模式下,再次选择骨骼,点击左上角“骨架 - 对称”,即可直接生成镜像,且骨骼会自动以L.为开头命名

    image 9.png

如何使用autoRig绑定骨骼

  1. 安装插件auto-rig-pro,选择所有模型相关Mesh,点击Auto-Rig Rro:Smart 折叠项,展开后点击 “Get Selected Objects”。此时将模型朝向正面,根据控制面板按钮提示选择模型的关键节点(Neck、Chin、Spine root等)后就能自动生成骨骼,调整好骨骼以适应当前的模型。

    image 10.png

  2. 回到最初的Atuo-Rig Pro折叠项,点击Match To Ring,此时就会生成一堆姿态控制器

    image 11.png

  3. 打开在“蒙皮”TAB,点击其中的“绑定”按钮,此时就会自动将骨骼与模型绑定。选中某个控制器,R可以控制旋转,G可以移动位置,S可以进行缩放,Alt+G可以重置位置移动,以此类推。

    Honeycam_2024-09-09_18-17-10.gif

如何让模型表面更光滑有质感

  1. 使用blender,在物体模式下,选中模型,右键平滑着色

    image 12.png

  2. 在编辑材质的时候,设置“材质属性-表面曲面 - 光泽BSDF”

    image 13.png

创建姿态资产

  1. blender 4.0+版本姿态库有所变化,创建资产需要在“动画摄影表”等其他栏目中才能打开。

    image 14.png

  2. 切换到“资产管理器”栏目 可以对资产进行重命名、截图等编辑操作。

    image 15.png

  3. 所有的姿态可以是共存关系,比如姿态A设置了脸部表情,姿态B设置了动作,那么就可以点击姿态A和姿态B将脸部表情和动作结合起来。

  4. 我们还可以预览2个姿态直渐的动作过渡。在姿态资产选中默认姿态A,在主场景选中会发生动作的几个控制器,然后将鼠标按住目标姿态B,然后拖动鼠标,此时就会出现两个姿态之间的切换动画,顶部还有进度条。

    image 16.png

写在最后

至此让小Z从二维平面走入三次元,动起来的这一步实现了,这里面仍有许多需要完善的地方,比如模型做动作时不时出现的穿模和破面等情况,如何给小Z加上脸部表情,实现表情与动作的组合等等。

然而这不是终点,最终的目标是让小Z模型成为一个被调用的前端模块,结合我们的企业AI聊天助手同步各种动作姿态;而在宣传层面,我们可以把小Z的姿态和动作库完善起来,作为各种周边产品的视觉物料,或者形成各种短视频动画,当然这些工作量很大,都需要其他伙伴的参与了。

参考链接

手把手教你用AI把草图做成3D骨骼动画

React+Lingo 实现一个超好玩的3D游戏

为模型添加骨骼绑定

Blender3D模型如何进行骨骼和动作自动绑定

【Blender】UV详细解释及各种UV操作

Youtbue教程: 4.2 中使用 Mixamo 动画

在blender合并mixamo动画

使用autoRig同步骨骼动作

合并多个mixamo动作到fbx