我以前对 3D 模型完全没有接触过,顶多只是预览下样子,解包游戏模型看看未公开的模型长啥样而已。直到 2021 年底,玩恋活玩得走火入魔了,已经不满足偷别人的衣服了,我就想做自己喜欢的衣服,给可爱滴的"女儿们"穿上独一无二的裙子,就开始学习改模了。但是一开始我没有基础,很难理解各种概念。就像运维或开发也要知道各种名词,且作用是什么;在改模也不可避免提到这些基础。刚开始不懂基础,导致做出来的模型都是依托答辩。

某天自己心血来潮去看了下 B 站的快速入门教学,虽然我只看了前两章,但已经足够我重新学习一遍基础了。有些概念确实很抽象,但是自己做了一遍之后才更好理解原理。所以我也总结一下这一两年的改模经验吧,但我主要以 VRChat 的模型优化或改模来展开。

骨骼与权重(顶点组)

这两个是我一直最困惑的关系。当初什么都不懂,直接传递权重就完事了,导致实际看,衣服跟人体的运动关系完全一团糟。到了后面我才理清这两者的关系。

如果类比成人体与皮肤的话,骨骼 就是我们人类的真实骨骼,而 权重(顶点组) 就代表骨骼可以控制肌肤的 形变范围。我们的骨骼通过神经发出信号来移动关节,例如我们摇头的话,只能控制我们自己的 Head 骨骼,Head 骨骼所控制的形变范围是我们人类的脸部、眼镜、头发等器官,当然摇头也会稍微移动脖子范围,只是受力来说脖子比较少一点;

我们可以尝试抬手,当你举起手的时候,你就需要移动你的肩膀、手肘、手臂、还有手部这四段骨骼,是你的骨骼带动你的皮肤移动,不是皮肤带动你的骨骼。你的左手臂在移动,但你左手臂只能影响你的整只左臂,你在抬左手的时候,右手的皮肤不会跟着你左手移动;你只抬双手的时候,你的脚也不会跟着抬起吧。

当你抬手的时候,可以观察手臂和肩膀,移动范围最大的是自己的手臂,但移动的关节受力反而不大,移动影响的皮肤可能没手臂中央那样大。人类骨骼和关节就决定这些地方没办法大范围移动,否则会被拉伤骨折,所以移动的受力不会那么大。

QQ截图20231023155014.png

通过上面两个类比,其实大家都能大概明白。骨骼就是提供动力移动的事物,权重就是骨骼对应的区域的能干涉的范围。不同的骨骼只能干涉他对应的范围,在开端与末端受力影响比较小。

套衣服

了解上面的原理,我们给角色穿衣服的话,如果要自己做衣服的话,就要让衣服也给一个 "骨骼",让衣服可以跟着人体动起来。

同样是用人体和衣服来举例子,当你举手的时候,如果你穿的是短袖的话,你的衣服会跟着你的骨骼一起移动,那衣服的会形变范围是什么呢?那肯定只有你的袖子和肩膀、腋窝这三个区域。但在移动干涉范围来说,只有你衣服的袖子形变范围很大,肩膀和腋窝虽然也会动有变化,但相比袖子来说不会那么大。因此我们可以理解到,衣服也是跟着人体提供的动力来形变的。

如果你是幽灵,因为你没有实体,就是没有骨骼,你穿人类衣服的话可能会穿透。为什么呢?因为你的骨骼提供的动力或结构不适合人类的骨骼,因此你要将这件衣服改成适合幽灵的骨骼才可以让衣服跟着你的动作来形变。

因此,我们改模,套别人的衣服或者自己的衣服,我们就要想办法把人物的骨骼来带动衣服的 mesh。在这几年的适配衣服经验,我总结了三个方法。

1. 数据传递人物骨骼权重(顶点组传递)

这个是无庭老师刚开始教改模的入门方法,就是将这件衣服的 Mesh,引用人类身体骨骼的权重,或者跟他体型相近的衣服的权重,通过投射(我不知道是不是这样叫,可能是映射),这件衣服的布料能直接使用身体肌肤的权重。

但是有个问题是什么呢?要知道如果你买了一件 XXXL 的长袖,但你的身体平时都是穿 S 码的衣服,会出现什么问题呢?衣服会非常宽松,你的双手移动的时候可能只能让衣服的手臂范围产生形变,你的手腕移动也只能移动小臂那段区域,没办法直接让袖子也跟着你的手腕移动。

