JSAPIThree LODModel 性能优化学习笔记:细节层次模型加载

在加载大量三维模型时,如果所有模型都使用高精度版本,会导致渲染性能急剧下降。LOD(Level of Detail,细节层次)技术可以根据相机距离动态切换模型精度,在保证视觉效果的同时显著提升性能。今天就来学习 mapvthree 的 LODModel 组件。

了解 LOD 技术

什么是 LOD?

LOD(Level of Detail)即"细节层次",是一种常见的三维渲染优化技术。

核心思想

  • 相机距离远时,使用低精度(少三角面)的模型
  • 相机距离近时,使用高精度(多三角面)的模型
  • 根据距离自动切换,用户几乎无感知

我的理解:就像看远处的树,不需要看清每一片树叶;只有走近时,才需要看到树叶的细节。LOD 让渲染引擎也这样"聪明"地工作。

为什么需要 LOD?

在实际场景中,LOD 技术非常重要:

性能问题

js 复制代码
// 假设场景中有 1000 棵树
// 每棵树的高精度模型有 10000 个三角面
// 总三角面数 = 1000 × 10000 = 1000万
// 这会导致严重的性能问题!

使用 LOD 优化

js 复制代码
// 使用 LOD 后:
// - 远处 800 棵树用低精度模型(每棵 500 面)= 40万面
// - 中距离 150 棵树用中精度模型(每棵 2000 面)= 30万面
// - 近处 50 棵树用高精度模型(每棵 10000 面)= 50万面
// 总三角面数 = 120万(降低到原来的 12%!)

我的发现:合理使用 LOD,可以在几乎不影响视觉效果的情况下,将渲染负担降低到原来的 10-20%!

LOD 的应用场景

LOD 特别适合以下场景:

  • 树木、植被:远看只需要轮廓,近看才需要树叶细节
  • 建筑物:远看只需要外形,近看才需要窗户、装饰等细节
  • 车辆模型:远看是简单的车型,近看才有车轮、车灯等细节
  • 地形:远处的地形可以更粗糙,近处需要更多细节

第一步:理解 LODModel 与 SimpleModel 的区别

在学习 LODModel 之前,我们需要理解它与 SimpleModel 的区别。

SimpleModel 的使用方式

js 复制代码
// SimpleModel:使用地理坐标,自动处理投影转换
const model = engine.add(new mapvthree.SimpleModel({
    object: 'assets/models/tree/tree18.glb',
    point: [120.628, 27.786, 0], // 地理坐标
    scale: [10, 10, 10],
    rotation: [Math.PI / 2, 0, 0],
}));

LODModel 的使用方式

js 复制代码
// LODModel:使用场景坐标,需要手动转换
const center = [120.628, 27.786, 0];
const position = engine.map.projectArrayCoordinate(center); // 转换为场景坐标

const lod = engine.add(new mapvthree.LODModel({
    hysteresis: 0.2,
}));

lod.position.set(...position); // 使用场景坐标
lod.scale.setScalar(10);
lod.rotateX(Math.PI / 2);

// 添加不同层级的模型
lod.addLevel('assets/models/tree/tree19.glb', 5000); // 低精度,5000米以内显示
lod.addLevel('assets/models/tree/tree18.glb', 1000); // 高精度,1000米以内显示

主要区别

特性 SimpleModel LODModel
位置设置 使用地理坐标 point: [lng, lat, z] 使用场景坐标 position.set(x, y, z)
坐标转换 自动处理 需要手动调用 projectArrayCoordinate
模型数量 单个模型 多个不同精度的模型
性能优化 根据距离自动切换模型
使用场景 单体模型展示 需要性能优化的大量模型

我的理解:LODModel 更接近原生 Three.js 的使用方式,需要手动处理坐标转换,但提供了性能优化的能力。

第二步:基本使用 - 创建 LOD 模型

让我们从一个简单的例子开始。

创建 LODModel 实例

js 复制代码
import * as mapvthree from '@baidumap/mapv-three';

const container = document.getElementById('container');

