一、官方教程
https://doc.babylonjs.com/features/featuresDeepDive/scene/optimize_your_scene
使用 TransformNode 而不是 AbstractMesh 或空网格
减少着色器开销
减少世界矩阵计算
冻结活动网格
未更新边界信息
指针移动时未选取场景
减少绘制调用
减少对 gl.clear() 的调用
使用深度预通道
使用未编制索引的网格
关闭/打开 AdaptToDeviceRatio
阻塞脏机构
使用 Animation Ratio
处理丢失的 WebGL 上下文
具有大量网格的场景
更改网格剔除策略
性能优先模式
向后兼容模式(默认)
中间模式
激进模式
仪表
EngineInstrumentation
场景 Instrumentation
检查员
VR/XR 场景

二、GPT教程
在 Babylon.js 中,影响帧率的因素主要包括以下几个方面,以及相应的解决方法:
1. 顶点数量
原因:
- 较多的顶点会增加 GPU 的负担,因为每个顶点都需要进行变换和光照计算。
解决方法:
- 简化模型:使用低多边形模型或进行网格简化。
- 使用细节层次(LOD):根据距离动态切换不同复杂度的模型。
2. 网格数量
原因:
- 多个网格会增加绘制调用(draw calls),增加 CPU 和 GPU 之间的通信开销。
解决方法:
- 合并网格:将多个网格合并为一个,以减少绘制调用。
- 使用实例化:对于重复的对象,使用实例化技术可以显著减少绘制调用。
3. 材质和着色器复杂度
原因:
- 复杂的材质和着色器会增加计算负担。
解决方法:
- 简化材质:使用简单的材质和着色器。
- 优化着色器:减少不必要的计算,使用更高效的算法。
4. 纹理大小和数量
原因:
- 大量或高分辨率的纹理会占用显存,影响渲染性能。
解决方法:
- 压缩纹理:使用压缩纹理格式(如 DDS)。
- 减少纹理分辨率:降低纹理的分辨率,尤其是在不影响视觉效果的情况下。
5. 动态效果
原因:
- 动态效果如粒子系统、动画和实时光照会增加计算复杂度。
解决方法:
- 优化动画:减少骨骼动画的复杂度,使用 GPU 骨骼动画。
- 优化粒子系统:减少粒子数量或使用简化的粒子效果。
- 使用预计算光照:如果可以,使用光照贴图或其他预计算光照技术。
6. 光源数量
原因:
- 较多的光源会显著增加计算负担。
解决方法:
- 限制光源数量:尽量减少场景中的光源数量。
- 使用环境光照:结合环境光照减少对实时光源的依赖。
7. 阴影
原因:
- 实时阴影计算复杂,尤其是多个光源的阴影。
解决方法:
- 减少阴影光源:只为关键光源启用阴影。
- 使用简单阴影:如使用软阴影或降低阴影分辨率。
8. 后处理效果
原因:
- 后处理效果(如模糊、景深)会增加渲染时间。
解决方法:
- 优化或减少后处理效果:仅在需要时使用,或简化效果。
通过合理优化这些方面,可以显著提高 Babylon.js 项目的帧率和性能
绘制调用介绍
绘制调用(draw calls)是指 CPU 向 GPU 发出的命令,用于绘制图形。每个绘制调用通常涉及多个步骤,包括设置状态、绑定资源和执行渲染命令。绘制调用的次数对性能影响很大,因为每次调用都需要 CPU 和 GPU 之间的通信。
绘制调用的影响
- CPU 开销:
- 每个绘制调用都需要 CPU 准备和发送数据给 GPU,这会占用 CPU 时间。
- GPU 开销:
- 每个调用需要 GPU 切换状态和处理新的指令,这可能导致性能瓶颈。
- 通信开销:
- CPU 和 GPU 之间的通信是一个有限资源,过多的调用会导致瓶颈。
如何减少绘制调用
- 合并网格:
- 将多个小网格合并为一个大网格,减少调用次数。
- 使用实例化:
- 对于重复的对象(如树木、建筑),使用实例化技术,只需一次调用即可绘制多个实例。
- 批处理渲染:
- 将具有相同材质和渲染状态的对象进行批处理,一次性发送给 GPU。
- 简化材质切换:
- 尽量减少材质和渲染状态的切换,因为每次切换都可能导致新的绘制调用。
- 使用细节层次(LOD):
- 根据对象距离动态切换不同复杂度的模型,减少不必要的调用。
优化建议
- 合理组织场景:尽量减少需要单独渲染的对象数量。
- 优化资源绑定:减少纹理、着色器和其他资源的频繁切换。
- 使用合适的渲染技术:如延迟渲染(deferred rendering)在复杂场景中可以减少绘制调用。
通过这些优化方法,可以有效减少绘制调用的数量,提高渲染性能。
在 Babylon.js 中,对于重复的对象(如树木、建筑),可以使用实例化技术来优化渲染性能。实例化技术允许你在场景中重复渲染同一个网格对象,而只需一次绘制调用(draw call),从而显著提高性能。
以下是如何在 Babylon.js 中使用实例化技术的详细步骤和示例:
1. 什么是实例化?
实例化(Instancing)是一种 GPU 优化技术,允许你通过共享同一个几何数据(网格数据)来渲染多个对象。这些对象可以有不同的位置、旋转和缩放,但它们的几何形状和材质是相同的。
2. 如何在 Babylon.js 中使用实例化?
方法 1:使用 createInstance
创建实例
Babylon.js 提供了 createInstance
方法,可以基于一个原始网格(称为源网格)创建多个实例。
javascript复制代码// 创建一个基础网格(源网格)
const sourceMesh = BABYLON.MeshBuilder.CreateBox("sourceBox", { size: 1 }, scene);
// 创建多个实例
for (let i = 0; i < 10; i++) {
const instance = sourceMesh.createInstance("instance" + i);
// 设置实例的位置、旋转和缩放
instance.position = new BABYLON.Vector3(i * 2, 0, 0); // 每个实例在 X 轴上间隔 2
instance.rotation = new BABYLON.Vector3(0, Math.PI / 4 * i, 0); // 每个实例有不同的旋转
instance.scaling = new BABYLON.Vector3(1, 1 + i * 0.1, 1); // 每个实例有不同的缩放
}
特点:
createInstance
会创建一个与源网格共享几何数据的实例。- 实例可以有独立的位置、旋转和缩放,但它们的材质和顶点数据是共享的。
- 所有实例会共享同一个绘制调用(draw call),极大地提高性能。
方法 2:使用 thinInstanceAdd
创建大量实例
当需要大量实例(如上千个对象)时,可以使用 thinInstance
技术。thinInstance
更高效,因为它不会为每个实例创建单独的对象,而是直接在 GPU 上管理实例数据。
javascript复制代码// 创建一个基础网格(源网格)
const sourceMesh = BABYLON.MeshBuilder.CreateBox("sourceBox", { size: 1 }, scene);
// 准备实例变换矩阵
const instanceMatrices = [];
for (let i = 0; i < 1000; i++) {
const matrix = BABYLON.Matrix.Translation(i % 10 * 2, Math.floor(i / 10) * 2, 0); // 创建平铺的实例位置
instanceMatrices.push(matrix);
}
// 添加实例化数据
sourceMesh.thinInstanceAdd(instanceMatrices);
特点:
thinInstanceAdd
使用变换矩阵直接在 GPU 上管理实例的变换。- 不会为每个实例创建独立的 JavaScript 对象,性能更高。
- 适用于需要大量重复对象的场景,例如森林、建筑群等。
3. 两种实例化方法的对比
特性 | createInstance | thinInstanceAdd |
---|---|---|
适用场景 | 少量(几十到几百个)实例 | 大量(上千个)实例 |
独立控制 | 每个实例是独立的对象,可单独控制 | 实例数据直接在 GPU 上管理 |
内存占用 | 每个实例占用少量内存 | 几乎没有额外的内存开销 |
性能 | 较高,但不如 thinInstance 高 | 性能最高 |
4. 注意事项
- 材质共享:
- 所有实例必须共享同一个材质。如果需要不同的材质,则无法使用实例化技术。
- 动态更新:
- 对于
createInstance
,可以动态更新实例的属性(如位置、旋转)。 - 对于
thinInstanceAdd
,需要通过调用thinInstanceSetMatrixAt
或thinInstanceBufferUpdated
来更新实例数据。
- 对于
- 光照和阴影:
- 实例化的对象可以正确投射和接收阴影,但需要为源网格启用阴影。
sourceMesh.receiveShadows = true; sourceMesh.castShadows = true;
- 碰撞检测:
createInstance
的实例支持碰撞检测。thinInstance
的实例不支持默认的碰撞检测,因为它们没有独立的对象。
babylonjs 如何使用压缩纹理格式(如 DDS)
在 Babylon.js 中,使用压缩纹理格式(如 DDS)可以显著减少纹理占用的内存,提高加载和渲染性能。以下是如何在 Babylon.js 中使用压缩纹理的步骤:
1. 准备压缩纹理
- 使用工具(如 Photoshop 插件、KTX2 转换工具或其他专用软件)将纹理转换为 DDS 格式。
- 确保生成的 DDS 纹理支持你目标平台的压缩格式(如 DXT1、DXT5 等)。
2. 加载压缩纹理
在 Babylon.js 中,可以直接加载 DDS 格式的纹理:
javascript复制代码// 创建场景
const scene = new BABYLON.Scene(engine);
// 加载 DDS 纹理
const ddsTexture = new BABYLON.Texture("path/to/your/texture.dds", scene);
// 应用到材质
const material = new BABYLON.StandardMaterial("material", scene);
material.diffuseTexture = ddsTexture;
// 创建一个网格并应用材质
const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 2 }, scene);
sphere.material = material;
3. 使用 KTX2 格式
KTX2 是一种现代的压缩纹理格式,支持多种压缩算法(如 ASTC、ETC2、BC7),并且具有更好的跨平台支持。
转换为 KTX2
- 使用工具(如
toktx
)将纹理转换为 KTX2 格式。
加载 KTX2 纹理
javascript复制代码// 加载 KTX2 纹理
const ktx2Texture = new BABYLON.Texture("path/to/your/texture.ktx2", scene);
// 应用到材质
const material = new BABYLON.StandardMaterial("material", scene);
material.diffuseTexture = ktx2Texture;
// 创建一个网格并应用材质
const box = BABYLON.MeshBuilder.CreateBox("box", { size: 2 }, scene);
box.material = material;
4. 优势
- 减少内存占用:压缩纹理占用的显存更少。
- 提高加载速度:文件大小更小,网络传输更快。
- 提高渲染性能:GPU 可以更高效地处理压缩纹理。
5. 注意事项
- 确保你的目标平台支持所使用的纹理压缩格式。
- 不同平台可能支持不同的压缩格式,考虑使用多种格式以适应不同设备。
- 在开发环境中测试压缩纹理的视觉效果,以确保质量符合要求。
通过使用压缩纹理格式,Babylon.js 项目可以在性能和资源管理上获得显著提升。
babylonjs 中如何使用LOD技术
在 Babylon.js 中,使用 LOD(Level of Detail,细节层次)技术可以根据对象与摄像机的距离动态切换不同复杂度的模型,从而提高渲染性能。以下是如何在 Babylon.js 中使用 LOD 技术的步骤:
1. 创建不同细节层次的模型
首先,为你的对象创建多个不同复杂度的模型。例如,一个高细节的模型用于近距离显示,一个低细节的模型用于远距离显示。
2. 使用 addLODLevel
方法
在 Babylon.js 中,你可以使用 addLODLevel
方法为网格添加不同的 LOD 级别。
javascript复制代码// 创建场景
const scene = new BABYLON.Scene(engine);
// 创建高细节模型
const highDetailMesh = BABYLON.MeshBuilder.CreateSphere("highDetail", { segments: 32, diameter: 2 }, scene);
// 创建中等细节模型
const mediumDetailMesh = BABYLON.MeshBuilder.CreateSphere("mediumDetail", { segments: 16, diameter: 2 }, scene);
mediumDetailMesh.setEnabled(false); // 初始时禁用
// 创建低细节模型
const lowDetailMesh = BABYLON.MeshBuilder.CreateSphere("lowDetail", { segments: 8, diameter: 2 }, scene);
lowDetailMesh.setEnabled(false); // 初始时禁用
// 为高细节模型添加 LOD 级��
highDetailMesh.addLODLevel(10, mediumDetailMesh); // 距离 > 10 时使用中等细节模型
highDetailMesh.addLODLevel(20, lowDetailMesh); // 距离 > 20 时使用低细节模型
highDetailMesh.addLODLevel(30, null); // 距离 > 30 时不显示
// 添加材质(可选)
const material = new BABYLON.StandardMaterial("material", scene);
highDetailMesh.material = material;
mediumDetailMesh.material = material;
lowDetailMesh.material = material;
3. 解释
addLODLevel(distance, mesh)
:为网格添加一个 LOD 级别。当摄像机与网格的距离大于distance
时,使用指定的mesh
。null
可以用于指定在某个距离之后不显示网格。
4. 优化提示
- 确保不同 LOD 模型的材质一致,以避免材质切换带来的性能开销。
- 选择合理的距离阈值,以在性能和视觉效果之间取得平衡。
- LOD 技术对于复杂场景和大量对象的渲染性能提升尤为明显。
通过使用 LOD 技术,可以有效减少渲染负担,提升 Babylon.js 项目的整体性能。
性能监测方式

