关于 3D AR Studio
3D AR Studio 是可嵌入网页的增强现实工作室,可在真实空间中放置和布置多个 3D 模型,面向网页开发者和 Agent。它支持场景链接分享、协作房间,并附带用于模型生成与场景编排的 MCP 服务。
主要功能
- 01放置和布置多个 3D 模型
- 02根据文本提示生成模型
- 03通过链接和二维码分享场景
- 04同步协作房间
- 05嵌入为网页组件或页面
适用场景
- 01在网站中加入 AR 模型工作室
- 02编排并分享房间布局
- 03让 Agent 生成模型并创建 AR 链接
- 04生成独立的 HTML AR 页面
MCP 相关
独立的 3d-ar-studio-mcp 服务提供模型生成、查询生成状态、搜索模型目录、编排场景、导出 AR 链接和创建 HTML 页面等工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y 3d-ar-studio-mcpAR_STUDIO_PAGE_URLThe page that composed AR scenes link to. Defaults to the hosted demo; set it to your own deployment of the studio.AR_STUDIO_ASSETSCatalogue URL that search_models searches. Defaults to the free CC0 model library.AR_STUDIO_MCP_ENDPOINTMCP endpoint used for text-to-3D generation. Defaults to the free, keyless three.ws 3D Studio connector.AR_STUDIO_ORIGINOrigin serving the hosted 'View in your space' launcher and the 3D viewer. Defaults to https://three.ws.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
6收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| kind | enum | 否 | model(道具、默认值)、avatar(已绑定骨骼的角色)或 mesh(先优化提示词,再按艺术指导生成)。model | avatar | mesh |
| tier | enum | 否 | 细节级别。级别越高,生成越慢。draft | standard | high |
| prompt | string | 是 | 要建模的单个物体或角色。 |
详细介绍
3D AR Studio
将完整的增强现实工作室嵌入任意网页。
通过摄像头,在真实房间里放置任意数量的 3D 模型,描述一个新模型并看着它出现,手动布置所有内容,然后将整个场景分享为链接、二维码,或分享一个其他人可以与你一起搭建的实时房间。
<script type="module" src="https://unpkg.com/3d-ar-studio/dist/ar-studio.min.js"></script>
<ar-studio></ar-studio>
这就是一个可用的 AR 工作室。无需构建步骤、API 密钥或账户。它已接入免费的数百个公有领域模型库,以及免费的免密钥文本转 3D 通道;准备好后,只需一个选项即可连接你自己的目录。
为什么要做这个
每个可嵌入网页的 AR 工具都只会放置一个模型,然后交给原生查看器,导致会话结束。而这个工具会将整个场景保留在你的页面中:
- 多个模型,同一个房间。 在同一个实时摄像头视图中,按需放置、拖动、捏合缩放、扭转旋转并复制任意数量的模型。
- 无需离开摄像头即可生成。 在工具栏中输入“一盏黄铜台灯”。生成过程会在实时视图背后运行,完成后模型便会出现在房间里。
- 在支持的设备上使用真正的 WebXR。 始终待命的命中测试准星、每个已放置模型对应一个
XRAnchor、真实世界光照估算,以及深度遮挡,让模型能隐藏在家具后面。 - 其他设备上使用真正的 ARKit 和 ARCore。 iPhone 不支持 WebXR,因此点按 放置到你的空间 会真正打开 Apple 的 AR Quick Look:具备真实的平面检测、真实比例、真实遮挡,以及系统自带的“以 AR 查看”弹窗。模型会在设备上转换为 USDZ(通过 three.js 的
USDZExporter进行真实转换,无需服务器参与);由于导出的是场景中已有的模型副本,因此模型会保持你捏合调整后的大小和原有姿态,并且立在地面上,而不会悬在它建模时恰好设定的高度。没有 WebXR 的 Android 设备会使用 Scene Viewer。桌面设备会显示网格预览,并通过二维码交接到手机。 - 场景就是链接。 模型、位置、旋转和缩放都能通过 URL 往返传递。在笔记本电脑上编排,扫描二维码后,手机上会原样重新打开。
- 一起实时搭建。 打开一个房间,分享一个六位字符代码,所有新增和移动操作都会同步给房间中的每个人。
- 角色会真正动起来。 对于没有内置动画的任何类人 GLB,都会将待机动画片段重定向到其自身骨架。不限制绑定类型,也不会出现 T 姿势。
- Agent 可以驱动它。 内置的 MCP 服务让 Claude、ChatGPT 或你自己的 Agent 生成模型、编排布局,并向用户提供一个可在其房间中打开的链接。
渲染层级、锚点生命周期、重定向管线、场景格式和共享房间协议均取自 three.ws 上投入生产的 AR 功能,并经过通用化处理,可在你的网站上与自己的模型配合使用。
安装
npm i 3d-ar-studio three
three 是对等依赖,因此你可以只保留一份并选择版本。CDN 包(dist/ar-studio.min.js)内含 three.js,无需其他依赖。
import { createArStudio } from '3d-ar-studio'
const studio = createArStudio('#stage', {
branding: { title: 'Acme AR', accent: '#00b894' },
})
studio.on('add', ({ placement }) => console.log('placed', placement.title))
工作室会绝对定位并填满其宿主元素,因此请为宿主设置高度(任何具有实际高度的定位框都可以;没有高度的 <div> 会采用合理的 70vh 默认值,而不会渲染成不可见)。
搭建可部署的页面
npx 3d-ar-studio create my-ar-site # a folder you can publish as-is
cd my-ar-site
npx 3d-ar-studio dev # look at it locally
npx 3d-ar-studio deploy # push it and turn on GitHub Pages
deploy 会在运行每条 git 和 gh 命令前先打印出来。它需要
git 和 GitHub CLI;如果缺少它们,它会告诉你三个手动步骤,而不是悄无声息地失败。
模板:static(单个 HTML 文件,无需构建)、vite、react。
3d-ar-studio 和 ar-studio 都会运行 CLI。MCP 服务是独立软件包中的单独二进制文件,因此 npx 3d-ar-studio-mcp 可以正常解析:请参阅
MCP 服务。
使用自己的模型
托盘默认从 three.ws 加载内容:数百个公有领域(CC0)道具,可免费用于商业用途,并通过开放 CORS 提供服务。使用 assets 选项即可换成自己的内容。
任意位置的 JSON 文件。 无需调整格式即可读取五种常见结构:
createArStudio(el, { assets: 'https://cdn.acme.com/models.json' })
// Any of these work:
[ { "url": "https://cdn.acme.com/chair.glb", "name": "Aero chair" } ]
{ "items": [ … ] }
{ "objects": [ … ] } // three.ws object library
{ "creations": [ … ] } // three.ws forge gallery
{ "models": [ … ] }
对于每个条目,模型 URL 会取自首个存在的 src、url、glb、glb_url、
glbUrl、file 或 model;标签取自 title、label、name 或 prompt;缩略图取自 poster、thumb、thumbnail、image 或 preview_image_url。任何非 https(或站点相对)URL 都会被丢弃,不会传给加载器。
在代码中维护的列表:
import { staticSource } from '3d-ar-studio/sources'
createArStudio(el, {
assets: staticSource({
label: 'Our furniture',
items: [{ src: 'https://cdn.acme.com/chair.glb', title: 'Aero chair', poster: '…' }],
}),
})
同时显示多个标签页,并按你指定的顺序排列:
createArStudio(el, { assets: ['recent', myCatalogue, 'objects', 'link'] })
内置键:'three.ws'(默认集合)、'recent'、'objects'、'community'、'link'。
其他任意来源。 来源是一个带有 list() 的对象:
createArStudio(el, {
assets: {
id: 'search',
label: 'Search',
searchable: true,
async list() {
const rows = await fetch('/api/models').then((r) => r.json())
return rows.map((m) => ({ src: m.glb, title: m.name, poster: m.thumb }))
},
},
})
list() 抛出异常也没关系:托盘会显示精心设计的错误状态,并提供“重试”按钮。
用户也可以重新指定来源,无需改动你的代码:在页面 URL 中添加 ?assets=https://…/manifest.json。只接受 https URL,并且每个模型来源在交给加载器之前都会重新验证,因此恶意链接可以添加目录,但无法将 javascript: 或 data: 模型偷偷带入场景。设置 allowUrlOverride: false 即可关闭此功能。
CORS
模型由浏览器加载,因此托管 .glb 文件的主机必须允许跨源请求(access-control-allow-origin)。模型加载失败时,几乎总是这个原因;工作室会在状态栏中说明,而不是悄无声息地失败。
选项
| 选项 | 默认值 | 作用 |
|---|---|---|
assets | 'three.ws' | 模型来源:预设键、清单 URL、来源对象或它们的数组。 |
generate | enabled | { enabled, endpoint, kind, tier, timeoutMs, pollMs }。endpoint 可以是任何提供兼容生成工具的 MCP 服务。 |
rooms | enabled | { enabled, server }。将 server 指向你自己的 Colyseus 部署,即可自行托管共享房间。 |
animations | three.ws idle clip | { enabled, manifestUrl, clip }。将此动画片段重定向到未自带动画的人形模型上。 |
lighting | 'studio' HDRI | { preset, urls }。preset: null 仅使用程序化光照,不下载 HDRI。 |
branding | : | { title, accent, backHref, backLabel }。 |
shareBaseUrl | 此页面 | 分享链接和 QR 码的指向位置。 |
origin | https://three.ws | 托管的“在你的空间中查看”启动器和查看器链接的源。 |
persistKey | 'ar-studio:scene:v1' | 保存场景的 localStorage 键。更改此项即可在同一源上运行两个工作室。 |
persist | true | 加载时恢复上次的场景。 |
maxPlacements | 20 | 同时放置的模型数量上限,确保低端手机仍可交互。 |
fullscreen | 自动 | 以固定的全屏图层渲染。仅当挂载到 document.body 时,默认值才为 true。 |
allowUrlOverride | true | 接受托管页面 URL 中的 ?assets=、?src=、?room= 和 ?forge= 参数。 |
onEvent | null | 每发生一项重要操作时,都会以 (event, detail) 为参数调用。可将其接入你的分析工具。 |
URL 参数
| 参数 | 效果 |
|---|---|
?assets=<https url> | 替换目录。 |
?src=<glb>&title=<name> | 将模型加载到场景中。可重复使用。 |
#s=<payload> | 重新打开完整布局,包括变换信息。由 shareUrl() 写入。 |
?room=<code> | 加入共享房间。 |
?forge=<prompt> | 加载时开始生成。 |
方法
await studio.addModel({ src, title }) // place a model
studio.clear() // remove everything; returns what was there
studio.getScene() // [{ src, title, x, z, yaw, scale }]
await studio.setScene(items) // replace the arrangement
studio.shareUrl() // a link that reopens it exactly
await studio.generate('a brass desk lamp') // text to 3D, into the room
studio.viewInYourSpace(src, title) // open the hosted launch page for one model
await studio.startCamera() // needs a user gesture on iOS
await studio.enterAR() // best AR path for this device
studio.openArSheet() // the "Place in your space" hand-off sheet
studio.closeArSheet()
await studio.placeInYourSpace() // straight to the native viewer, no sheet
await studio.toggleImmersive() // enter or leave WebXR specifically
await studio.openRoom() // returns the room code
studio.destroy() // releases camera, socket and GPU context
事件
studio.on(name, fn) 会返回一个取消订阅函数。同一事件也会在已挂载的元素上触发
ar-studio:<name> DOM 事件。
| 事件 | 详情 |
|---|---|
add | { placement, remote } |
remove | { src, title } |
select | { placement }(取消选择时为 null) |
clear | { items } |
generate | { model } |
generate-error | { error, prompt } |
camera | { active } |
xr | { active } |
native-ar | { src, title, viewer },其中 viewer 为 quicklook、sceneviewer 或 none |
native-ar-error | { error, src } |
ar-sheet | { open },在交接面板打开或关闭时触发 |
room | { status, code } |
share | { url } |
Web 组件
<ar-studio
assets="https://cdn.acme.com/models.json"
title="Acme AR"
accent="#00b894"
generate="true"
rooms="true"
></ar-studio>
element.studio 是当前实例。导入 3d-ar-studio/auto(CDN 包所做的操作)会自动注册该元素。
键盘与无障碍
每个控件都是真正的按钮,并带有无障碍名称;来源选项卡实现了完整的 ARIA tablist 规范;每个对话框都会接收并归还焦点。
| 按键 | 操作 |
|---|---|
| 方向键 | 相对于摄像头轻推选中的模型。按住 Shift 可进行微调。 |
R | 旋转 45°。 |
D | 复制。 |
| Delete / Backspace | 移除,并在状态栏中提供撤销操作。 |
| Escape | 关闭打开的面板,或取消选择。 |
prefers-reduced-motion 会移除入场动画和所有过渡效果。
MCP 服务
npx 3d-ar-studio-mcp
{
"mcpServers": {
"3d-ar-studio": {
"command": "npx",
"args": ["-y", "3d-ar-studio-mcp"]
}
}
}
无需 API 密钥。所有工具均免费且无需密钥。
| 工具 | 功能 |
|---|---|
generate_3d_model | 将文本提示词转换为带纹理的 GLB。返回模型以及可在 AR 中打开模型的链接。 |
check_generation | 获取首次调用返回时仍在渲染的生成结果。 |
search_models | 按名称、类别和标签搜索免费的 CC0 库(或你配置的任意目录)。 |
compose_ar_scene | 将多个模型编排到同一场景中,并返回一个可精确还原该场景的链接。 |
export_ar | 将任意 GLB URL 转换为适配设备的“在你的空间中查看”链接。 |
create_ar_page | 生成完整、独立的 HTML 页面,其中嵌入工作室,可直接提交。 |
| 环境变量 | 默认值 | 更改内容 |
|---|---|---|
AR_STUDIO_PAGE_URL | 托管演示页面 | compose_ar_scene 链接到的页面。将其设置为你自己的部署地址。 |
AR_STUDIO_ASSETS | 免费的 CC0 库 | search_models 搜索的目录。 |
AR_STUDIO_MCP_ENDPOINT | three.ws 3D Studio | 用于生成的 MCP 端点。 |
AR_STUDIO_ORIGIN | https://three.ws | 托管的 AR 启动链接和查看器链接的来源地址。 |
会话示例如下:
> Put a mid-century lamp and a potted fern in my living room.
generate_3d_model { prompt: "a brass mid-century desk lamp" } → lamp.glb
search_models { query: "potted plant" } → fern.glb
compose_ar_scene { models: [{ src: lamp.glb, x: 0, z: -1.4 },
{ src: fern.glb, x: 0.9, z: -1.2 }] }
→ one link; open it on a phone and both objects stand in the room.
设备支持
| 设备 | 路径 | 效果 |
|---|---|---|
| Android Chrome | WebXR immersive-ar | 将整个场景呈现在房间中:通过命中测试放置、为每个模型设置锚点、估算光照、进行深度遮挡。 |
| iOS Safari | AR Quick Look | 一次查看一个模型,使用 Apple 自带的查看器,并支持真实的 ARKit 跟踪、比例和遮挡。模型会在设备上转换为 USDZ。通过陀螺仪实现世界锁定的摄像头透视效果,可在页面内与之组合呈现多模型场景。 |
| 不支持 WebXR 的 Android 设备 | Scene Viewer | 一次通过 ARCore 查看一个模型;若缺少 ARCore,则回退到浏览器。 |
| 桌面设备 | 预览 | 网格地面、拖动环视、通过 QR 码转交到手机。 |
| 头显 | WebXR | 与 Android Chrome 相同。 |
顶部栏中的 AR 按钮始终选择设备支持的最佳路径,显示清晰标签,不会误导用户,并会作用于选中的模型(或最近放置的模型)。
摄像头和 WebXR 都需要安全上下文:https:// 或 localhost。
将一个模型放进某人的真实房间
在支持 WebXR 的设备上,AR 按钮会直接进入沉浸式会话。在其他设备上,它会打开交接面板:显示要放置的模型;如果场景中有多个模型,则提供选择器;并提供一个主按钮,用于打开设备自带的 AR 查看器。
该面板的存在有一个特定原因。如果你要基于此包构建自己的 UI,值得了解这一点:
只有在页面仍保留触发操作的用户手势时,iOS 才会打开 AR Quick Look。 将 GLB 转换为 USDZ 需要一两秒。如果在点击处理程序中启动转换,那么等到点击
<a rel="ar">时,用户手势就已失效,Safari 会悄无声息地拒绝操作,按钮看起来就像坏了一样。这是 iPhone 上“在 AR 中查看”按钮毫无反应最常见的原因。
紧接着还有第二个陷阱,而且更棘手,因为失败看起来像是成功:
Safari 根据 URL 的文件扩展名判断它是否为 AR 资源。
blob:URL 没有路径,因此也没有扩展名。将它交给<a rel="ar">,但不提供文件名,Safari 仍会打开 Quick Look,不过会将其作为通用 3D 预览:查看器会进入对象模式,且无法使用 AR。在锚点上设置download="something.usdz",就能为 Safari 提供它用于判断的文件名,Quick Look 也会进入 AR 模式。openQuickLook()会替你完成这一操作。
因此,该包将准备和打开分开处理,绝不会在一次点击中同时完成:
import { prepareNativeAr, isQuickLookReady } from '3d-ar-studio';
// Ahead of the tap: convert, cache, and keep the result.
const handoff = await prepareNativeAr({
src: 'https://example.com/chair.glb',
title: 'Chair',
key: '[email protected]', // cache identity; include the scale if you bake one in
});
// Inside the tap, synchronously. No await between the click and open().
button.addEventListener('click', () => handoff?.open());
在没有原生 AR 查看器的设备上,prepareNativeAr 会解析为 null;在 USDZ 已准备好、可通过 blob: 打开的 iOS 设备上,会解析为 { viewer: 'quicklook' };在无需转换任何内容的 Android 设备上,则会解析为 { viewer: 'sceneviewer' }。转换结果会被缓存(同时最多缓存四项,采用最近最少使用策略;淘汰时会撤销对象 URL);你可以通过 isQuickLookReady(key)、
releaseQuickLook(key) 和 clearQuickLookCache() 自行管理缓存。
工作室会在后台预热按钮将要发送的模型对应的缓存,因此当天第二次点击时即可立即打开。placeInYourSpace() 仍然可用,也仍会在一次调用中完成这两步:如果 USDZ 已缓存,或者你从自己已准备好的按钮调用它,就可以使用该方法。
从实时场景而非重新获取 GLB 来导出,也是有意为之:无需再次下载,也无需再次进行 CORS 往返,而且用户看到的姿势和尺寸会保持不变。如果你想在自己的 three.js 场景中使用该功能,也可以使用导出的 objectToUsdzBlob(object3D)。
为什么模型会悬在空中,而不是落在地面上
第三个陷阱,也是前两个问题都解决后仍然存在的问题:
AR Quick Look 会将场景的 ORIGIN 锚定到它检测到的平面上,而不会检查几何体。 以边界框中心为基准创作的 GLB 会有一半埋在地里;以远处场景原点为基准创作的模型,则会按照建模时的高度,漂浮在房间里的某个位置。这两种情况看起来都像跟踪失效,而且任何锚定属性都无法修复:必须移动内容。
因此,本软件包导出的所有内容在写入前,都会将模型放置在 y = 0 上,并让其占地范围以原点为中心。如果你想对自己的场景进行同样的处理,可以使用导出的 groundOnFloor()。
还有两个较小的问题也一并处理了:
USDZExporter会遍历scene.children并写入每个节点的局部矩阵,因此你交给它的对象变换根本不会写入。若在根节点上设置缩放,导出的文件会保持原始大小,而且不会发出警告。usdzExportRoot()会将内容包装在一个恒等根节点和一个Model阶段节点中,本软件包应用的所有放置变换都会施加到阶段节点上,而该节点确实会写入文件。
USDZ 使用米制单位(
metersPerUnit = 1)。以厘米为单位创作的 75 cm 道具,导入后会高达 75 m,任何室内 ARKit 检测到的平面都无法容纳它,因此模型会在用户周围漂移。将{ fit: true }传给sceneToUsdzBlob()(glbUrlToUsdzBlob()已经会这样做),即可直接将从网络加载的模型规范化。任何尺寸已在可信现实尺寸的 2 倍范围内的模型,都会保持创作时的原样。
最后,还有一个最像跟踪失效的问题:
Quick Look 要等 ARKit 找到足以容纳模型的平面后,才会放置模型。 在此之前,模型会与相机对齐并随手机移动。模型尺寸超过一定范围后,普通房间里就不会有足够大的平面,因此它永远不会落地。所有导出内容都会通过
clampToPlaceableSize()限制在MAX_AR_FOOTPRINT_M(2.5 m)和MAX_AR_HEIGHT_M(2.5 m)以内。这只是上限,并非规范化处理:家具、人物和道具都会保持原样。
相机一次只能供一个客户端使用
进入设备的 AR 查看器时,工作室会释放其 getUserMedia 直通流,返回后再重新启动。如果让页面的视频流继续运行,ARKit 启动时就会发现摄像头已被另一个进程占用:模型会出现,但世界跟踪和平面检测始终无法收敛,因此模型会随着手机漂移,而不是稳定下来。如果你要从自己的相机 UI 控制交接,请在调用 open() 前停止所有轨道。
直通模式本质上是在视频流上叠加陀螺仪效果:画面会随你转动,仅此而已。它没有平面检测或位置跟踪,因此永远无法让模型固定在真实地面的某个位置上。在 iOS 上,这正是 Quick Look 的用途,工作室的状态栏也会对此作出说明。
开发
npm install
npm test # 75 unit tests, no browser needed
npm run build # dist/ bundles
npm run build:site # docs/ (the GitHub Pages site)
npm run test:browser # 35 end-to-end checks in a real browser (needs Playwright)
npm run inspect # MCP Inspector against the local server
已发布的网站提交在 docs/ 下,并由 GitHub Pages 从 main 分支提供服务。没有 CI 工作流:npm run build && npm run build:site,然后提交并推送。
许可与致谢
Apache-2.0。
此软件包包含 three.js(MIT)和 colyseus.js(MIT)。默认模型库采用来自 Poly Haven 的 CC0 内容,默认的生成和动画通道由 three.ws 托管。它们都不是必需的:每一项都可以替换为你指定的 URL。
Star 历史
支持该项目
如果 3D-AR-Studio 为你节省了时间,请在 GitHub 上为它点星。星标能帮助其他开发者和 AI Agent 找到值得信赖的代码仓库,而且只需点击一下。
认识可能会用到它的人吗?在 X 上发布 · 在 Bluesky 上分享 · 在 LinkedIn 上分享 · 提交到 Hacker News · 在 Reddit 上分享
同样为 AI Agent 打造
编码 Agent 和大模型工具可以直接读取此代码仓库:AGENTS.md、llms.txt、llms-full.txt。将 https://github.com/nirholas/3D-AR-Studio 提供给 Agent,它就能获取所需的上下文。
作者的更多项目
- nirholas 的所有代码仓库:完整目录,按主题分组
- three.ws:面向 3D AI Agent 的平台,提供 Solana 钱包、技能市场和 x402 支付
- 有问题或想法?提交 issue或发起讨论
贡献者
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。