const engine = new mapvthree.Engine(container, {
    map: {
        center: [120.628, 27.786, 0],
        range: 1000,
        pitch: 80,
        projection: 'EPSG:3857',
        provider: null,
    },
    rendering: {
        enableAnimationLoop: true, // 必须开启,LOD 需要动态更新
    },
});

// 1. 创建 LODModel 实例
const lod = engine.add(new mapvthree.LODModel({
    hysteresis: 0.2, // 滞后系数,避免频繁切换
}));

// 2. 将地理坐标转换为场景坐标
const center = [120.628, 27.786, 0];
const position = engine.map.projectArrayCoordinate(center);

// 3. 设置位置、缩放和旋转
lod.position.set(...position);
lod.scale.setScalar(10);
lod.rotateX(Math.PI / 2);

// 4. 添加不同层级的模型
lod.addLevel('assets/models/tree/tree19.glb', 5000); // 低精度模型
lod.addLevel('assets/models/tree/tree18.glb', 1000); // 高精度模型

我的发现:创建 LODModel 的流程是固定的,分为四步:创建实例 → 转换坐标 → 设置变换 → 添加层级。

我的理解

  • hysteresis(滞后系数):避免在临界距离时频繁切换模型,值越大切换越不频繁
  • enableAnimationLoop:必须开启,否则 LOD 不会根据相机距离动态切换

第三步:理解 addLevel 方法

addLevel 方法用于添加不同层级的模型。

addLevel 的参数

js 复制代码
lod.addLevel(modelUrl, distance);

参数说明

  • modelUrl:模型文件路径(支持所有 Three.js 支持的格式)
  • distance:显示距离(单位:米)

层级切换逻辑

js 复制代码
// 添加 3 个层级
lod.addLevel('assets/models/tree/tree_low.glb', 10000);   // 层级 0:超远距离
lod.addLevel('assets/models/tree/tree_mid.glb', 5000);    // 层级 1:中等距离
lod.addLevel('assets/models/tree/tree_high.glb', 1000);   // 层级 2:近距离

切换规则

  • 相机距离 > 10000米:不显示任何模型
  • 10000米 ≥ 相机距离 > 5000米:显示 tree_low.glb(低精度)
  • 5000米 ≥ 相机距离 > 1000米:显示 tree_mid.glb(中精度)
  • 相机距离 ≤ 1000米:显示 tree_high.glb(高精度)

我的理解

  • 距离参数是该层级的最大显示距离
  • 层级顺序很重要:从低精度到高精度,距离从大到小
  • 第一个层级的距离决定了模型的最大可见距离

典型的层级配置

js 复制代码
// 适用于树木、植被
lod.addLevel('tree_low.glb', 5000);    // 低精度:500-1000 三角面
lod.addLevel('tree_high.glb', 1000);   // 高精度:5000-10000 三角面

// 适用于建筑物
lod.addLevel('building_low.glb', 10000);   // 低精度:简单盒子
lod.addLevel('building_mid.glb', 3000);    // 中精度:基本结构
lod.addLevel('building_high.glb', 500);    // 高精度:完整细节

// 适用于车辆
lod.addLevel('car_low.glb', 2000);    // 低精度:车身轮廓
lod.addLevel('car_mid.glb', 500);     // 中精度:基本车型
lod.addLevel('car_high.glb', 100);    // 高精度:完整车辆

我的发现:不同类型的模型需要不同的层级配置,根据模型复杂度和视觉重要性来调整距离阈值。

第四步:理解 hysteresis 参数

hysteresis(滞后系数)是 LOD 的重要参数,用于避免频繁切换。

什么是滞后(Hysteresis)?

问题场景

js 复制代码
// 假设中精度模型的切换距离是 5000 米
// 如果相机在 5000 米附近移动:
// - 4999 米:切换到中精度
// - 5001 米:切换到低精度
// - 4999 米:又切换到中精度
// - 5001 米:又切换到低精度
// 这样会导致模型频繁切换,产生闪烁!

滞后解决方案

js 复制代码
const lod = new mapvthree.LODModel({
    hysteresis: 0.2, // 滞后系数为 20%
});

