img2threejs 把单图转成 Three.js 场景,先确认原图能给出多少深度线索

文章导读
手里只有一张图时,先别急着点转换。img2threejs 这类把单图变成 Three.js 场景的处理,本质上是把可见像素反推成少量几何与贴图:没拍到的背面、被挡住的交界、没有纹理起伏的平面,只能由模型补猜。判断顺序建议是:先确认原图的透视是否单一,再标出信息缺失区,然后跑一次最小转换查看交付物结构,最后用自检清单决定直接可用、返工还是换图。
📋 目录
  1. 壹 在原图上标出灭点与地平线,判断透视是否单一
  2. 贰 逐块检查遮挡与重复纹理,标出模型必然会猜错的位置
  3. 叁 跑一次最小转换,查看输出的对象树、网格与材质命名
  4. 肆 编写场景自检清单,逐项判定可用或需返工
  5. 伍 根据检查结果,决定补图、换图或进入 Three.js 手修
A A

手里只有一张图时,先别急着点转换。img2threejs 这类把单图变成 Three.js 场景的处理,本质上是把可见像素反推成少量几何与贴图:没拍到的背面、被挡住的交界、没有纹理起伏的平面,只能由模型补猜。判断顺序建议是:先确认原图的透视是否单一,再标出信息缺失区,然后跑一次最小转换查看交付物结构,最后用自检清单决定直接可用、返工还是换图。

单图能撑起什么程度的 Three.js 场景,取决于四点:透视是否单一、遮挡区是否落在次要位置、纹理是否唯一、阴影方向是否明确。做法是在原图上标地平线、灭点和四类高风险区域,再跑一次最小转换,核对对象树、网格与贴图引用。四项自检不过就补图或换图,别靠手修掩盖几何缺失。

在原图上标出灭点与地平线,判断透视是否单一

准备一张原图的副本,用任意标注工具(Photoshop、Figma、系统截图标注都行)在上面画线,不改动原文件。先找地平线:画面里本应水平的边,比如窗台、桌面边缘、远处海平面,沿这些边画直线;如果这些线在画面上大致重合于一条水平带,就能定出地平线位置。再看可见面数量:只看到正面一类面,说明深度线索不足;能看到正面和侧面两个面,几何大致能由一组相机参数解释;同时看到正面、侧面和顶面三个面,通常还能接受。

判断鱼眼或广角畸变,看三点:本应笔直的边出现弯曲、画幅边缘出现明显拉伸、两条平行边在画面内明显向外扩。出现任意一条,单相机针孔模型的解释力都会下降,转换后的墙面和地面容易歪。

还有一种情况需要单独记录:左侧窗格向右收敛、右侧窗格也向外扩,收敛方向互相矛盾。这类图可能是拼接或经过了非针孔投影,转换结果会同时出现两个方向的倾斜,不能指望靠改相机参数修回来。判断结论记成一句就够:“一点透视/两点透视/透视矛盾”,后面选补图还是换图要用到。

逐块检查遮挡与重复纹理,标出模型必然会猜错的位置

同一张副本上继续标注四类高风险区域,每类用不同颜色,标完大致判断各类区域占画面的面积比例(用眼睛估个区间即可,不需要精确数字)。

img2threejs 把单图转成 Three.js 场景,先确认原图能给出多少深度线索
区域类型标记方式转换后常见后果
遮挡区(家具挡住墙角、前景物体压住地面)用半透明色块圈出被挡住的交界,旁注“几何不可见”被挡部分被补成平板或直接断开,接缝错位
镜面高光(玻璃、金属、水面反光)圈出高光范围,标注亮度峰值位置高光被烘进颜色贴图,换光源角度仍然亮着,材质通道也分不清
纯色墙、纯色地面用矩形框住,记录有无渐变和污渍缺少纹理就没有尺度参照,深度估计只能给出单层平板,墙和地容易共面
重复窗格、瓷砖、栅栏数出重复周期,框出一段完整重复单元周期被误当深度线索,模型猜出多余凹凸或错层

