











仓库地址:https://github.com/img2threejs/img2threejs
当前版本:v1.5.0 | 许可证:Apache License 2.0 | 主要语言:Python(stdlib)+ TypeScript
文档生成时间:2026-07-28
img2threejs —— 字面含义即「image to three.js」,把一张参考图转成 Three.js 3D 模型。
img2threejs 的主维护者,最新提交与版本发布均由其完成)。一句话:给一张物体的参考图,它产出一段用 TypeScript 编写的 THREE.Group 工厂函数,用「图元 + 程序化着色器 + 生成几何体」在代码层面重建该物体,并附带运行期层级(pivot 枢轴、socket 插槽、collider 碰撞体),使结果「可被动画驱动」,而不是一个死板的静态网格。
能力要点:
object / character / hybrid;角色走解剖感知轨道;detailInventory 细节清单(光泽、倒角、螺丝、雕刻线、磨损等)受严格质量门控约束,未列全不得生成。blockout → structural → form → material → surface → lighting → interaction → optimization,自纠正至每个身份特征达标。官方自带 10 个示例:Glock-18、Classic Knife、BMX 自行车、M9 刺刀、索尼耳机、Gerber 刀、哆啦A梦屋、War-Hauler、宝箱。
该项目诞生于「text-to-3D / image-to-3D」赛道,但刻意走了一条反主流路线:
.glb。背景里还包含对「单图局限」的诚实声明:单张图无法揭示隐藏面、角色为风格化重建而非照片级,项目明确把「本图达不到所要求保真度」视为一个合法的预期结果。
img2threejs 不是一个独立服务,而是一个技能(Skill)/ 代码工具包,部署方式即「放进 AI 编码代理的 skills 目录并克隆仓库」:
# 1. 克隆到 Claude Code 的技能目录(其他代理类似,放入对应 skills 路径)
git clone https://github.com/img2threejs/img2threejs.git ~/.claude/skills/img2threejs
随后在 Claude Code 中附上/指向一张物体图片,运行斜杠命令即可:
/img2threejs Rebuild this object as a Three.js model, keep the proportions, angles, and colours.
若希望直接走命令行脚本(不经过对话代理),可从技能根目录直接运行各阶段脚本:
python3 forge/stage1_intake/probe_image.py <image>
python3 forge/stage2_spec/new_pre_spec_assessment.py "Name" --image <image> --out assessment.json
python3 forge/stage2_spec/new_sculpt_spec.py "Name" --image <image> --assessment assessment.json --out spec.json
python3 forge/stage2_spec/validate_sculpt_spec.py spec.json --strict-quality
python3 forge/stage3_build/generate_threejs_factory.py spec.json --out src/createObjectModel.ts
| 项目 | 条件 |
|---|---|
| 语言运行时 | Python 3.10+(仅用标准库,无需 pip 安装任何依赖) |
| 宿主环境 | 一个支持「视觉输入 + 浏览器/预览截图」的 AI 编码代理(Claude Code / Codex / OpenCode);若纯命令行使用,则仅需 Python 与人工看截图 |
| 网络 | 首次克隆需联网;运行阶段脚本本身不联网(无外部依赖、无 API 调用) |
| 产物运行环境 | 生成的 .ts 需 Three.js 运行环境(浏览器 + three);评估渲染需在能跑 WebGL 的浏览器中截图 |
| 磁盘/系统 | 普通桌面/开发机即可,无 GPU 硬性要求(生成是代码,不是训练) |
关键亮点:「零依赖、零安装折腾」——所有脚本是纯 Python 3.10+ 标准库实现,PNG 读写用 struct + zlib 手写,没有 PIL / numpy / Playwright,因此上下文里没有任何需要调试的第三方包。
/img2threejs ...。Fidelity / Materials / Runtime / Gates 四段,分别对应保真度约束、材质推导、运行期插槽/动画、严格质量门(--strict-quality)。Maximize likeness(投影优先路径);--cs2,且初始家族边界仅限刀(knife),手枪/步枪等若误判会被 unsupported-family 拦截;| 维度 | 选型 |
|---|---|
| 渲染/产物 | Three.js(TypeScript 编写的 Group 工厂,使用 MeshPhysicalMaterial、PBR、RoomEnvironment、EffectComposer 等) |
| 生成语言 | TypeScript(模型代码);Python 3.10+(验证/门控脚本,纯标准库) |
| 核心算法 | 程序化几何(Shape 拉伸、Lathe、Tube、曲线扫掠、实例网格)、CIEDE2000 色差、PBR 通道提取(推理而非逆渲染)、确定性噪声(周期化 value noise) |
| 门控/评估 | Python 确定性集成评估(IoU / 尺度 / 对称奇偶 / pHash / SSIM / 边缘 / 过曝 / 平坦 / 色调奇偶);VLM 作为「被门控的最后一层」 |
| 运行宿主 | AI 编码代理(Claude Code / Codex / OpenCode),利用其视觉与浏览器工具 |
| 质量保障 | 严格质量门、细节清单、CS2 专属组件契约、Divine Eye 评估框架、有界纠正循环(防无限 token 燃烧) |
img2threejs/
├── SKILL.md # 技能定义(frontmatter name/license/version=1.5.0)+ 完整流水线指令
├── README.md # 项目介绍、演示画廊、快速开始、路线图
├── CHANGELOG.md # v1.0 → v1.5.0 变更记录
├── ROADMAP.md # 版本路线图(v1.4→v2.0 四阶段长视图)
├── LICENSE # Apache-2.0
├── forge/ # ★ 核心:分阶段确定性脚本(纯 Python stdlib)
│ ├── next.py # 报告当前已解锁 pass、下一步命令、未满足的验收条件
│ ├── stage1_intake/ # intake:图像探测、细节清单、地标、相机求解、去光照
│ │ ├── probe_image.py # 纯 stdlib 读 PNG/JPEG/GIF/WEBP/BMP/TIFF 尺寸与适配性
│ │ ├── build_detail_inventory.py
│ │ ├── extract_landmarks.py
│ │ ├── solve_camera_pose.py
│ │ ├── delight_albedo.py
│ │ ├── extract_pbr_evidence.py
│ │ └── check_reference_admission.py / check_intake_correctness.py / search_specs.py ...
│ ├── stage2_spec/ # spec:分类、复杂度、质量契约、ObjectSculptSpec 编写与校验
│ │ ├── new_pre_spec_assessment.py
│ │ ├── new_sculpt_spec.py
│ │ └── validate_sculpt_spec.py # --strict-quality 拦截浅层 spec
│ ├── stage3_build/ # build:pass 状态机 + Three.js 工厂代码生成
│ │ ├── orchestrate_passes.py # status / check / sync
│ │ └── generate_threejs_factory.py # ★ 把 spec 编译成 .ts 工厂(核心代码生成器)
│ ├── stage4_review/ # review:对比图打包、Divine Eye、CS2 审查、纠正循环
│ │ ├── make_comparison_sheet.py
│ │ ├── append_review.py
│ │ ├── divine_eye.py # 确定性多信号集成(硬门 + 软门 + 自不确定性)
│ │ ├── vlm_gate.py # 经门控、校准、交叉验证的 VLM 最后层
│ │ ├── cs2_review.py
│ │ ├── diagnose_render.py / diagnose_render_multi_angle.py
│ │ ├── correction_loop.py
│ │ └── check_part_coverage.py
│ └── _shared/ # 内部公共 helper(如 feature_acceptance_policy.py)
├── grimoire/ # 「魔法书」:各门控应用的详细评分标准(rubric)
│ ├── intake/ (validation_rubric, detail_inventory, quality_contract, surface_topology, image_analysis, cs2_texture_acquisition)
│ ├── build/ (geometry_patterns, threejs_texture_reference, cs2_finishes)
│ ├── character/ (reconstruction, likeness_maximization)
│ ├── readiness/ (action_rigging, joint_attachment)
│ ├── feedback/ (render_capture, shading_realism)
│ ├── review/ (self_correction)
│ └── glossary/ (3d_vocabulary)
├── docs/ # ARCHITECTURE.md / TOKEN_COST.md / UPGRADE_PLAN.md / cs2/review-gates.md
├── scripts/ # 顶层辅助脚本
├── skills/ # CS2 等子技能
└── assets/ # logo 等
最关键的两个文件:
forge/stage3_build/generate_threejs_factory.py —— 真正的「代码生成器」,把 ObjectSculptSpec(JSON)编译成可运行的 Three.js .ts 工厂。forge/stage1_intake/probe_image.py —— 展示「零依赖」哲学的范例,仅用 struct/zlib 解析多种图像格式。分阶段「雕刻」:脚本给每个阶段设门,代理的「视觉」是唯一能批准一个 pass 的东西。
flowchart TD A[参考图] --> B[探测 + 适配性门] B --> C[Pre-Spec 评估:分类 / 复杂度 / 质量契约] C --> D[编写 ObjectSculptSpec:组件 / 材质 / 插槽] D --> E{校验 + 严格质量} E -- 太浅 --> D E -- 通过 --> F[锁定的构建 pass] F --> G[仅生成当前 pass 的 Three.js 工厂] G --> H[浏览器渲染并截图] H --> I[打包一张「参考 vs 渲染」对比图] I --> J{代理视觉评审} J -- 低于阈值 --> K[自纠正:refine-spec / refine-code] K --> F J -- 通过 --> L{还有 pass?} L -- 是 --> F L -- 否 --> M[可动画的 Three.js 模型]
构建顺序固定,后一个 pass 只有在前一个被评审接受后才解锁:
blockout → structural-pass → form-refinement → material-pass → surface-pass → lighting-pass → interaction-pass → optimization-pass
每个 pass 有独立验收标准,必须同时满足「真实渲染 + 对比图 + 代理视觉分 ≥ 阈值 + 每个身份特征 ≥ 其自身阈值」才能标为 continue。
下面给出最具代表性的片段(完整源码见仓库,已逐字核对)。
generate_threejs_factory.pyVALID_PRIMITIVES = {
"box", "sphere", "ellipsoid", "cylinder", "cone", "capsule",
"torus", "tube", "lathe", "extrude", "ground-blade",
"curve-sweep", "plane-card", "instanced-cluster",
}
def geometry_for(primitive, component=None):
"""把 spec 里的基元名映射成 Three.js 几何体构造调用。"""
if primitive == "box":
return "new THREE.BoxGeometry(1, 1, 1, 12, 12, 12)"
if primitive in {"sphere", "ellipsoid"}:
return "new THREE.SphereGeometry(0.5, 64, 40)"
if primitive == "cylinder":
return "new THREE.CylinderGeometry(0.5, 0.5, 1, 48, 16)"
# ... lathe / tube / curve-sweep / instanced-cluster 等分支
if primitive == "ground-blade":
spec = descriptor.get("bladeSpec") or _DEFAULT_BLADE_SPEC
return f"buildGroundBladeGeometry({json_literal(spec)})"
raise GeometryNotImplementedError(primitive) # 绝不静默退化为 box!
设计要点:早先「未知基元静默退化为 box」曾导致刀刃被渲染成方块却毫无提示,因此引入
GeometryNotImplementedError,强制在生成前报错。
generate() 的骨架generate(spec, pass_id) 做三件事:① 按当前 pass 过滤组件(filter_components_for_pass,只生成已解锁层级,避免每轮重读整模型);② 仅 emit 本 pass 实际用到的几何 helper 函数(防止 noUnusedLocals 构建失败);③ 拼出 create<Name>Model(options) 工厂,并附带 create<Name>LookDevLights / create<Name>Environment / frame<Name>Camera / create<Name>PresentationComposer / configure<Name>Renderer / create<Name>InspectControls 等配套函数。
输出的工厂关键结构(节选):
export function createObjectNameModel(options: ProceduralModelOptions = {}): THREE.Group {
const root = new THREE.Group();
root.name = "ObjectName";
root.userData.reconstructionEvidence = { itemFamily, subtype, route, exactnessTier, ... };
const materialMap: Record<string, THREE.Material> = {};
// ... 由 spec.materials 生成 MeshPhysicalMaterial(含 clearcoat/iridescence/
// transmission/anisotropy 等 PBR 通道 + 程序化贴图集)...
const nodes: Record<string, THREE.Object3D> = { root };
const meshes: Record<string, THREE.Mesh> = {};
const sockets: Record<string, THREE.Object3D> = {};
const colliders: Record<string, unknown> = {};
const destructionGroups: Record<string, THREE.Object3D[]> = {};
// ... 按 componentTree 递归建立 pivot→mesh,attachment 用 Cylinder 连接
// (endpoint 由 localStart/localEnd 决定,杜绝悬空部件)...
// 重复系统(辐条/螺钉/齿)用单个 InstancedMesh 实现,一次 draw call
// ...
root.userData.sculptRuntime = { nodes, meshes, sockets, colliders, destructionGroups };
return root;
}
probe_image.py不依赖任何第三方库,用 struct 直接解析文件头字节:
def png_size(data: bytes) -> tuple[int, int] | None:
if data.startswith(b"\x89PNG\r\n\x1a\n") and len(data) >= 24:
return struct.unpack(">II", data[16:24]) # PNG: IHDR 宽高在大端 8 字节
return None
def jpeg_size(data: bytes) -> tuple[int, int] | None:
if not data.startswith(b"\xff\xd8"):
return None
# 遍历 JPEG 标记段,找 SOF0/SOF2... 读取宽高
...
def probe(path: Path) -> dict:
data = path.read_bytes()
image_type = detect_image_type(data)
size = detect_size(data) # png/jpeg/gif/webp/bmp/tiff 全部自制解析
warnings = []
if size and (size[0] < 512 or size[1] < 512):
warnings.append("low resolution; small geometry/material details may be unreliable")
return {"path":..., "type":..., "width":..., "height":...,
"technicalSuitability": "conditional" if warnings else "pass",
"warnings": warnings,
"note": "This is only technical image probing. Semantic object suitability still requires visual inspection."}
--strict-quality 在生成一行 Three.js 之前就拦住浅层 spec;unsupported-family 拒绝——覆盖面有限。probe),避免盲目信任视觉模型。request-input,绝不让代理无限烧 token。check_part_coverage.py 是整套体系里唯一对「结构」打分的门——它能抓出「spec 写了但没建」「两个组件熔到一个网格」;作者明确说它的局限(只证明你建了 spec 里的东西,不证明 spec 本身足够)也要如实声明。cs2-intake.json 交接契约(含 6 种状态、原子写入、保留未知字段)把「证据可追溯」落到数据格式。img2threejs 是一个定位精准、工程取向鲜明的开源项目:它不追求「一张图变出照片级网格」,而是用「代码即资产」的思路,把单张参考图变成可版本化、可动画、可评审的 Three.js 程序化模型。其最大价值不在某个炫技算法,而在架构哲学——把昂贵的模型判断力与廉价的确定性脚本严格分层,并用零依赖 Python 把一切机械工作挡在 token 上下文之外。配合严密的质量门控、Divine Eye 评估、有界纠正循环与「透明可调试」原则,它特别适合「硬表面道具 / 游戏资产 / 可动可破坏物体」这类场景,并已向角色、生物、CS2 武器、环境、乃至 v2.0「程序化世界」路线演进。
局限同样清晰:单图先天信息不足、强依赖 AI 代理生态、CS2 家族覆盖窄、复杂有机体仍偏风格化。理解这些边界,是使用该项目前必须建立的预期。
README.md、docs/ARCHITECTURE.md、SKILL.md、ROADMAP.md、CHANGELOG.mdforge/stage3_build/generate_threejs_factory.py、forge/stage1_intake/probe_image.pydocs/cs2/review-gates.md、forge/stage4_review/divine_eye.py、forge/stage4_review/correction_loop.py注:本文档内容基于对该仓库 README、ARCHITECTURE、SKILL.md 及两份核心源码的逐字核对整理而成(核对时间 2026-07-28,仓库版本 v1.5.0)。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。