Babylon.js 知识点总结
Babylon.js 是一个强大的、功能丰富的、开源的 3D 引擎,能够渲染交互式 3D 和 2D 图形,使用 HTML5 和 WebGL。
核心概念
三大核心组件
Babylon.js 的核心由三个组件构成:
- Engine(引擎) - 渲染引擎,负责与 WebGL 交互
- Scene(场景) - 3D 世界的容器
- Camera(相机) - 定义观察者的视角
// 基本结构
const canvas = document.getElementById('renderCanvas');
const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, -10), scene);
// 渲 染循环
engine.runRenderLoop(() => {
scene.render();
});
Engine(引擎)
引擎是 Babylon.js 的核心,负责初始化 WebGL 上下文和管理渲染循环。
// 创建引擎
const engine = new BABYLON.Engine(canvas, antialias, options, adaptToDeviceRatio);
// 引擎选项
const engine = new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true,
antialias: true,
alpha: false,
premultipliedAlpha: false,
powerPreference: "high-performance"
});
// 适配设备像素比
engine.setHardwareScalingLevel(1 / window.devicePixelRatio);
// 渲染循环
engine.runRenderLoop(() => {
scene.render();
});
// 响应式处理
window.addEventListener('resize', () => {
engine.resize();
});
引擎特性
- WebGL 1.0 和 2.0 支持
- WebGPU 支持(实验性)
- 自动 降级:WebGL 2.0 → WebGL 1.0 → 2D Canvas
- 多场景支持:一个引擎可以渲染多个场景
Scene(场景)
场景是所有对象的容器,管理渲染、动画和事件。
const scene = new BABYLON.Scene(engine);
// 设置背景色
scene.clearColor = new BABYLON.Color3(0.1, 0.1, 0.1);
// 设置环境色
scene.ambientColor = new BABYLON.Color3(0.3, 0.3, 0.3);
// 启用雾效果
scene.fogMode = BABYLON.Scene.FOGMODE_EXP;
scene.fogDensity = 0.01;
scene.fogColor = new BABYLON.Color3(0.9, 0.9, 0.85);
// 启用阴影
scene.shadowsEnabled = true;
// 启用物理引擎
const gravityVector = new BABYLON.Vector3(0, -9.81, 0);
const physicsPlugin = new BABYLON.CannonJSPlugin();
scene.enablePhysics(gravityVector, physicsPlugin);
场景属性
clearColor: 场景背景色ambientColor: 环境光颜色fogMode: 雾模式(NONE/EXP/EXP2/LINEAR)shadowsEnabled: 是否启用阴影lightsEnabled: 是否启用光照texturesEnabled: 是否启用纹理
Camera(相机)
FreeCamera(自由相机)
可以自由移动和旋转的相机。
const camera = new BABYLON.FreeCamera('camera1',
new BABYLON.Vector3(0, 5, -10),
scene
);
camera.setTarget(BABYLON.Vector3.Zero());
camera.attachControls(canvas, true);
ArcRotateCamera(弧形旋转相机)
围绕目标点旋转的相机,适合查看对象。
const camera = new BABYLON.ArcRotateCamera(
'camera1',
-Math.PI / 2, // alpha(水平角度)
Math.PI / 2.5, // beta(垂直角度)
10, // radius(距离)
BABYLON.Vector3.Zero(), // target(目标点)
scene
);
camera.attachControls(canvas, true);
UniversalCamera(通用相机)
支持触摸和游戏手柄的相机。
const camera = new BABYLON.UniversalCamera('camera1',
new BABYLON.Vector3(0, 0, -10),
scene
);
camera.attachControls(canvas, true);
FollowCamera(跟随相机)
跟随目标的相机。
const camera = new BABYLON.FollowCamera('camera1',
new BABYLON.Vector3(0, 10, -10),
scene
);
camera.lockedTarget = mesh;
camera.radius = 10;
camera.heightOffset = 5;
相机控制
// 使用 ArcRotateCamera 的控制器
camera.attachControls(canvas, true);
// 禁用控制
camera.detachControls();
// 设置相机限制
camera.lowerBetaLimit = 0.1;
camera.upperBetaLimit = Math.PI / 2.2;
camera.lowerRadiusLimit = 5;
camera.upperRadiusLimit = 20;
Mesh(网格)
内置网格
// 立方体
const box = BABYLON.MeshBuilder.CreateBox('box', {
size: 2,
width: 1,
height: 1,
depth: 1
}, scene);
// 球体
const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {
diameter: 2,
segments: 32
}, scene);
// 平面
const plane = BABYLON.MeshBuilder.CreatePlane('plane', {
size: 2,
width: 1,
height: 1
}, scene);
// 圆柱体
const cylinder = BABYLON.MeshBuilder.CreateCylinder('cylinder', {
diameter: 2,
height: 3,
tessellation: 32
}, scene);
// 圆环
const torus = BABYLON.MeshBuilder.CreateTorus('torus', {
diameter: 2,
thickness: 0.5,
tessellation: 32
}, scene);
// 地面
const ground = BABYLON.MeshBuilder.CreateGround('ground', {
width: 10,
height: 10,
subdivisions: 2
}, scene);
自定义网格
// 使用顶点创建自定义网格
const customMesh = new BABYLON.Mesh('custom', scene);
const positions = [
-1, -1, 0,
1, -1, 0,
0, 1, 0
];
const indices = [0, 1, 2];
const vertexData = new BABYLON.VertexData();
vertexData.positions = positions;
vertexData.indices = indices;
vertexData.normals = [];
BABYLON.VertexData.ComputeNormals(positions, indices, vertexData.normals);
vertexData.applyToMesh(customMesh);
网格操作
// 位置
mesh.position = new BABYLON.Vector3(1, 2, 3);
mesh.position.x = 1;
// 旋转(弧度制)
mesh.rotation = new BABYLON.Vector3(0, Math.PI / 4, 0);
mesh.rotationQuaternion = new BABYLON.Quaternion();
// 缩放
mesh.scaling = new BABYLON.Vector3(2, 2, 2);
// 父级关系
mesh.setParent(parentMesh);
// 克隆
const clonedMesh = mesh.clone('clonedMesh');
// 合并网格
const mergedMesh = BABYLON.Mesh.MergeMeshes([mesh1, mesh2], true, true);
Material(材质)
StandardMaterial(标准材质)
PBR 标准材质,支持物理渲染。
const material = new BABYLON.StandardMaterial('material', scene);
material.diffuseColor = new BABYLON.Color3(1, 0, 0); // 漫反射颜色
material.specularColor = new BABYLON.Color3(1, 1, 1); // 高光颜色
material.emissiveColor = new BABYLON.Color3(0, 0, 0); // 自发光颜色
material.ambientColor = new BABYLON.Color3(0.2, 0.2, 0.2); // 环境色
material.roughness = 0.5; // 粗糙度
material.metallic = 0.5; // 金属度
material.metallicF0Factor = 0.5; // 金属 F0 因子
material.alpha = 1.0; // 透明度
material.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE;
material.backFaceCulling = true; // 背面剔除
material.twoSidedLighting = false; // 双面光照
material.wireframe = false; // 线框模式
PBRMaterial(PBR 材质)
更高级的物理渲染材质。
const pbr = new BABYLON.PBRMaterial('pbr', scene);
pbr.baseColor = new BABYLON.Color3(1, 0, 0);
pbr.metallic = 0.9;
pbr.roughness = 0.1;
// 纹理
pbr.baseTexture = new BABYLON.Texture('diffuse.jpg', scene);
pbr.normalTexture = new BABYLON.Texture('normal.jpg', scene);
pbr.metallicRoughnessTexture = new BABYLON.Texture('metallicRoughness.jpg', scene);
pbr.occlusionTexture = new BABYLON.Texture('ao.jpg', scene);
pbr.emissiveTexture = new BABYLON.Texture('emissive.jpg', scene);
// 环境贴图
pbr.environmentTexture = hdrTexture;
材质类型
// MeshBasicMaterial - 不受光照影响
const basicMaterial = new BABYLON.StandardMaterial('basic', scene);
basicMaterial.disableLighting = true;
// MeshPhongMaterial - 高光材质
const phongMaterial = new BABYLON.StandardMaterial('phong', scene);
phongMaterial.specularPower = 32;
// MeshLambertMaterial - 漫反射材质
const lambertMaterial = new BABYLON.StandardMaterial('lambert', scene);
lambertMaterial.specularColor = BABYLON.Color3.Black();
// ShaderMaterial - 自定义着色器
const shaderMaterial = new BABYLON.ShaderMaterial('shader', scene, {
vertex: 'custom',
fragment: 'custom'
}, {
attributes: ['position', 'normal', 'uv'],
uniforms: ['worldViewProjection']
});
纹理
// 加载纹理
const texture = new BABYLON.Texture('path/to/texture.jpg', scene);
// 纹理设置
texture.uScale = 2; // U 方向缩放
texture.vScale = 2; // V 方向缩放
texture.uOffset = 0.5; // U 方向偏移
texture.vOffset = 0.5; // V 方向偏移
texture.uAng = Math.PI / 4; // U 方向旋转
texture.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE; // 重复模式
texture.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
// 立方体贴图
const cubeTexture = new BABYLON.CubeTexture('path/to/env', scene, null, false, null, null, '.jpg', null, true);
scene.environmentTexture = cubeTexture;
// HDR 环境贴图
const hdrTexture = BABYLON.CubeTexture.CreateFromPrefilteredData('environment.dds', scene);
scene.environmentTexture = hdrTexture;
Light(光照)
光源类型
// 方向光 - 平行光(如太阳光)
const directionalLight = new BABYLON.DirectionalLight('light1',
new BABYLON.Vector3(0, -1, 0),
scene
);
directionalLight.diffuse = new BABYLON.Color3(1, 1, 1);
directionalLight.specular = new BABYLON.Color3(1, 1, 1);
directionalLight.intensity = 1.0;
// 点光源 - 从一点向四周发射
const pointLight = new BABYLON.PointLight('light2',
new BABYLON.Vector3(0, 10, 0),
scene
);
pointLight.diffuse = new BABYLON.Color3(1, 1, 1);
pointLight.range = 100;
// 聚光灯 - 圆锥形光束
const spotLight = new BABYLON.SpotLight('light3',
new BABYLON.Vector3(0, 10, 0),
new BABYLON.Vector3(0, -1, 0),
Math.PI / 4, // 角度
2, // 指数
scene
);
spotLight.diffuse = new BABYLON.Color3(1, 1, 1);
spotLight.range = 100;
// 半球光 - 模拟天空和地面
const hemisphericLight = new BABYLON.HemisphericLight('light4',
new BABYLON.Vector3(0, 1, 0),
scene
);
hemisphericLight.diffuse = new BABYLON.Color3(1, 1, 1);
hemisphericLight.groundColor = new BABYLON.Color3(0, 0, 0);
hemisphericLight.intensity = 0.7;
阴影
// 启用阴影
scene.shadowsEnabled = true;
// 创建阴影生成器
const shadowGenerator = new BABYLON.ShadowGenerator(1024, directionalLight);
shadowGenerator.useBlurExponentialShadowMap = true;
shadowGenerator.blurKernel = 32;
// 添加阴影投射者
shadowGenerator.addShadowCaster(mesh);
// 设置阴影接收者
ground.receiveShadows = true;
// 阴影类型
shadowGenerator.useBlurExponentialShadowMap = true; // 模糊指数阴影
shadowGenerator.usePercentageCloserFiltering = true; // PCF 阴影
shadowGenerator.useContactHardeningShadow = true; // 接触硬化阴影
Animation(动画)
使用 Animation
// 创建动画
const animationBox = new BABYLON.Animation(
'myAnimation',
'position.x',
30, // 帧率
BABYLON.Animation.ANIMATIONTYPE_FLOAT,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);
// 定义关键帧
const keys = [];
keys.push({ frame: 0, value: 0 });
keys.push({ frame: 100, value: 5 });
keys.push({ frame: 200, value: 0 });
animationBox.setKeys(keys);
// 添加到网格
box.animations.push(animationBox);
// 开始动画
scene.beginAnimation(box, 0, 200, true);
使用 AnimationGroup
const animationGroup = new BABYLON.AnimationGroup('group');
// 创建多个动画
const anim1 = BABYLON.Animation.CreateAndStartAnimation(
'anim1',
mesh1,
'position.x',
30,
100,
0,
5,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);
const anim2 = BABYLON.Animation.CreateAndStartAnimation(
'anim2',
mesh2,
'rotation.y',
30,
100,
0,
Math.PI * 2,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);
animationGroup.addTargetedAnimation(anim1, mesh1);
animationGroup.addTargetedAnimation(anim2, mesh2);
animationGroup.play();
使用 AnimationPropertiesOverride
scene.animationPropertiesOverride = new BABYLON.AnimationPropertiesOverride();
scene.animationPropertiesOverride.enableBlending = true;
scene.animationPropertiesOverride.blendingSpeed = 0.1;