如果主要结构几乎都压在遮挡区或纯色区,这张图基本只能当背景板用,转换出来的几何不具备可编辑价值;如果高风险区只占角落,单图转换仍有继续核对的必要。

跑一次最小转换,查看输出的对象树、网格与材质命名

用默认参数、只放这一张原图做一次转换,输出到独立目录,先不要调参。目的不是看效果好不好,而是看 img2threejs 交付到 Three.js 工程里的内容结构。把导出的场景加载进 Three.js 页面后,在控制台遍历一遍对象树:

const stats = { meshes: 0, groups: 0, materials: new Set(), textures: new Set() };
scene.traverse((o) => {
  if (o.isMesh) {
    stats.meshes++;
    const mats = Array.isArray(o.material) ? o.material : [o.material];
    mats.forEach((m) => {
      stats.materials.add(m.type);
      if (m.map) stats.textures.add(m.map.name || m.map.uuid);
    });
  }
  if (o.isGroup) stats.groups++;
});
console.log(stats);

重点看三项。对象层级:Scene 下有几个 Group、嵌套几层,一个物体一个节点的结构后续好定位,嵌套过深会让手修时找不到对应网格。网格数量与命名:如果命名是 wall、floor、window 这类可读词,说明转换时做了语义分组;如果全是 mesh_0、mesh_1 这类序号,就只能整体处理。贴图引用方式:材质里的 map 指向外部图片文件、内嵌 data URI 还是程序化生成的 CanvasTexture,外部文件要确认路径大小写和相对位置,否则加载后是空白灰模。上面代码里贴图 name 为空时退到 uuid,uuid 每次加载都会变,不能用来判断两次输出是否一致,判断一致性要看文件路径和网格命名。

编写场景自检清单,逐项判定可用或需返工

把“看着还行”换成四项可以重复执行的检查,每一项都要留下记录:通过、不通过、不通过的原因。

检查项操作方法通过标准不通过时动作
相机视角对齐记录初始 camera.position 和 lookAt,渲染一帧后与原图标注的地平线比高度,再轻微旋转看灭点走向地平线落在画面相近高度,灭点随旋转同向移动先调相机,调不动说明几何本身有多个视角
比例尺找门高、桌面高度这类已知尺寸物体,在场景里量同一物体量级合理,单位统一(米或厘米)整体缩放模型,别逐件改
地面贴合把相机压到接近地面视角,检查物体底部没有穿地、没有悬空,贴地网格 y 值一致按组平移,记录偏移量
材质通道关掉场景光源,只保留颜色贴图渲染一张颜色贴图里没有明显高光和投影分离出高光与阴影贴图,或换材质类型

四项里相机视角和地面贴合属于几何问题,不通过基本要回到前两步找原因;比例尺和材质通道属于装配问题,通常能在 Three.js 里改。

img2threejs 把单图转成 Three.js 场景,先确认原图能给出多少深度线索

根据检查结果,决定补图、换图或进入 Three.js 手修

把检查结果分成三种情况处理。

补图:触发条件是透视单一成立、失败集中在少数遮挡区或纯色面,同时还能拿到同一场景另外一到两张不同角度的照片。工作量按需要覆盖的缺失面数量估,一个缺失墙角通常对应一次补拍加一次重新转换,不要指望补拍后完全不用手修。

换图:触发条件是原图本身不满足单相机假设,比如地平线找不到、可见面收敛方向互相矛盾、画面大面积为镜面或纯色。换图后要重新走一遍灭点标注和四类区域标注,不进入手修环节。

手修:触发条件是自检四项里只有命名混乱、材质通道或少量接缝不通过,几何与贴图大体对齐。工作量按需要改动的网格数量估,逐个替换材质、重命名、调整 y 值,改动范围控制在已有对象树内。手修不解决几何缺失,被挡住的墙角不会因为改了材质就长出来。