找回密码
 立即注册
首页 资源区 代码 JSAPIThree 加载 3D Tiles 学习笔记:大规模三维场景渲 ...

JSAPIThree 加载 3D Tiles 学习笔记:大规模三维场景渲染

呈步 昨天 16:35
在实际项目中,我们经常需要加载大规模的三维场景数据,比如城市建筑模型、地形数据等。3D Tiles 是 Cesium 提出的开放标准,用于高效地流式传输和渲染大量 3D 内容。今天就来学习一下如何在 mapvthree 中使用 3D Tiles。
了解 3D Tiles

3D Tiles 是一种用于流式传输和渲染大量 3D 内容的开放标准,具有以下特点:

  • 层次化结构:使用空间层次结构组织数据,支持细节层次(LOD)
  • 流式传输:按需加载,只加载视野内的数据
  • 高性能:通过剔除、LOD 等技术优化渲染性能
  • 标准化:开放标准,支持多种数据格式
我的理解:3D Tiles 就像是一个智能的三维场景管理系统,能够根据相机位置和视角,自动决定加载哪些数据,以及加载到哪个细节层次。
第一步:从 URL 加载 3D Tiles

最简单的方式是从 URL 加载 3D Tiles 数据。
基本使用
  1. import * as mapvthree from '@baidumap/mapv-three';
  2. const container = document.getElementById('container');
  3. const engine = new mapvthree.Engine(container, {
  4.     map: {
  5.         center: [105.931, 29.349, 280],
  6.         range: 2000,
  7.         pitch: 75,
  8.         provider: null,
  9.     },
  10. });
  11. // 从 URL 加载 3D Tiles
  12. const tileset = engine.add(new mapvthree.Default3DTiles({
  13.     url: 'data/3dtiles/tileset.json',
  14. }));
复制代码
我的发现:只需要提供 tileset.json 的 URL,引擎会自动加载整个 3D Tiles 数据集。
我的理解

  • tileset.json 是 3D Tiles 的入口文件,定义了整个数据集的层次结构
  • 引擎会根据相机位置自动加载需要的瓦片
  • 支持多种 3D Tiles 格式(b3dm、i3dm、pnts 等)
第二步:从 Cesium Ion 加载

如果数据存储在 Cesium Ion 上,可以使用 asset ID 加载。
使用 fromAssetId
  1. // 从 Cesium Ion asset ID 加载
  2. const tileset = await mapvthree.Default3DTiles.fromAssetId('assetId', {
  3.     errorTarget: 16,
  4. });
  5. engine.add(tileset);
复制代码
我的发现:fromAssetId 是静态方法,返回一个 Promise,需要等待加载完成。
我的理解

  • 需要先配置 Cesium Ion AccessToken
  • asset ID 是 Cesium Ion 中资源的唯一标识
  • 可以使用配置参数来优化加载和渲染
第三步:性能优化配置

3D Tiles 提供了很多性能优化参数,合理配置可以显著提升渲染性能。
errorTarget:屏幕空间误差

errorTarget 控制屏幕空间误差目标值,影响 LOD 的切换时机。
  1. const tileset = engine.add(new mapvthree.Default3DTiles({
  2.     url: 'data/3dtiles/tileset.json',
  3.     errorTarget: 16, // 默认值,数值越小,细节越多,性能开销越大
  4. }));
复制代码
我的理解

  • 数值越小,显示的细节越多,但性能开销越大
  • 数值越大,显示的细节越少,但性能更好
  • 需要根据场景和性能要求调整
cullRequestsWhileMoving:移动时剔除

cullRequestsWhileMoving 控制相机移动时是否剔除请求,可以提升移动时的性能。
  1. const tileset = engine.add(new mapvthree.Default3DTiles({
  2.     url: 'data/3dtiles/tileset.json',
  3.     cullRequestsWhileMoving: true, // 移动时剔除请求,提升性能
  4. }));
复制代码
我的发现:开启后,相机快速移动时不会加载新瓦片,等移动停止后再加载,可以避免不必要的网络请求。
cullWithChildrenBounds:使用子节点边界剔除

cullWithChildrenBounds 控制是否使用子节点边界进行剔除,可以更精确地判断是否需要加载子节点。
  1. const tileset = engine.add(new mapvthree.Default3DTiles({
  2.     url: 'data/3dtiles/tileset.json',
  3.     cullWithChildrenBounds: true, // 使用子节点边界进行剔除
  4. }));
复制代码
我的理解:开启后,会使用子节点的边界框来判断是否需要加载,可以更精确地剔除不可见的节点。
loadSiblings:加载兄弟节点

loadSiblings 控制是否加载兄弟节点,可以预加载相邻的瓦片。
  1. const tileset = engine.add(new mapvthree.Default3DTiles({
  2.     url: 'data/3dtiles/tileset.json',
  3.     loadSiblings: true, // 加载兄弟节点,预加载相邻瓦片
  4. }));
复制代码
我的发现:开启后,会预加载相邻的瓦片,当相机移动到相邻区域时,数据已经准备好了,可以提升用户体验。
其他性能参数

