单图转出来的模型塌,通常不是单一原因:一类是输入侧的问题——一张正面图本身提供不了侧面和背面约束,转出来的壳在斜看时自然没有厚度;另一类是参数侧的问题——深度尺度、相机 FOV、网格或体素密度、平滑强度没配对,几何是闭合的却比例失真或面片自交。判断顺序建议先别急着换图或换参数,用一组对照实验把「换图」和「换参数」分开,看塌陷是否随图片变化、是否随参数变化,再决定走哪条路。下面五节是可以直接照做的记录、实验和排查方法。
适用场景:单图转 Three.js 模型后出现侧面缺失、整体比例失真或局部穿插。操作动作:先固定相机机位截图,把塌陷按部位分类;再做「固定参数换图」和「固定图换参数」两组对照,最后在 Three.js 里用 DoubleSide 与法线材质排除渲染假象。验证方式:斜 45° 与 90° 侧视图是否有可测厚度、包围盒尺寸是否接近参考、旋转一圈是否出现空洞。风险边界:单图本身缺背面信息时,调参只能改善正面表现,背面仍需补几何或换多视图输入。
把塌陷现象按部位拆开记录
先统一记录方式,否则后面两次实验的截图没法对比。建议固定四个机位:正视图、侧视图(绕 Y 轴 90°)、俯视图、斜 45° 视图;关掉环境光和贴图,用线框或纯色材质,窗口尺寸保持一致,文件名带上图名、参数组和机位,例如 objA_p1_side_wireframe.png。同一个模型的四张图放在一起看,比单张截图更容易判断问题出在几何本身还是渲染。
- 整体缩放或尺度错误:模型绕轴旋转时四周轮廓完整、没有空洞,但相对地面或参考物体的比例不对,表现为悬空、穿地,或者包围盒某一轴明显偏离参考值。判断特征是「转一圈都实心」,问题在尺度参数或单位换算。
- 侧面缺失:正视图像是完整的,转到侧视图厚度趋近于零,斜 45° 能看到背面是空的或只是薄片,投影接近一条线。判断特征是「正面像、侧面薄」,这类多见于单图只给了正面信息、背面没有约束。
- 局部穿插或自交:整体轮廓大致对,但手臂与躯干、头发与脸这类相邻部位互相穿透,放大后能看到面片交叠,法线翻转处出现黑斑。判断特征是「局部黑、局部尖」,问题往往在平滑强度、网格密度或对称补全参数。
三类现象可以在同一个模型的四张截图里同时标注出来,后续实验只盯其中一类变化,避免一次改动看不出结果。
固定参数换图,看塌陷是否随图片变化
这一组实验的目的是判断输入图是不是唯一变量。做法是:把生成参数写成一份固定配置(记录到文件里,不要靠记忆),只替换输入图,连续跑三到四张不同来源的图——正面清晰图、斜 45° 图、带背景图、去背景图。
需要固定的参数项通常包括:深度或整体缩放系数、相机 FOV 与距离、网格分辨率或体素尺寸、平滑/去噪强度、是否开启对称或背面补全、输出朝向与单位。参数名以你使用的版本为准,但同一轮实验里这些值必须完全一致,只改输入图路径。
# 通用骨架,字段名按实际工具替换
input: ./images/objA_front.png
scale: 1.0
depth_gain: 1.0
camera_fov: 45
mesh_resolution: 256
smooth: medium
mirror_back: false
output_up_axis: Y
结果按下面这张表记录,每张图一行,四张截图对照打分即可,不需要量化到具体数值:
| 图名 | 参数组 | 正面 | 斜45° | 侧视图厚度 | 局部穿插 | 备注 |
|---|---|---|---|---|---|---|
| objA_front | p1 | OK | 薄片 | 近 0 | 无 | 换图后对比 |
| objA_45 | p1 | OK | 有厚度 | 可测 | 轻微 | 斜视图信息更多 |
| objA_bg | p1 | 轮廓偏移 | — | — | — | 背景干扰主体 |
如果换成斜 45° 图后侧面明显变实,而参数组完全没动,说明塌陷主要来自输入图缺视角;如果四张图侧面都是薄片,换图这条路的收益有限,问题更可能在参数或渲染侧。
固定图换参数,观察几何与法线的变化
这一组只保留一张表现最稳定的图,逐个改参数。改动顺序建议是:先动尺度类(深度系数、整体 scale),再动拓扑类(网格分辨率、平滑强度),最后动补全类(对称、背面填充)。每次只改一项,其余参数写回配置并截图标注,改完一项立刻拍四张机位图,避免一次改三项后无法归因。
每步的观察点固定为三个:包围盒尺寸是否接近参考物、侧视图厚度有没有从零变成可测、三角面数是否出现异常跳变。包围盒和面数可以用下面这段代码在控制台打印,作为参数对比的客观锚点:
const box = new THREE.Box3().setFromObject(model);
const size = box.getSize(new THREE.Vector3());
console.log('size', size.x.toFixed(3), size.y.toFixed(3), size.z.toFixed(3));
console.log('triangles', renderer.info.render.triangles);
如果改了平滑或分辨率,几何形状有变化但侧面厚度不变,说明参数影响的是表面细节而不是体量;如果法线出现大片异常色块而轮廓没变,说明影响的是着色表现,需要转到下一节的渲染侧排查。
在 Three.js 里检查法线与面朝向
有些「塌」其实是背面剔除造成的假象:几何是闭合的,但面朝向反了,从外侧看被 FrontSide 剔除,视觉上就像缺了一块。第一步先把材质切到双面渲染,对比前后截图:
const mat = new THREE.MeshStandardMaterial({
color: 0xcccccc,
side: THREE.DoubleSide, // 排查阶段临时改成双面
flatShading: false
});
如果切到 DoubleSide 后空洞消失,说明是面朝向或索引顺序问题,几何本身没塌,后续应修正法线或索引,而不是继续调生成参数。第二步用 MeshNormalMaterial 单独跑一遍,法线朝向一致的面颜色一致,朝向相反的会呈现明显不同的色相,扫一眼就能定位翻转区域:
const debugMat = new THREE.MeshNormalMaterial({ flatShading: true });
model.traverse(o => { if (o.isMesh) o.material = debugMat; });
验证方式很简单:同一机位分别截「标准材质单面」「标准材质双面」「法线材质」三张图,三张对比就能区分是几何缺失、面朝向反了,还是着色器参数(粗糙度、金属度、贴图未加载)导致的暗块。
按结论选择换图、重设相机还是手动补几何
两组实验做完,通常能落到三条分支中的一条。触发条件和验收标准如下,建议按顺序判断,前一条成立就不用走后面:
- 换图。触发条件:固定参数下,换成斜 45° 或多视图输入后侧视图厚度明显出现,且多张不同质量的图结果差异明显。验收标准:斜 45° 与 90° 侧视图有可测厚度,旋转一圈不出现薄片状空腔。注意风险边界:换图能改善的是有信息的那一面,纯背面仍可能缺失。
- 重设相机。触发条件:几何四视图都闭合,但整体看起来比例怪异、透视过强、边缘拉伸,或者模型在场景里大小明显偏离预期。操作动作是先调 FOV 与相机距离,再确认 near/far 没有裁掉模型;验收标准是正视图轮廓与参考图叠合、包围盒尺寸与场景中参照物比例合理。
- 手动补几何。触发条件:换图后背面依然是空的,参数调整只改善了正面细节,且业务上必须要一个能绕轴看一圈的模型。操作动作包括对缺失面做挤出加厚、沿对称轴镜像补背面、或在 3D 编辑工具里补齐后重新导出 glTF;验收标准是任意角度旋转不出现空洞、法线朝向一致、双面与单面渲染结果基本相同。
三条分支的共同前提是先做分类记录和两组对照,否则容易在「换图」和「调参」之间反复来回。参数侧能修的多是尺度和细节,输入侧缺的视角和背面,通常只能靠更完整的输入或手动补几何解决。