处理这种问题,我们需要将衣服修改成适合我们身型,而且要比较贴身,这样传递权重的时候,才能做到完美的形变范围。

我使用数据传递的修改器,一般用在贴身衣服(袜子、鞋子、手套等),因为贴身衣服有 99% 会跟着人类的骨骼移动的。但如果说像裙子或宽松的衣服,形变范围不会那么大,我们就需要另外处理权重问题了。下面这件和服是直接传递恋活人体的权重,这里就有一个问题:穿和服的话,因为振袖非常大,我们移动关节的时候,上袖的形变很大,但下袖在有重力的情况下不会产生太大的形变,下袖的形变更多来自于重力。这种我们就需要套用衣服原来的权重(如果有),给衣服加上重力形变骨,让手臂带动衣服重力骨运动。

2. 套用衣服原来的权重

这个是第二个方法,如果我们使用别人作者已经做好的成品衣服的话,这衣服是 MMD 的衣服,而我们的人体骨骼是标准的 Unity 人形骨骼的话,我们可以借用 MMD 的骨骼权重,将它们的权重直接改名或合成,改到能对应 Unity 人体骨骼范围。

这个可能非常难说明,这个我可能要单独写一份文章来讲述。我就简单说说吧,我们的手臂在中文名就叫 "上手臂",英文名叫 "UpperArm",在日语叫 "腕",我们人体骨骼名是用中文,但这件衣服骨骼名都用英文。因为语言不同,虽然我们都知道都是手臂的衣服,但计算机可不管,A一定就要叫A。因此我们就把衣服的 "UpperArm" 权重名改成 "上手臂"。这样的话,我们移动手臂的时候,"上手臂" 也会直接使用人体骨骼的 "上手臂" 一起移动。这就是我上面说的,怎么让幽灵能穿上人类的衣服。

刚刚方法一不是有个难题,有些衣服的布料,重力所造成的形变比人体还要大。这种就叫额外骨,我们可以直接将这些额外骨拆分成独立的骨骼,然后合并到人体骨骼。比如一条简单的 JK 裙,腰带固定在人体的腰上(Hips),Hips 就是固定骨;裙子的布料受重力影响多,所以裙子四周都是额外骨(Skirt_Bones),但我们转身的时候,腰部也会运动,裙子也会跟着腰部运动而旋转。我们就要额外骨(Skirt_Bones) 成为 Hips 的子级,这样裙子可以做到跟着身体运动,裙摆也受重力影响朝下,但裙子不会掉下来。

3. 自建骨+自修权重

如果自己做了一件新衣服,或者提取的衣服没有骨骼关系,这种模型就叫素模,只是一个雕像而已。衣服我们可以用第一个方法传递人体权重,但是?裙子怎么办?胸部呢?受重力影响比较大的布料呢?

这种难度非常大,传递人体权重未必是完美的,需要自己涂权重。非常费劲不讨好,虽然可以用自动权重,但效果不是很理想,我做的时候顶多是做裙子的时候会用自动权重,其他部位就只能靠自己了。

我做的话,裙子、缎带或头发,我就单独拆开,单独给这些网格建立骨骼再细分。调整好大概的位置,自动权重或自己涂,最后合成,做好的骨骼合并到人体模型上。总之就是很费劲...特别是用 MD 做的布料衣服。

模型优化

以下优化我是针对 VRChat 的模型评价进行优化。这里只说明思路啊,方法得大佬们自己摸索。

官方评级

详情我们可以查阅官方文档的 Performance Ranks,这里只针对 PC。我这边列出最需要优化的地方

模型指标ExcellentGoodMediumPoor备注
面数32000700007000070000一般是指三角面
显存40M75M110M150M贴图占用显存容量,不是图片大小
蒙皮网格12816对我理解就是模型网格的独立 UV
网格481624跟上面差不多,把模型拆分成几个独立部件
材质球481632模型对应UV需要独立渲染效果的区域
骨骼75150256400人物骨骼
PhysBone 组件481632人物骨骼需要受物理形变的骨骼

对我们来说,做到一个稍微能看且优化不错的模型,Medium 完全足够了,Good 的话取舍太多了,所以我觉得大家只要做到 Medium 的话就已经很好了。

如果要上传 Fallback 模型,你的模型必须达成 PC&Quest 都达到 Good 评级,Quest 的模型是另外的模型,你可以直接引用 PC 的 avtr_id 再上传。不需要把 PC 的模型优化到 quest 的评分。