lod.addLevel('tree_low.glb', 5000);
lod.addLevel('tree_high.glb', 1000);

// 实际切换距离:
// - 从低精度切换到中精度:5000 × (1 - 0.2) = 4000 米
// - 从中精度切换到低精度:5000 × (1 + 0.2) = 6000 米
// 这样在 4000-6000 米之间有一个"缓冲区"

我的理解

  • hysteresis = 0.0:无滞后,精确按距离切换(可能频繁闪烁)
  • hysteresis = 0.2:20% 滞后,适合大多数场景
  • hysteresis = 0.5:50% 滞后,切换非常"迟钝"

如何选择 hysteresis 值?

js 复制代码
// 小场景、快速移动:使用较大的滞后
const lod = new mapvthree.LODModel({
    hysteresis: 0.3, // 避免快速移动时频繁切换
});

// 大场景、慢速移动:使用较小的滞后
const lod = new mapvthree.LODModel({
    hysteresis: 0.1, // 更精确的切换时机
});

// 不需要滞后(不推荐)
const lod = new mapvthree.LODModel({
    hysteresis: 0.0, // 可能产生闪烁
});

我的建议

  • 一般情况使用 0.2(默认值)
  • 如果发现切换闪烁,增大到 0.30.4
  • 如果切换太"迟钝",减小到 0.1

第五步:坐标转换详解

LODModel 需要手动进行坐标转换,这是与 SimpleModel 最大的区别。

为什么需要手动转换?

js 复制代码
// SimpleModel:自动转换
const model = engine.add(new mapvthree.SimpleModel({
    point: [120.628, 27.786, 0], // 地理坐标,自动转换
}));

// LODModel:手动转换
const center = [120.628, 27.786, 0]; // 地理坐标
const position = engine.map.projectArrayCoordinate(center); // 转换为场景坐标
const lod = engine.add(new mapvthree.LODModel());
lod.position.set(...position); // 使用场景坐标

我的理解:LODModel 更接近原生 Three.js 的使用方式,需要使用场景坐标(x, y, z),而不是地理坐标(经度, 纬度, 高度)。

坐标转换方法

js 复制代码
// 方法 1:转换单个坐标
const geoCoord = [120.628, 27.786, 0]; // [经度, 纬度, 高度]
const sceneCoord = engine.map.projectArrayCoordinate(geoCoord); // [x, y, z]
lod.position.set(...sceneCoord);

// 方法 2:转换多个坐标
const geoCoords = [
    [120.628, 27.786, 0],
    [120.629, 27.787, 0],
    [120.630, 27.788, 0],
];

const sceneCoords = geoCoords.map(coord => 
    engine.map.projectArrayCoordinate(coord)
);

// 为每个坐标创建 LOD 模型
sceneCoords.forEach(position => {
    const lod = engine.add(new mapvthree.LODModel({
        hysteresis: 0.2,
    }));
    lod.position.set(...position);
    lod.scale.setScalar(10);
    lod.addLevel('tree_low.glb', 5000);
    lod.addLevel('tree_high.glb', 1000);
});

我的发现:如果需要加载大量 LOD 模型,可以先批量转换坐标,然后再创建模型。

动态更新位置

js 复制代码
// 创建 LOD 模型
const lod = engine.add(new mapvthree.LODModel({
    hysteresis: 0.2,
}));

// 设置初始位置
const initialPos = engine.map.projectArrayCoordinate([120.628, 27.786, 0]);
lod.position.set(...initialPos);
lod.scale.setScalar(10);
lod.addLevel('tree_low.glb', 5000);
lod.addLevel('tree_high.glb', 1000);

// 后续更新位置
setTimeout(() => {
    const newPos = engine.map.projectArrayCoordinate([120.629, 27.787, 0]);
    lod.position.set(...newPos);
}, 5000);

我的理解:LODModel 的位置可以动态更新,每次更新前都需要重新转换地理坐标。

第六步:设置变换(位置、旋转、缩放)

LODModel 使用 Three.js 的标准方式设置变换。

设置位置

