3D Tiles
3D Tiles 是流式传输海量 3D 数据的开放标准,适用于摄影测量采集、城市模型和地形等内容。一个 tileset 由细节逐级增加的 tile 树组成,因此查看器只需加载相机当前需要的瓦片及其细节层级。
NASA-AMMOS 的 3DTilesRendererJS 用于加载和渲染 3D Tiles,并提供 PlayCanvas 渲染器。它通过引擎的 glTF 解析器加载瓦片内容,因此瓦片也可使用引擎支持的 glTF 扩展,并支持 WebGPU 和 WebGL 2 渲染。
安装
通过 npm 安装库和引擎:
npm install 3d-tiles-renderer playcanvas
PlayCanvas 渲染器从 3d-tiles-renderer/playcanvas 导入。
渲染瓦片集
使用瓦片集 tileset.json 的 URL 创建 TilesRenderer,为其指定决定瓦片加载的相机,将根实体添加到场景,并逐帧更新:
import { TilesRenderer } from '3d-tiles-renderer/playcanvas';
const tiles = new TilesRenderer('https://example.com/tileset/tileset.json', app);
tiles.setCamera(camera.camera);
app.root.addChild(tiles.group);
// update the tiles every frame, after the camera has moved
app.on('update', () => {
tiles.update();
});
瓦片作为 container 资源加载,并在 tiles.group 下创建带渲染组件的实体。Application 包含所需的全部功能。使用 AppBase 时,需要注册 RenderComponentSystem,以及 ContainerHandler 和 TextureHandler 资源处理器。
瓦片集使用自己的坐标系定位,可以移动、旋转或缩放 tiles.group 或其父实体,将它放置到场景中。
设置
| 属性 | 说明 |
|---|---|
errorTarget | 瓦片被更高细节瓦片替换前允许的屏幕空间误差,单位为像素。值越小,加载的细节和数据越多。默认为 16。 |
lruCache.minBytesSize、lruCache.maxBytesSize | 已加载瓦片的内存预算,默认分别为 0.3 和 0.4 GiB。 |
fetchOptions | 每次请求传给 fetch 的选项,例如 mode、credentials 或 headers。 |
renderOptions | 瓦片渲染组件的选项,例如 castShadows、receiveShadows 或 layers。 |
assetOptions | 瓦片加载时使用的 container 资源选项,例如 glTF 解析器回调。 |
摄影测量瓦片通常带有较大的纹理。如果内存预算不足以容纳当前视图所需内容,瓦片会被卸载以给其他瓦片腾出空间,导致视图始终无法加载完成。应为这类瓦片集提高预算,同时考虑目标设备的内存限制。
压缩内容
包含 Draco 压缩网格或 KTX2 纹理的瓦片,需要在加载前配置引擎解码器,否则这些瓦片会加载失败:
import { basisInitialize, dracoInitialize } from 'playcanvas';
dracoInitialize({
jsUrl: 'wasm/draco/draco.wasm.js',
wasmUrl: 'wasm/draco/draco.wasm.wasm'
});
basisInitialize({
glueUrl: 'wasm/basis/basis.wasm.js',
wasmUrl: 'wasm/basis/basis.wasm.wasm',
fallbackUrl: 'wasm/basis/basis.js'
});
解码器不包含在 playcanvas npm 包中,可以在引擎仓库的 examples/assets/wasm 下找到。
定制已加载瓦片
渲染器在工作过程中会发出事件。每个瓦片加载完成后都会触发 load-model,并传入为其内容创建的实体,因此你可以修改材质。例如,摄影测量瓦片通常不受光照影响,颜色位于自发光贴图中。若希望它们参与光照并接收阴影,可以将颜色移到漫反射贴图:
tiles.on('load-model', ({ scene }) => {
for (const render of scene.findComponents('render')) {
for (const meshInstance of render.meshInstances) {
const material = meshInstance.material;
material.diffuseMap = material.emissiveMap;
material.emissiveMap = null;
material.emissive.set(0, 0, 0);
material.useLighting = true;
material.update();
}
}
});
可以通过 on 和 off,或 addEventListener 和 removeEventListener 订阅与取消订阅事件。
插件
插件用于扩展渲染器,例如进行瓦片服务身份验证,或支持更多瓦片集功能。使用 registerPlugin 注册:
tiles.registerPlugin(plugin);
位于 3d-tiles-renderer/core/plugins 的引擎无关插件可以用于 PlayCanvas 渲染器。插件也可以是提供加载期间所需钩子函数的普通对象;下方 Helsinki 示例正是用这种方式适配其瓦片集。
限制
- 仅支持 glTF、GLB 和 B3DM 瓦片内容。
- 仅支持
box和sphere包围体。只有region包围体的瓦片不会显示。 - 引擎变换采用 32 位精度,因此以距原点数百万米的地球坐标定位的瓦片集无法精确渲染。此类瓦片集必须在进入引擎前,以双精度将坐标重新定位到原点附近;Helsinki 示例通过插件实现这一点。
- 不支持对瓦片进行射线检测。