还有很多,对我来说这些指标是大多数改模玩家比较难优化的地方。很多人都是简单套衣服,一个人体叠着穿各种衣服,用动画来显示隐藏衣服。我个人很反感衣柜模,因为衣柜模塞了一堆未必穿得完的衣服,这些衣服会增加网格和显存和材质球的数量,这些会占用显卡的处理开销。但这个也没办法,大部分萌新都喜欢这种多合一的模型。不过作为一位玩很久的玩家,我们已经不是萌新了,我们应该贯彻 你好我好大家好 的理念,转变自己的改模方式。

同一个模型为了满足不同评级,要做出不同的取舍。能做到 Medium 已经不错了,没必要强求 Good 了。我这个模型还有 Poor 版本,Poor 版本好看点。如果做跳舞模的话,我觉得做到 Medium 的话,其他大佬看你模型至少不再是个热狗人了。

我的改模流程

我当前改模很简单,一件衣服对应一个模型,我宁愿精心搭配一套穿搭,也不想随便套各种衣服就事。太乱来了,而且切换起来非常麻烦。什么都要却很难照顾全局,我们现实生活也一样,今天穿上可爱的 Lolita 的衣服鞋子,妆容和头发肯定得配上可爱的打扮,打造属于自己的 OOTD。如果你又想在这穿搭加一点 JK,加一点汉服,妆容换成地雷妆,不会觉得很怪吗?

因此,精心给自己做专属的 OOTD 独立模型,才是最正解。只有一套衣服,一份头发,一份袜子和鞋子,面数就可以限制到 70000 以内,有效控制贴图的数量,降低显存的占用。

优化面数

我会使用 Cats 插件来一键减面,素模的话可能用 ZBrush 减面,或者重拓扑减面再自己拉 UV。有些 Booth 的模型,就一个简单的颈环,居然会有 10W 个三角面。完全是没必要的。我们要做减法,一些看不见的地方,或者范围很小的模型,我们就尽量压缩他们的面数。

  1. 布料覆盖的地方,把被衣服覆盖的人体网格删掉。(你都穿得严严实实,身体手臂和大腿就没必要显示了吧)
  2. 鞋子和饰品那么小,我牺牲点面数也没问题吧?(一个锁链占你十万面,是不是有点过分呢?)
  3. 衣服看看能不能减面一点点,先 -1000 再 -2000,视觉没问题的话继续做减法,变怪就撤销。
  4. 研究下衣服模型里面有无多余或叠加的网格,例如毛衣模型,你可以考虑把袖口空缺的地方缝在一起,然后把毛衣里面看不见的网格都删掉。

例如这个模型,是 Booth 的成品衣服,但这个眼镜为了让苹果好看点细分了很多,但苹果那么小一个,一个顶一件衣服,这种就可以考虑减面,减面到 3000 也不会有太大的视觉损失。

这种也是典型的模型刺客,看很简单的 choker 面数很多且就纯黑色,就占用了 4 个材质球。

显存与贴图

你想你都用一体机,你的显示器又不是 4K,串流的画面肯定不是无损的,衣服再高清在你的串流画面也是有损的。所以这些地方也要做减法。

  1. 有些纯颜色的模型,直接贴个 matcap 就行了,贴图没必要。
  2. 可以将贴图压缩到 1080 或 512 分辨率,影响视觉就自己做取舍(matcap或蒙版压到 512 我觉得也没问题);
  3. 法线看情况压缩,小模型的法线贴图直接删掉也没问题(法线是给低模有高模的质感,也是跟上面的思路一样,看不见或者不是重点的地方做可以优化掉);
  4. 尽量不要用 Crouch 压缩,因为 Vrchat 解压贴图会占用 CPU,其他好友和你一起卡。
  5. 有些不需要贴图就算自己删了,可能会被材质球的其他开关引用着,要记得取消引用。(使用插件)
  6. 贴图压缩的话,如果贴图没有 Alpha 通道,格式可以考虑选择 RGB 16bit。

取消不需要的贴图的引用

骨骼复用、父骨做动骨

骨骼的话,我一般改模直接在 Blender 改模,骨骼与权重直接使用上面的方法二,把衣服的骨骼权重名改成 VRC 模型的骨骼名,额外骨直接接到人体骨骼上。这样的话可以复用人体的骨骼,就不需要绑骨了。