js 复制代码
// 方式 1:使用 position.set
const position = engine.map.projectArrayCoordinate([120.628, 27.786, 0]);
lod.position.set(...position); // 展开数组
// 或
lod.position.set(position[0], position[1], position[2]); // 分别传入

// 方式 2:直接赋值
lod.position.x = position[0];
lod.position.y = position[1];
lod.position.z = position[2];

设置旋转

js 复制代码
// 方式 1:使用旋转方法
lod.rotateX(Math.PI / 2); // 绕 X 轴旋转 90 度
lod.rotateY(Math.PI / 4); // 绕 Y 轴旋转 45 度
lod.rotateZ(Math.PI);     // 绕 Z 轴旋转 180 度

// 方式 2:直接设置 rotation
lod.rotation.set(Math.PI / 2, 0, 0); // [x, y, z]
// 或
lod.rotation.x = Math.PI / 2;
lod.rotation.y = 0;
lod.rotation.z = 0;

我的发现 :旋转单位是弧度,不是角度。Math.PI / 2 = 90度,Math.PI = 180度。

设置缩放

js 复制代码
// 方式 1:统一缩放
lod.scale.setScalar(10); // x, y, z 都缩放 10 倍

// 方式 2:分别设置
lod.scale.set(10, 10, 10); // [x, y, z]

// 方式 3:非均匀缩放
lod.scale.x = 10; // x 方向放大 10 倍
lod.scale.y = 20; // y 方向放大 20 倍
lod.scale.z = 5;  // z 方向放大 5 倍

我的理解:这些都是 Three.js 的标准 API,如果熟悉 Three.js,使用起来会很自然。

第七步:批量创建 LOD 模型

在实际场景中,我们通常需要创建大量的 LOD 模型。

批量创建示例

js 复制代码
import * as mapvthree from '@baidumap/mapv-three';

const container = document.getElementById('container');

const engine = new mapvthree.Engine(container, {
    map: {
        center: [120.628, 27.786, 0],
        range: 2000,
        pitch: 80,
        projection: 'EPSG:3857',
        provider: null,
    },
    rendering: {
        enableAnimationLoop: true,
    },
});

// 树木的地理坐标数据
const treeData = [
    [120.628, 27.786, 0],
    [120.629, 27.787, 0],
    [120.627, 27.785, 0],
    [120.630, 27.788, 0],
    [120.626, 27.784, 0],
    // ... 更多坐标
];

// 批量创建 LOD 模型
treeData.forEach(geoCoord => {
    // 1. 转换坐标
    const position = engine.map.projectArrayCoordinate(geoCoord);
    
    // 2. 创建 LOD 模型
    const lod = engine.add(new mapvthree.LODModel({
        hysteresis: 0.2,
    }));
    
    // 3. 设置变换
    lod.position.set(...position);
    lod.scale.setScalar(10);
    lod.rotateX(Math.PI / 2);
    
    // 4. 添加层级
    lod.addLevel('assets/models/tree/tree19.glb', 5000); // 低精度
    lod.addLevel('assets/models/tree/tree18.glb', 1000); // 高精度
});

我的发现:批量创建时,每个 LOD 模型都是独立的,可以有不同的位置、旋转和缩放。

使用函数封装

js 复制代码
// 封装创建函数
function createTreeLOD(engine, geoCoord, config = {}) {
    const {
        scale = 10,
        rotation = [Math.PI / 2, 0, 0],
        hysteresis = 0.2,
        lowUrl = 'assets/models/tree/tree19.glb',
        highUrl = 'assets/models/tree/tree18.glb',
        lowDistance = 5000,
        highDistance = 1000,
    } = config;
    
    // 转换坐标
    const position = engine.map.projectArrayCoordinate(geoCoord);
    
    // 创建 LOD
    const lod = engine.add(new mapvthree.LODModel({ hysteresis }));
    
    // 设置变换
    lod.position.set(...position);
    lod.scale.setScalar(scale);
    lod.rotation.set(...rotation);
    
    // 添加层级
    lod.addLevel(lowUrl, lowDistance);
    lod.addLevel(highUrl, highDistance);
    
    return lod;
}

