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