但 MMD 的衣服的话,他们为了布料模拟做了很多刚体,裙子的骨骼比人体还要多。对我们来说不需要那么多裙骨的,我们可以 Cats 插件的 Merge Weights 合并连续的骨骼,再调整下骨骼的大小,这样就能优化好骨骼数量了。如果想做到 Good 评分的话,可能要把骨骼当裤子穿了,就是裙子左边套用左腿的权重,右边用右腿的权重。

对于动骨,我们可以像之前一样采用减法的方式进行优化。刘海部分不需要进行调整,因此我们可以考虑合成或删除物理组件,对于不需要动骨的网格,可以避免添加动骨组件。提到蝴蝶结的骨骼,一般会将其分成四段骨骼作为额外的骨骼。我们可以在额外骨骼的父骨骼上添加动骨组件,没必要四个骨骼都各添加一个动骨组件。单个父骨骼动骨直接控制四个额外骨骼,从而节省了三个动骨组件的使用。头发也可以采用类似的方法来处理。(该段落由 AI 优化)

如果你心情好想冲到 Good,裙子可以考虑只保留尾部的骨骼,应该问题不大。

骨骼越多会消耗 CPU 资源

这个是我在 VRC 贴吧以前看过的分析贴,但原贴找不到了。

大概意思,由于目前 VRChat 官方做地图 Udon 脚本比较摆烂,当你进一个带 udon 脚本的地图,游戏会给你的模型的骨骼都挂载一个乌冬组件。你的模型有 300 个骨骼就创造 300 个组件,地图人越多的话,总骨骼量会越来越多,这样量变促成质变,会变得越来越卡。虽然官方有距离屏蔽可以缓解,但你的模型如果有 700 个骨骼相当于四个玩家的量,你的游戏体验也会很糟糕。

所以,我不建议做衣柜模,就是这原因。如果你觉得不卡只是你的电脑性能不错,要多照顾配置比你弱的玩家。

不要用或者少量约束

VRChat 官方在历史开发者更新中提过关于 约束 的问题,原文 URL:https://ask.vrchat.com/t/developer-update-16-february-2023/16474?page=7 下面是通过 AI 翻译的内容。

约束有多糟糕?

在少量约束时并不太糟糕,但随着数量增加...情况就相当糟糕了。以下是我们进行的一些研究。接下来是包络数学!

从场景中启用 0 到 682 个约束,每个约束大约需要 3.2 微秒(0.0032 毫秒,但请记住,在 90FPS 下,您每帧大约有 11 毫秒的时间)。这听起来很小(而且单独来看确实很小!),但它们会迅速累积。在场景中有 300 个约束时,您将使用 0.96 毫秒,这相当于您帧时间预算的约 9%。将其翻倍到 600 个约束,那将近五分之一的帧时间都用于约束!!

对于用户来说,这已经是很多了,因为他们通常已经超过了 11 毫秒的目标,更糟糕的是,化身预设(如克隆、服装附件和其他社区创建的系统)通常为单个化身包含数十个或数百个约束。在 VRChat 实例中拥有超过一千个活动约束并不罕见。

以前改模教程中,有些教程可能为了让萌新省事点,通过用约束的方式直接绑骨,整理起来的话很方便。但是从官方的说明,约束越多,会影响帧生成时间,这样在游戏体验上会感觉有明显掉帧感或滞后感。因此如果想做多衣服模型的话,还不如传统绑骨或者用 MA 绑上去也行。如果实在要用约束,可以开启关闭衣服的时候,录动画也录上约束开关的动画。

关于详情的说明和数据可以参考贴吧大佬的分析:混水摸魚半年多大概分析出了一點VRchat異常的CPU開銷原因

Multi Child type 和 Endpoint postion

这两个大家看 PBC 的设置经常能看到,但可能比较难理解其意思。

按我的理解,Endpoint postion 是给动骨提供一个固定方向的力,可以拉长动骨碰撞体的长度,类似 DB 的 Force。如果你的骨骼比较短,可以提供一个在 Y 轴填 -0.1 或 0.1 来延长。

Multi Child type 的话,我们一般选择忽略忽略 是指父骨不受动骨影响,如果没有权重的父骨选忽略就可以了。但如果这个父骨就是衣服的第一根骨骼,是有权重的,选 First 的话,父骨骼也会参与物理骨骼的变化。平均 这个就不太清楚了。

Limit

