Skip to content

简单示例

template
js
<template>
  <div class="babylon-container">
    <div class="info">
      <p>BabylonJS + Vue 3 示例</p>
      <p>操作: 鼠标拖动旋转视角,滚轮缩放</p>
    </div>
    <canvas ref="renderCanvas" class="render-canvas"></canvas> // [!code focus]
  </div>
</template>

1. 获取 Canvas 元素

js
// 获取canvas元素的引用
const renderCanvas = ref(null);

2. 创建 Engine 实例

js
// 存储BabylonJS的核心对象
let engine = null;
let sceneA = null;

// 初始化引擎
  engine = new BABYLON.Engine(renderCanvas.value, true, {  
    precision: "highp", //渲染精度 highp(默认), mediump, lowp
    renderMode: BABYLON.Engine.RENDERMODE_WEBGL2, // 渲染模式 webgl, webgl2, webgl2deferred
  }); 
  • new BABYLON.Engine([canvas对象], [是否启动抗锯齿])

3. 创建场景 (Scene)

js
// 创建场景
const scene = new BABYLON.Scene(engine); 
scene.clearColor = new BABYLON.Color3(0.9, 0.9, 0.9); 
  • 场景 是所有 3D 对象的容器
  • 一个 Engine 实例可以管理多个 Scene 实例,但通常情况下,一个应用对应一个场景。

4. 创建相机 (Camera)

js
// 创建相机
const camera = new BABYLON.ArcRotateCamera(
  "camera1",
  0,
  Math.PI / 3,
  10,
  BABYLON.Vector3.Zero(), // 原点
  scene
);
camera.attachControl(renderCanvas.value, true);
  • 第一个参数: 相机的名称
  • 第二个参数: 水平旋转角度(弧度)
  • 第三个参数: 垂直旋转角度(弧度)
  • 第四个参数: 相机与目标点的距离
  • 第五个参数: 目标点的位置(这里设置为原点)
  • 第六个参数: 所属的场景

5. 创建光源 (Light)

js
  // 创建环境光
  const light = new BABYLON.HemisphericLight("light1", BABYLON.Vector3.Up(), scene);
  light.intensity = 0.7;
  • HemisphericLight 模拟来自天空的环境光
  • 第一个参数: 光源的名称。
  • 第二个参数: 光源的方向(这里指向天空)
  • 第三个参数: 所属的场景

6. 创建物品

js
// 往scene场景添加一个box
const box1 = BABYLON.MeshBuilder.CreateBox("box", { size: 2 }, scene); 


// 往scene场景添加一个球体
const sphere = BABYLON.MeshBuilder.CreateSphere(
  "sphere",
  { diameter: 2, segments: 32 },
  scene
);
sphere.position.y = 1;

// 球体材质
const sphereMaterial = new BABYLON.StandardMaterial("sphereMaterial", scene);
sphereMaterial.diffuseColor = new BABYLON.Color3(0.2, 0.5, 1);
sphereMaterial.specularColor = new BABYLON.Color3(1, 1, 1);
sphereMaterial.specularPower = 32;
sphere.material = sphereMaterial;

7. 启动渲染循环

js
engine.runRenderLoop(() => { // 每一帧被调用
    scene.render(); // 渲染当前场景
});

8. 处理窗口调整大小

js
// 当浏览器窗口大小发生变化时,调用 engine.resize() 方法来调整 Canvas 的大小
// 并重新计算相机的投影矩阵。
window.addEventListener("resize", () => {
    engine.resize();
});

完整简单示例

Details
html
<template>
  <div class="babylon-container">
    <div class="info">
      <p>BabylonJS + Vue 3 示例</p>
      <p>操作: 鼠标拖动旋转视角,滚轮缩放</p>
    </div>
    <canvas ref="renderCanvas" class="render-canvas"></canvas>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
// 引入BabylonJS库
import * as BABYLON from 'babylonjs';

// 获取canvas元素的引用
const renderCanvas = ref(null);
// 存储BabylonJS的核心对象
let engine = null;
let sceneA = null;

// 创建3D场景
const createSceneA = () => {
  // 1 初始化引擎
  engine = new BABYLON.Engine(renderCanvas.value, true);
  
  // 2 创建场景
  const scene = new BABYLON.Scene(engine);
  scene.clearColor = new BABYLON.Color3(0.9, 0.9, 0.9);
  
  // 3 创建相机
  const camera = new BABYLON.ArcRotateCamera(
    "camera",
    0,
    Math.PI / 3,
    10,
    BABYLON.Vector3.Zero(),
    scene
  );
  camera.attachControl(renderCanvas.value, true);
  
  // 4 创建灯光
  const light = new BABYLON.HemisphericLight("light1", BABYLON.Vector3.Up(), scene);
  light.intensity = 0.7;
  
  // 创建球体
  const sphere = BABYLON.MeshBuilder.CreateSphere(
    "sphere",
    { diameter: 2, segments: 32 },
    scene
  );
  sphere.position.y = 1;
  
  // 球体材质
  const sphereMaterial = new BABYLON.StandardMaterial("sphereMaterial", scene);
  sphereMaterial.diffuseColor = new BABYLON.Color3(0.2, 0.5, 1);
  sphereMaterial.specularColor = new BABYLON.Color3(1, 1, 1);
  sphereMaterial.specularPower = 32;
  sphere.material = sphereMaterial;


  const box1 = BABYLON.MeshBuilder.CreateBox("box", { size: 2 }, scene);
  box1.position.x = 2;

  
  // 创建地面
  const ground = BABYLON.MeshBuilder.CreateGround(
    "ground",
    { width: 10, height: 10 },
    scene
  );
  
  // 地面材质
  const groundMaterial = new BABYLON.StandardMaterial("groundMaterial", scene);
  groundMaterial.diffuseColor = new BABYLON.Color3(0.8, 0.8, 0.8);
  ground.material = groundMaterial;
  
  // 球体旋转动画
  scene.registerBeforeRender(() => {
    sphere.rotation.y += 0.01;
  });
  
  return scene;
};

// 组件挂载时初始化场景
onMounted(() => {
  sceneA = createSceneA();
  
  // 启动渲染循环
  engine.runRenderLoop(() => {
    sceneA.render();
  });
  
  // 窗口大小变化时调整
  const handleResize = () => {
    engine.resize();
  };
  
  window.addEventListener('resize', handleResize);
  
  // 组件卸载时清理事件监听
  onUnmounted(() => {
    window.removeEventListener('resize', handleResize);
  });
});

// 组件卸载时清理资源
onUnmounted(() => {
  if (engine) {
    engine.dispose();
  }
});
</script>

<style scoped>
.babylon-container {
  position: relative;
  width: 100%;
  height: 520px;
  background-color: #f0f0f0;
  overflow: hidden;
}

.render-canvas {
  width: 100%;
  height: 100%;
  touch-action: none;
}

.info {
  position: fixed;
  top: 10px;
  left: 10px;
  background: rgba(255, 255, 255, 0.8);
  padding: 10px;
  border-radius: 5px;
  font-family: Arial, sans-serif;
  font-size: 14px;
  z-index: 100;
}
</style>