还有一些高级性能参数:
  1. const tileset = engine.add(new mapvthree.Default3DTiles({
  2.     url: 'data/3dtiles/tileset.json',
  3.     // 缓存配置
  4.     cacheBytes: 512 * 1024 * 1024, // 缓存大小(字节)
  5.    
  6.     // 动态屏幕空间误差
  7.     dynamicScreenSpaceError: true,
  8.     dynamicScreenSpaceErrorDensity: 0.00278,
  9.     dynamicScreenSpaceErrorHeightFalloff: 0.25,
  10.    
  11.     // 注视点渲染(Foveated Rendering)
  12.     foveatedScreenSpaceError: true,
  13.     foveatedConeSize: 0.1,
  14.     foveatedMinimumScreenSpaceErrorRelaxation: 2.0,
  15.    
  16.     // 其他配置
  17.     forceUnlit: false, // 强制无光照模式
  18.     progressiveResolutionHeightFraction: 0.3,
  19. }));
复制代码
我的理解:这些参数主要用于高级优化,一般使用默认值即可,除非有特殊的性能需求。
第四步:运行时调整参数

可以在运行时动态调整参数,实时优化性能。
  1. const tileset = engine.add(new mapvthree.Default3DTiles({
  2.     url: 'data/3dtiles/tileset.json',
  3.     errorTarget: 16,
  4. }));
  5. // 运行时调整参数
  6. tileset.errorTarget = 8; // 提高细节
  7. tileset.cullRequestsWhileMoving = true; // 开启移动剔除
  8. tileset.loadSiblings = true; // 开启兄弟节点加载
复制代码
我的发现:可以根据场景需求动态调整参数,比如在性能不足时降低 errorTarget,在需要流畅移动时开启 cullRequestsWhileMoving。
第五步:完整示例

我想写一个完整的示例,把学到的都用上:
  1. import * as mapvthree from '@baidumap/mapv-three';
  2. const container = document.getElementById('container');
  3. const engine = new mapvthree.Engine(container, {
  4.     map: {
  5.         center: [105.931, 29.349, 280],
  6.         range: 2000,
  7.         pitch: 75,
  8.         provider: null,
  9.     },
  10. });
  11. // 从 URL 加载 3D Tiles,配置性能参数
  12. const tileset = engine.add(new mapvthree.Default3DTiles({
  13.     url: 'data/3dtiles/tileset.json',
  14.     errorTarget: 16,
  15.     cullRequestsWhileMoving: true,
  16.     cullWithChildrenBounds: true,
  17.     loadSiblings: true,
  18. }));
复制代码
我的感受:掌握了这些配置,就可以根据实际需求优化 3D Tiles 的加载和渲染性能了!
第六步:踩过的坑

作为一个初学者,我踩了不少坑,记录下来避免再犯:
坑 1:3D Tiles 不显示

原因:URL 路径错误,或者 tileset.json 文件不存在。
解决

  • 检查 URL 路径是否正确
  • 确认 tileset.json 文件存在且可访问
  • 检查浏览器控制台是否有错误信息
坑 2:加载很慢

原因:数据量大,或者网络慢,或者性能参数配置不当。
解决

  • 检查网络连接
  • 调整 errorTarget 参数,降低细节要求
  • 开启 cullRequestsWhileMoving 优化移动性能
  • 检查数据是否过大,考虑使用 LOD 优化
坑 3:内存占用过高

原因:缓存设置过大,或者加载了太多瓦片。
解决

  • 调整 cacheBytes 参数,限制缓存大小
  • 降低 errorTarget,减少加载的瓦片数量
  • 开启 cullWithChildrenBounds 精确剔除
坑 4:相机移动卡顿

原因:移动时加载了太多新瓦片,或者性能参数配置不当。
解决

  • 开启 cullRequestsWhileMoving,移动时暂停加载
  • 开启 loadSiblings,预加载相邻瓦片
  • 调整 errorTarget,降低细节要求
坑 5:Cesium Ion 加载失败

原因:没有配置 Cesium Ion AccessToken,或者 asset ID 错误。
解决

  • 确保配置了 Cesium Ion AccessToken
  • 检查 asset ID 是否正确
  • 确认 asset ID 对应的资源存在且有访问权限
我的学习总结

经过这一天的学习,我掌握了:

  • 从 URL 加载:使用 new Default3DTiles({ url }) 从 URL 加载
  • 从 Cesium Ion 加载:使用 Default3DTiles.fromAssetId() 从 Cesium Ion 加载
  • 性能优化:理解 errorTarget、cullRequestsWhileMoving 等参数的作用
  • 运行时调整:可以在运行时动态调整参数
我的感受:3D Tiles 功能很强大,但配置参数也比较多。关键是要理解每个参数的作用,然后根据实际需求进行优化。性能优化是一个平衡的过程,需要在细节和性能之间找到平衡点!
下一步计划

  • 学习更多 3D Tiles 的高级功能
  • 尝试创建自定义的 3D Tiles 数据
  • 做一个完整的大规模场景展示项目
学习笔记就到这里啦!作为一个初学者,我觉得 3D Tiles 功能很强大,但配置参数也比较多。关键是要理解每个参数的作用,然后根据实际需求进行优化。希望我的笔记能帮到其他初学者!大家一起加油!

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册