// 使用封装的函数
const trees = treeData.map(coord => 
    createTreeLOD(engine, coord, {
        scale: 10,
        hysteresis: 0.2,
    })
);

我的理解:封装成函数后,代码更简洁,也更容易维护和复用。

第八步:性能优化技巧

使用 LOD 时,还有一些额外的优化技巧。

技巧 1:合理设置层级数量

js 复制代码
// 不推荐:层级太少
lod.addLevel('tree_high.glb', 1000); // 只有一个层级,没有优化效果

// 不推荐:层级太多
lod.addLevel('tree_level0.glb', 10000);
lod.addLevel('tree_level1.glb', 8000);
lod.addLevel('tree_level2.glb', 6000);
lod.addLevel('tree_level3.glb', 4000);
lod.addLevel('tree_level4.glb', 2000);
lod.addLevel('tree_level5.glb', 1000); // 层级过多,管理复杂

// 推荐:2-3 个层级
lod.addLevel('tree_low.glb', 5000);  // 低精度
lod.addLevel('tree_high.glb', 1000); // 高精度

// 或 3 个层级
lod.addLevel('tree_low.glb', 10000);   // 低精度
lod.addLevel('tree_mid.glb', 3000);    // 中精度
lod.addLevel('tree_high.glb', 500);    // 高精度

我的建议

  • 简单模型(如树木):2 个层级足够
  • 复杂模型(如建筑物):3 个层级
  • 超复杂模型:最多 4-5 个层级

技巧 2:根据重要性调整距离

js 复制代码
// 重要的模型(如主建筑):更大的显示距离
const mainBuilding = engine.add(new mapvthree.LODModel({
    hysteresis: 0.2,
}));
mainBuilding.addLevel('building_low.glb', 20000);  // 20km 可见
mainBuilding.addLevel('building_high.glb', 5000);

// 不重要的模型(如背景树木):较小的显示距离
const backgroundTree = engine.add(new mapvthree.LODModel({
    hysteresis: 0.2,
}));
backgroundTree.addLevel('tree_low.glb', 3000);  // 3km 可见
backgroundTree.addLevel('tree_high.glb', 500);

我的理解:不是所有模型都需要远距离可见,根据重要性合理分配渲染资源。

技巧 3:控制模型精度差异

js 复制代码
// 精度差异太小:优化效果不明显
lod.addLevel('tree_9000faces.glb', 5000);  // 9000 三角面
lod.addLevel('tree_10000faces.glb', 1000); // 10000 三角面(差异太小)

// 推荐:精度差异明显
lod.addLevel('tree_500faces.glb', 5000);   // 500 三角面(低精度)
lod.addLevel('tree_10000faces.glb', 1000); // 10000 三角面(高精度,20倍差异)

我的建议

  • 低精度模型应该是高精度模型的 5-20% 面数
  • 例如:高精度 10000 面 → 低精度 500-2000 面

技巧 4:必须开启动画循环

js 复制代码
// 错误:没有开启动画循环
const engine = new mapvthree.Engine(container, {
    rendering: {
        enableAnimationLoop: false, // LOD 不会工作!
    },
});

// 正确:开启动画循环
const engine = new mapvthree.Engine(container, {
    rendering: {
        enableAnimationLoop: true, // LOD 需要每帧更新
    },
});

我的发现:如果没有开启动画循环,LOD 不会根据相机距离动态切换,失去了优化效果。

第九步:完整示例

我想写一个完整的示例,展示如何在实际场景中使用 LOD:

js 复制代码
import * as mapvthree from '@baidumap/mapv-three';

const container = document.getElementById('container');

// 初始化引擎(必须开启动画循环)
const engine = new mapvthree.Engine(container, {
    map: {
        center: [120.628, 27.786, 0],
        range: 2000,
        pitch: 80,
        projection: 'EPSG:3857',
        provider: null,
    },
    rendering: {
        enableAnimationLoop: true, // 必须开启
    },
});

