Babylon.js 高级主题 #
性能优化 #
性能优化是 3D 开发中的关键环节,良好的优化可以确保应用在各种设备上流畅运行。
渲染优化 #
text
┌─────────────────────────────────────────────────────────────┐
│ 渲染优化策略 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 减少绘制调用 │
│ - 合并网格 │
│ - 使用实例化 │
│ - 批量渲染 │
│ │
│ 2. 几何体优化 │
│ - LOD(细节层次) │
│ - 视锥剔除 │
│ - 遮挡剔除 │
│ │
│ 3. 材质优化 │
│ - 冻结材质 │
│ - 减少纹理大小 │
│ - 使用纹理压缩 │
│ │
│ 4. 阴影优化 │
│ - 降低阴影贴图分辨率 │
│ - 限制阴影范围 │
│ - 使用简单阴影算法 │
│ │
└─────────────────────────────────────────────────────────────┘
实例化渲染 #
javascript
// 创建源网格
const sourceMesh = BABYLON.MeshBuilder.CreateBox('source', { size: 1 }, scene);
// 创建实例(共享几何体,性能更好)
for (let i = 0; i < 1000; i++) {
const instance = sourceMesh.createInstance('instance' + i);
instance.position = new BABYLON.Vector3(
Math.random() * 100,
Math.random() * 100,
Math.random() * 100
);
}
// 隐藏源网格
sourceMesh.isVisible = false;
LOD 细节层次 #
javascript
// 创建 LOD 层级
const highDetail = BABYLON.MeshBuilder.CreateSphere('high', { segments: 64 }, scene);
const mediumDetail = BABYLON.MeshBuilder.CreateSphere('medium', { segments: 32 }, scene);
const lowDetail = BABYLON.MeshBuilder.CreateSphere('low', { segments: 16 }, scene);
// 添加 LOD 层级
highDetail.addLODLevel(20, mediumDetail);
highDetail.addLODLevel(50, lowDetail);
highDetail.addLODLevel(100, null); // 超过距离不渲染
材质冻结 #
javascript
// 冻结材质(停止自动更新)
material.freeze();
// 冻结网格世界矩阵
mesh.freezeWorldMatrix();
// 解冻
material.unfreeze();
mesh.unfreezeWorldMatrix();
视锥剔除 #
javascript
// 自动视锥剔除(默认启用)
mesh.alwaysSelectAsActiveMesh = false;
// 禁用剔除(用于特殊需求)
mesh.alwaysSelectAsActiveMesh = true;
// 手动控制可见性
mesh.isVisible = true;
mesh.setEnabled(true);
场景优化 #
javascript
// 自动优化设置
scene.autoClear = false;
scene.autoClearDepthAndStencil = false;
// 禁用不必要的功能
scene.blockfreeActiveMeshesAndRenderingGroups = true;
// 优化粒子系统
particleSystem.updateSpeed = 0.01; // 降低更新频率
particleSystem.maxParticles = 1000; // 限制粒子数量
纹理优化 #
javascript
// 使用压缩纹理
const texture = new BABYLON.Texture('/textures/compressed.ktx', scene);
// 设置纹理采样
texture.samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE;
// 禁用 Mipmap(节省内存)
texture.generateMipMaps = false;
// 异步加载
texture.onLoadObservable.add(() => {
console.log('纹理加载完成');
});
性能监控 #
javascript
// 启用性能监控
scene.debugLayer.show();
// 获取性能数据
const fps = engine.getFps();
const drawCalls = scene.getActiveMeshes().length;
// 使用性能分析器
const instrumentation = new BABYLON.EngineInstrumentation(engine);
instrumentation.captureFrameTime = true;
console.log('帧时间:', instrumentation.frameTimeCounter.lastSecAverage);
WebGPU #
WebGPU 是下一代 Web 图形 API,提供更好的性能和更多功能。
启用 WebGPU #
javascript
// 检查 WebGPU 支持
async function checkWebGPU() {
if (!navigator.gpu) {
console.log('WebGPU 不支持,回退到 WebGL');
return false;
}
return true;
}
// 创建 WebGPU 引擎
async function createEngine(canvas) {
const supported = await checkWebGPU();
if (supported) {
return await BABYLON.WebGPUEngine.CreateAsync(canvas, {
preserveDrawingBuffer: true,
stencil: true
});
} else {
return new BABYLON.Engine(canvas, true);
}
}
// 使用
const engine = await createEngine(canvas);
engine.beginFrame();
scene.render();
engine.endFrame();
WebGPU 特性 #
text
┌─────────────────────────────────────────────────────────────┐
│ WebGPU 优势 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 性能提升 │
│ - 更低的 CPU 开销 │
│ - 更好的多线程支持 │
│ - 更高效的渲染管线 │
│ │
│ 新功能 │
│ - 计算着色器 │
│ - 更灵活的着色器 │
│ - 高级纹理格式 │
│ │
│ 现代架构 │
│ - 显式 API 设计 │
│ - 更好的错误处理 │
│ - 跨平台一致性 │
│ │
└─────────────────────────────────────────────────────────────┘
WebGPU 计算着色器 #
javascript
// 创建计算着色器
const computeShader = new BABYLON.ComputeShader(
'computeShader',
engine,
{
computeSource: `
@group(0) @binding(0) var<storage, read_write> output : array<f32>;
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) global_id : vec3<u32>) {
let index = global_id.x;
output[index] = f32(index) * 2.0;
}
`
},
{
bindingsMapping: {
output: { group: 0, binding: 0 }
}
}
);
// 执行计算
computeShader.dispatch(256);
扩展开发 #
创建自定义材质 #
javascript
class CustomMaterial extends BABYLON.PushMaterial {
constructor(name, scene) {
super(name, scene);
this._color = new BABYLON.Color3(1, 0, 0);
}
get color() {
return this._color;
}
set color(value) {
this._color = value;
this._markAllSubMeshesAsTexturesDirty();
}
needAlphaBlending() {
return false;
}
needAlphaTesting() {
return false;
}
isReadyForSubMesh(mesh, subMesh) {
if (!this._uniformBufferLayoutBuilt) {
this._uniformBufferLayoutBuilt = true;
}
const effect = this._getEffect(subMesh);
if (!effect || !effect.isReady()) {
return false;
}
subMesh.setEffect(effect, this._getDefines(mesh));
return true;
}
bindForSubMesh(world, mesh, subMesh) {
const effect = subMesh.effect;
if (!effect) return;
this._activeEffect = effect;
this._uniformBuffer.bindToEffect(effect, 'Material');
this._uniformBuffer.updateFloat4(
'vColor',
this._color.r,
this._color.g,
this._color.b,
1.0
);
this._uniformBuffer.update();
}
}
创建自定义行为 #
javascript
class CustomBehavior extends BABYLON.Behavior {
constructor() {
super();
this.name = 'CustomBehavior';
this._time = 0;
}
init() {
// 初始化
}
attach(target) {
this._target = target;
}
detach() {
this._target = null;
}
update(deltaTime) {
if (!this._target) return;
this._time += deltaTime;
this._target.rotation.y += deltaTime * 0.001;
}
}
// 使用
const behavior = new CustomBehavior();
mesh.addBehavior(behavior);
创建自定义后处理 #
javascript
class CustomPostProcess extends BABYLON.PostProcess {
constructor(name, camera) {
super(
name,
'custom', // 着色器名称
['time', 'resolution'],
null,
1.0,
camera
);
this._time = 0;
this.onApply = (effect) => {
this._time += engine.getDeltaTime() * 0.001;
effect.setFloat('time', this._time);
effect.setVector2('resolution', new BABYLON.Vector2(
camera.getScene().getEngine().getRenderWidth(),
camera.getScene().getEngine().getRenderHeight()
));
};
}
}
// 使用
const postProcess = new CustomPostProcess('custom', camera);
最佳实践 #
资源管理 #
javascript
class ResourceManager {
constructor(scene) {
this.scene = scene;
this.textures = new Map();
this.meshes = new Map();
this.materials = new Map();
}
async loadTexture(name, url) {
if (this.textures.has(name)) {
return this.textures.get(name);
}
const texture = new BABYLON.Texture(url, this.scene);
this.textures.set(name, texture);
return texture;
}
async loadMesh(name, url) {
if (this.meshes.has(name)) {
return this.meshes.get(name).clone(name + '_clone');
}
const result = await BABYLON.SceneLoader.ImportMeshAsync('', '', url, this.scene);
this.meshes.set(name, result.meshes[0]);
return result.meshes[0];
}
createMaterial(name, options) {
if (this.materials.has(name)) {
return this.materials.get(name).clone(name + '_clone');
}
const material = new BABYLON.PBRMaterial(name, this.scene);
// 设置材质属性...
this.materials.set(name, material);
return material;
}
dispose() {
this.textures.forEach(t => t.dispose());
this.meshes.forEach(m => m.dispose());
this.materials.forEach(m => m.dispose());
this.textures.clear();
this.meshes.clear();
this.materials.clear();
}
}
场景状态管理 #
javascript
class SceneManager {
constructor(engine) {
this.engine = engine;
this.scenes = new Map();
this.activeScene = null;
}
createScene(name) {
const scene = new BABYLON.Scene(this.engine);
this.scenes.set(name, scene);
return scene;
}
switchTo(name) {
if (this.activeScene) {
this.activeScene.detachControl();
}
this.activeScene = this.scenes.get(name);
if (this.activeScene) {
this.activeScene.attachControl();
}
}
render() {
if (this.activeScene) {
this.activeScene.render();
}
}
dispose(name) {
const scene = this.scenes.get(name);
if (scene) {
scene.dispose();
this.scenes.delete(name);
}
}
}
输入管理 #
javascript
class InputManager {
constructor(scene) {
this.scene = scene;
this.keys = {};
this.mouse = { x: 0, y: 0, down: false };
this.setupKeyboard();
this.setupMouse();
}
setupKeyboard() {
window.addEventListener('keydown', (e) => {
this.keys[e.key.toLowerCase()] = true;
});
window.addEventListener('keyup', (e) => {
this.keys[e.key.toLowerCase()] = false;
});
}
setupMouse() {
const canvas = this.scene.getEngine().getRenderingCanvas();
canvas.addEventListener('mousemove', (e) => {
this.mouse.x = e.clientX;
this.mouse.y = e.clientY;
});
canvas.addEventListener('mousedown', () => {
this.mouse.down = true;
});
canvas.addEventListener('mouseup', () => {
this.mouse.down = false;
});
}
isKeyDown(key) {
return this.keys[key.toLowerCase()] === true;
}
isMouseDown() {
return this.mouse.down;
}
getMousePosition() {
return { x: this.mouse.x, y: this.mouse.y };
}
}
// 使用
const input = new InputManager(scene);
scene.onBeforeRenderObservable.add(() => {
if (input.isKeyDown('w')) {
player.position.z += 0.1;
}
if (input.isKeyDown('s')) {
player.position.z -= 0.1;
}
});
调试工具 #
javascript
class DebugTools {
constructor(scene) {
this.scene = scene;
this.enabled = false;
this.stats = {
fps: 0,
meshes: 0,
vertices: 0,
drawCalls: 0
};
}
enable() {
this.enabled = true;
this.scene.debugLayer.show();
}
disable() {
this.enabled = false;
this.scene.debugLayer.hide();
}
toggle() {
if (this.enabled) {
this.disable();
} else {
this.enable();
}
}
update() {
if (!this.enabled) return;
this.stats.fps = this.scene.getEngine().getFps();
this.stats.meshes = this.scene.meshes.length;
this.stats.vertices = this.scene.meshes.reduce((sum, mesh) => {
return sum + mesh.getTotalVertices();
}, 0);
this.stats.drawCalls = this.scene.getActiveMeshes().length;
}
log() {
console.table(this.stats);
}
}
发布部署 #
构建优化 #
javascript
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
build: {
target: 'esnext',
minify: 'terser',
rollupOptions: {
output: {
manualChunks: {
babylon: ['@babylonjs/core'],
loaders: ['@babylonjs/loaders'],
gui: ['@babylonjs/gui']
}
}
}
}
});
资源压缩 #
javascript
// 压缩纹理
// 使用工具将 PNG/JPG 转换为 KTX/Basis 格式
// 加载压缩纹理
const texture = new BABYLON.Texture('/textures/compressed.ktx', scene);
懒加载 #
javascript
// 懒加载模型
async function loadModelOnDemand(url) {
const { SceneLoader } = await import('@babylonjs/loaders');
return await SceneLoader.ImportMeshAsync('', '', url, scene);
}
// 懒加载 GUI
async function showGUI() {
const { AdvancedDynamicTexture } = await import('@babylonjs/gui');
const gui = AdvancedDynamicTexture.CreateFullscreenUI('UI');
return gui;
}
学习资源 #
官方资源 #
进阶学习 #
text
┌─────────────────────────────────────────────────────────────┐
│ 学习路径 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 初级 → 中级 │
│ - 完成基础教程 │
│ - 创建简单项目 │
│ - 理解核心概念 │
│ │
│ 中级 → 高级 │
│ - 学习性能优化 │
│ - 掌握 WebGPU │
│ - 开发自定义扩展 │
│ │
│ 高级 → 专家 │
│ - 贡献开源代码 │
│ - 创建复杂项目 │
│ - 参与社区讨论 │
│ │
└─────────────────────────────────────────────────────────────┘
总结 #
恭喜你完成了 Babylon.js 完全指南的学习!你已经掌握了:
- Babylon.js 的基础概念和安装配置
- 场景、相机、光照、材质、网格等核心系统
- 动画系统和粒子效果
- 物理引擎集成
- 性能优化和高级主题
继续实践和探索,你将成为一名优秀的 Babylon.js 开发者!
最后更新:2026-03-29