Limit 我只讨论 Type。在此之前,我们要了解 欧拉角,点击这个超链接,里面有动画演示。

  • 选择 角度 的话,这条动骨可以在 XYZ 轴旋转;
  • 选择 Hinge,只能在绕 X 轴旋转 Pitch,换人话来说就是这个头发或裙子只能前后摇动,不能左右摇动;
  • 选择 Polar,只能在 Y 轴旋转 Yaw,换人话来说就是这个头发或裙子只能左右摇动,不能前后摇动;

如果是自己做衣服的话,你想省事不穿模的话,可以根据角度限制动骨的摆动。

材质球与蒙皮网格

在 Unity ,你的模型是不是共用同一个 UV,不共通的 UV 的模型会单独分成一个蒙皮网格。材质球就是你的模型某些部位做单独渲染,例如裙子的裙摆蕾丝与裙子本身,为了显示效果好看肯定会给蕾丝区域做蕾丝效果。那么,你的裙子模型就分成了柄图区的、蕾丝区两个材质球。

(以下内容用 AI 优化)

材质球是 Unity 中用来表示着色器的一种方式。一个材质球可以包含多个纹理贴图,并且可以定义渲染时使用的特定参数。在渲染过程中,显卡需要执行许多 D3D API 调用,这就是所说的 D3D Drewcalls。每一个材质球都代表一个独特的渲染调用,因此拥有更多的材质球就意味着显卡需要执行更多的渲染调用,这会增加GPU的负担。

对于优化性能,以下是一些可以考虑的点:

  1. 尽可能地合并网格(join meshes)。如果你有许多小的模型,那么最好是将它们合并成一个大的模型。这样不仅可以减少在运行时需要处理的网格数量,而且还可以减少绘制调用和内存占用。
  2. 尽量使用相同的材质球。如果你有许多使用相同纹理贴图的模型,那么最好是使用同一个材质球。这样就可以减少材质球的数目,从而减少渲染调用和GPU内存的占用。
  3. 使用MatCombiner来合并多个材质球。MatCombiner是 Blender 的一个插件,它可以用来将多个材质球合并成一个单一的材质球,贴图都会合成为一张贴图。这样可以减少渲染调用和GPU内存的占用。但如果想显示效果好看的话,需要自己做蒙版。

着色器优化与其他

这边摘录了下 VRChat 官方的优化 Tips,与自己的优化经验。可能收益不大,但量变促成质变,能高一帧也不错。

  1. 避免使用高开销的着色器,例如 Poiyomi与 Slientshader,或者有毛皮折射等效果的。不然 CPU 和 GPU 渲染开销很大。尽量使用轻量化的着色器,Standard,或者 liltoon/MToon 等稍微轻量化的着色器。而且着色器的话,最好全部用一套就一套吧(混搭其他着色器也没问题)。
  2. 少使用 Cloth 布料组件,而且 Unity 自带的布料挺辣鸡的。如果某些布料没有动骨又想让布料稍微有点物理效果的话,建议单独把需要动的网格分成一个 Mesh ,再涂满 Cloth 权重。Total Cloth Vertices 高于 200 点就 Very Poor 了。
  3. 少使用透明,尽量使用镂空(Cutout),透明也有渲染开销。当然如果想做眼睛或透肉效果的话,那也只能透明了。
  4. 要用透明的情况下,Two Pass 的开销也很大。
  5. 做金属或者漆皮效果的话,能用 Matcap 的话比较好,又省事又不需要自己做金属度设置。
  6. 使用 liltoon 的色调校正的话,建议上传前先烘焙新的贴图,否则其他玩家的盾牌关闭 Shader 的话,其他玩家看你的瞳孔或头发会是原来的颜色,不是你改色的效果。
  7. 有些玩家为了优化游戏帧数,盾牌也会关闭自定义动画,这样别人看你的模型是穿回默认的衣服,你换装别人也看不到。这些也是你需要考虑的内容。
  8. 如果你加了一件衣服,移动的时候突然消失了,可能是你的边界设置有问题。可以调整衣服的边界,或者勾选 "离屏时更新"。估计是根骨或描点覆盖问题,但我也不清楚问题点。
  9. 虽然没什么用,有些衣服的形态建如果你自己不怎么变更的话,可以考虑直接应用掉或者全部删掉。

这个是我改 Elpis 的衣服,我只想让手臂附近的布料稍微动起来就用布料系统了,但是 Cloth 会把整个衣服都纳入总顶点组,所以拆开单独一个 Mesh 能降低总布料顶点数。

待补全

我写得有点眼花了,写得有点乱七八糟,有些内容直接让 AI 帮忙整理了。

这篇文章后面继续补全。