// 生成随机的树木坐标(模拟实际数据)
function generateTreePositions(center, count, radius) {
    const positions = [];
    for (let i = 0; i < count; i++) {
        const angle = Math.random() * Math.PI * 2;
        const distance = Math.random() * radius;
        const lng = center[0] + (distance * Math.cos(angle)) / 111000; // 粗略转换
        const lat = center[1] + (distance * Math.sin(angle)) / 111000;
        positions.push([lng, lat, 0]);
    }
    return positions;
}

// 生成 100 个树木位置
const treePositions = generateTreePositions([120.628, 27.786, 0], 100, 1000);

// 批量创建 LOD 模型
treePositions.forEach(geoCoord => {
    // 1. 转换坐标
    const position = engine.map.projectArrayCoordinate(geoCoord);
    
    // 2. 创建 LOD 模型
    const lod = engine.add(new mapvthree.LODModel({
        hysteresis: 0.2, // 20% 滞后,避免频繁切换
    }));
    
    // 3. 设置位置和变换
    lod.position.set(...position);
    lod.scale.setScalar(8 + Math.random() * 4); // 随机缩放 8-12
    lod.rotateX(Math.PI / 2);
    lod.rotateZ(Math.random() * Math.PI * 2); // 随机旋转
    
    // 4. 添加两个层级
    // 低精度:5000米以内显示(约500三角面)
    lod.addLevel('assets/models/tree/tree19.glb', 5000);
    // 高精度:1000米以内显示(约10000三角面)
    lod.addLevel('assets/models/tree/tree18.glb', 1000);
});

console.log('创建了 ' + treePositions.length + ' 个 LOD 树木模型');
console.log('远距离三角面数:约 ' + (treePositions.length * 500) + ' 个');
console.log('近距离三角面数:约 ' + (treePositions.length * 10000) + ' 个');
console.log('性能提升:约 ' + Math.round((1 - 500/10000) * 100) + '%');

我的感受:通过 LOD 技术,我们可以在场景中放置大量模型,而不用担心性能问题!

第十步:踩过的坑

作为一个初学者,我踩了不少坑,记录下来避免再犯:

坑 1:忘记开启动画循环

错误代码

js 复制代码
const engine = new mapvthree.Engine(container, {
    rendering: {
        enableAnimationLoop: false, // 忘记开启
    },
});

const lod = engine.add(new mapvthree.LODModel());
lod.addLevel('tree_low.glb', 5000);
lod.addLevel('tree_high.glb', 1000);
// LOD 不会切换!

解决 :必须开启 enableAnimationLoop: true

坑 2:层级距离顺序错误

错误代码

js 复制代码
// 错误:距离从小到大
lod.addLevel('tree_high.glb', 1000);  // 高精度
lod.addLevel('tree_low.glb', 5000);   // 低精度
// 导致远处显示高精度,近处显示低精度!

解决:距离应该从大到小,精度从低到高:

js 复制代码
// 正确:距离从大到小,精度从低到高
lod.addLevel('tree_low.glb', 5000);   // 低精度,远距离
lod.addLevel('tree_high.glb', 1000);  // 高精度,近距离

坑 3:忘记转换坐标

错误代码

js 复制代码
const lod = engine.add(new mapvthree.LODModel());
lod.position.set(120.628, 27.786, 0); // 直接使用地理坐标!
// 模型位置不对!

解决:必须先转换坐标:

js 复制代码
const position = engine.map.projectArrayCoordinate([120.628, 27.786, 0]);
lod.position.set(...position);

坑 4:模型不显示

原因:可能的原因有多个:

  1. 模型路径错误
  2. 模型加载失败
  3. 相机距离超过了最大显示距离
  4. 位置坐标错误

解决

js 复制代码
// 1. 检查模型路径
console.log('模型路径:', 'assets/models/tree/tree18.glb');

// 2. 监听加载事件(LODModel 暂不支持,需要检查控制台)
// 查看浏览器控制台是否有加载错误

// 3. 检查显示距离
lod.addLevel('tree_low.glb', 10000); // 增大显示距离

// 4. 检查位置坐标
const position = engine.map.projectArrayCoordinate([120.628, 27.786, 0]);
console.log('场景坐标:', position);
lod.position.set(...position);

坑 5:切换太频繁导致闪烁

原因hysteresis 值太小,或设置为 0。

解决

js 复制代码
// 增大 hysteresis 值
const lod = new mapvthree.LODModel({
    hysteresis: 0.3, // 从 0.2 增大到 0.3
});

坑 6:性能优化不明显

原因:低精度模型和高精度模型面数差异太小。

解决

  • 检查模型面数:低精度应该是高精度的 5-20%
  • 使用建模软件重新导出低精度版本
  • 或使用模型简化工具(如 Blender、Meshlab)

坑 7:使用 SimpleModel 的方式设置位置

错误代码

js 复制代码
// LODModel 不支持 point 参数!
const lod = engine.add(new mapvthree.LODModel({
    point: [120.628, 27.786, 0], // 不支持!
}));

解决:LODModel 必须使用场景坐标:

js 复制代码
const lod = engine.add(new mapvthree.LODModel());
const position = engine.map.projectArrayCoordinate([120.628, 27.786, 0]);
lod.position.set(...position);

我的学习总结

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

  1. LOD 的概念:Level of Detail,根据距离动态切换模型精度
  2. LOD 的优势:在保证视觉效果的同时,显著提升渲染性能(可降低到 10-20%)
  3. LODModel 的使用:创建实例 → 转换坐标 → 设置变换 → 添加层级
  4. addLevel 方法:添加不同层级的模型,距离从大到小,精度从低到高
  5. hysteresis 参数:滞后系数,避免频繁切换,一般使用 0.2
  6. 坐标转换 :必须使用 engine.map.projectArrayCoordinate 转换地理坐标
  7. 批量创建:可以封装函数,批量创建大量 LOD 模型
  8. 性能优化技巧:合理设置层级数量、显示距离、模型精度差异

我的感受:LODModel 是性能优化的神器!虽然比 SimpleModel 使用起来稍微复杂一点(需要手动转换坐标),但性能提升非常明显。特别是在需要加载大量模型的场景中(如树木、建筑物),LOD 技术是必不可少的。

关键要点

  • ✅ 必须开启 enableAnimationLoop: true
  • ✅ 层级顺序:距离从大到小,精度从低到高
  • ✅ 必须转换坐标:engine.map.projectArrayCoordinate
  • ✅ 合理设置 hysteresis,避免频繁切换
  • ✅ 低精度模型应该是高精度的 5-20% 面数

下一步计划

  1. 学习如何使用建模工具制作不同精度的模型
  2. 尝试在大型场景中批量加载 LOD 模型
  3. 学习如何结合 InstancedMesh 进一步优化性能

学习笔记就到这里啦!作为一个初学者,我觉得 LOD 技术是三维渲染性能优化的核心技术之一。虽然 LODModel 需要手动转换坐标,使用起来比 SimpleModel 稍微复杂,但性能提升是巨大的。掌握了 LOD,就可以在场景中放置成千上万个模型而不用担心性能问题!希望我的笔记能帮到其他初学者!大家一起加油!

相关推荐
Yuner20002 小时前
BabylonJS魔法:学习指南
3d·webgl
MarkHD3 小时前
智能体在车联网中的应用:第9天 核心工具链与仿真世界:SUMO交通仿真入门——从安装到构建你的第一个虚拟十字路口
学习
lxh01133 小时前
2025/12/18 学习总结
学习
im_AMBER3 小时前
数据结构 13 图 | 哈希表 | 树
数据结构·笔记·学习·算法·散列表
会思考的猴子3 小时前
UE5 笔记敌人自动追踪
笔记·ue5
wdfk_prog3 小时前
[Linux]学习笔记系列 -- [fs][drop_caches]
linux·笔记·学习
2021_fc4 小时前
Flink笔记
大数据·笔记·flink
黑客思维者4 小时前
机器学习006:监督学习【回归算法】(概论)--教AI从历史中预测未来
人工智能·学习·机器学习·监督学习·回归算法
xunyan62344 小时前
面向对象(下)-内部类的分类
java·学习