| name | babylonjs-engine |
| description | Comprehensive skill for Babylon.js 3D web rendering engine. Use this skill when building real-time 3D experiences, browser-based games, interactive visualizations, or immersive web applications. Triggers on tasks involving Babylon.js, 3D scenes, WebGL/WebGPU rendering, entity-component systems, physics simulations, PBR materials, shadow mapping, or 3D model loading. Alternative to Three.js with built-in editor integration and game engine features. |
Babylon.js Engine Skill
Related Skills
- threejs-webgl: Alternative 3D engine
- react-three-fiber: React integration for 3D
- gsap-scrolltrigger: Animation library
- motion-framer: UI animations
Core Concepts
1. Engine and Scene Initialization
Basic Setup
const canvas = document.getElementById('renderCanvas');
const engine = new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true
});
const scene = new BABYLON.Scene(engine);
engine.runRenderLoop(() => {
scene.render();
});
window.addEventListener('resize', () => {
engine.resize();
});
ES6/TypeScript Setup
import { Engine } from '@babylonjs/core/Engines/engine';
import { Scene } from '@babylonjs/core/scene';
import { FreeCamera } from '@babylonjs/core/Cameras/freeCamera';
import { Vector3 } from '@babylonjs/core/Maths/math.vector';
import { HemisphericLight } from '@babylonjs/core/Lights/hemisphericLight';
import { CreateSphere } from '@babylonjs/core/Meshes/Builders/sphereBuilder';
const canvas = document.getElementById('renderCanvas') as HTMLCanvasElement;
const engine = new Engine(canvas);
const scene = new Scene(engine);
const camera = new FreeCamera('camera1', new Vector3(0, 5, -10), scene);
camera.setTarget(Vector3.Zero());
camera.attachControl(canvas, true);
const light = new HemisphericLight('light1', new Vector3(0, 1, 0), scene);
light.intensity = 0.7;
const sphere = CreateSphere('sphere1', { segments: 16, diameter: 2 }, scene);
sphere.position.y = 2;
engine.runRenderLoop(() => {
scene.render();
});
Scene Configuration Options
const scene = new BABYLON.Scene(engine, {
useGeometryUniqueIdsMap: true,
useMaterialMeshMap: true,
useClonedMeshMap: true
});
2. Camera Systems
Free Camera (FPS-style)
const camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, -10), scene);
camera.setTarget(BABYLON.Vector3.Zero());
camera.attachControl(canvas, true);
camera.speed = 0.5;
camera.angularSensibility = 2000;
camera.keysUp = [87];
camera.keysDown = [83];
camera.keysLeft = [65];
camera.keysRight = [68];
Arc Rotate Camera (Orbit)
const camera = new BABYLON.ArcRotateCamera(
'camera',
-Math.PI / 2,
Math.PI / 2.5,
15,
new BABYLON.Vector3(0, 0, 0),
scene
);
camera.attachControl(canvas, true);
camera.lowerRadiusLimit = 5;
camera.upperRadiusLimit = 50;
camera.lowerBetaLimit = 0.1;
camera.upperBetaLimit = Math.PI / 2;
Universal Camera (Advanced)
const camera = new BABYLON.UniversalCamera('camera', new BABYLON.Vector3(0, 5, -10), scene);
camera.setTarget(BABYLON.Vector3.Zero());
camera.attachControl(canvas, true);
camera.checkCollisions = true;
camera.applyGravity = true;
camera.ellipsoid = new BABYLON.Vector3(1, 1, 1);
3. Lighting Systems
Hemispheric Light (Ambient)
const light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), scene);
light.intensity = 0.7;
light.diffuse = new BABYLON.Color3(1, 1, 1);
light.specular = new BABYLON.Color3(1, 1, 1);
light.groundColor = new BABYLON.Color3(0, 0, 0);
Directional Light (Sun-like)
const light = new BABYLON.DirectionalLight('dirLight', new BABYLON.Vector3(-1, -2, -1), scene);
light.position = new BABYLON.Vector3(20, 40, 20);
light.intensity = 0.5;
const shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
shadowGenerator.useExponentialShadowMap = true;
Point Light (Omni-directional)
const light = new BABYLON.PointLight('pointLight', new BABYLON.Vector3(0, 10, 0), scene);
light.intensity = 0.7;
light.diffuse = new BABYLON.Color3(1, 0, 0);
light.specular = new BABYLON.Color3(0, 1, 0);
light.range = 100;
light.radius = 0.1;
Spot Light (Focused)
const light = new BABYLON.SpotLight(
'spotLight',
new BABYLON.Vector3(0, 10, 0),
new BABYLON.Vector3(0, -1, 0),
Math.PI / 3,
2,
scene
);
light.intensity = 0.8;
Light Optimization (Include Only Specific Meshes)
light.includedOnlyMeshes = [mesh1, mesh2, mesh3];
light.excludedMeshes = [mesh4, mesh5];
4. Mesh Creation
Built-in Shapes
const box = BABYLON.MeshBuilder.CreateBox('box', {
size: 2,
width: 2,
height: 2,
depth: 2
}, scene);
const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {
diameter: 2,
segments: 32,
diameterX: 2,
diameterY: 2,
diameterZ: 2,
arc: 1,
slice: 1
}, scene);
const cylinder = BABYLON.MeshBuilder.CreateCylinder('cylinder', {
height: 3,
diameter: 2,
tessellation: 24
}, scene);
const plane = BABYLON.MeshBuilder.CreatePlane('plane', {
size: 5,
width: 5,
height: 5
}, scene);
const ground = BABYLON.MeshBuilder.CreateGround('ground', {
width: 10,
height: 10,
subdivisions: 2
}, scene);
const ground = BABYLON.MeshBuilder.CreateGroundFromHeightMap('ground', 'heightmap.png', {
width: 100,
height: 100,
subdivisions: 100,
minHeight: 0,
maxHeight: 10
}, scene);
const torus = BABYLON.MeshBuilder.CreateTorus('torus', {
diameter: 3,
thickness: 1,
tessellation: 16
}, scene);
const torusKnot = BABYLON.MeshBuilder.CreateTorusKnot('torusKnot', {
radius: 2,
tube: 0.6,
radialSegments: 64,
tubularSegments: 8,
p: 2,
q: 3
}, scene);
Mesh Transformations
mesh.position = new BABYLON.Vector3(0, 5, 10);
mesh.position.x = 5;
mesh.position.y = 2;
mesh.rotation = new BABYLON.Vector3(0, Math.PI / 2, 0);
mesh.rotation.y = Math.PI / 4;
mesh.scaling = new BABYLON.Vector3(2, 2, 2);
mesh.scaling.x = 1.5;
mesh.lookAt(new BABYLON.Vector3(0, 0, 0));
childMesh.parent = parentMesh;
Mesh Properties
mesh.isVisible = true;
mesh.visibility = 0.5;
mesh.isPickable = true;
mesh.checkCollisions = true;
mesh.cullingStrategy = BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY;
mesh.receiveShadows = true;
5. Materials
Standard Material
const material = new BABYLON.StandardMaterial('material', scene);
material.diffuseColor = new BABYLON.Color3(1, 0, 1);
material.specularColor = new BABYLON.Color3(0.5, 0.6, 0.87);
material.emissiveColor = new BABYLON.Color3(0, 0, 0);
material.ambientColor = new BABYLON.Color3(0.23, 0.98, 0.53);
material.diffuseTexture = new BABYLON.Texture('diffuse.png', scene);
material.specularTexture = new BABYLON.Texture('specular.png', scene);
material.emissiveTexture = new BABYLON.Texture('emissive.png', scene);
material.ambientTexture = new BABYLON.Texture('ambient.png', scene);
material.bumpTexture = new BABYLON.Texture('normal.png', scene);
material.opacityTexture = new BABYLON.Texture('opacity.png', scene);
material.alpha = 0.8;
material.backFaceCulling = true;
material.wireframe = false;
material.specularPower = 64;
mesh.material = material;
PBR Material (Physically Based Rendering)
const pbr = new BABYLON.PBRMaterial('pbr', scene);
pbr.albedoColor = new BABYLON.Color3(1, 1, 1);
pbr.albedoTexture = new BABYLON.Texture('albedo.png', scene);
pbr.metallic = 1.0;
pbr.roughness = 0.5;
pbr.metallicTexture = new BABYLON.Texture('metallic.png', scene);
pbr.albedoTexture = new BABYLON.Texture('albedo.png', scene);
pbr.reflectivityTexture = new BABYLON.Texture('reflectivity.png', scene);
pbr.environmentTexture = BABYLON.CubeTexture.CreateFromPrefilteredData('environment.dds', scene);
pbr.bumpTexture = new BABYLON.Texture('normal.png', scene);
pbr.ambientTexture = new BABYLON.Texture('ao.png', scene);
pbr.emissiveTexture = new BABYLON.Texture('emissive.png', scene);
mesh.material = pbr;
Multi-Materials
const multiMat = new BABYLON.MultiMaterial('multiMat', scene);
multiMat.subMaterials.push(material1);
multiMat.subMaterials.push(material2);
multiMat.subMaterials.push(material3);
mesh.material = multiMat;
mesh.subMeshes = [];
mesh.subMeshes.push(new BABYLON.SubMesh(0, 0, verticesCount, 0, indicesCount1, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(1, 0, verticesCount, indicesCount1, indicesCount2, mesh));
6. Model Loading
GLTF/GLB Import
BABYLON.SceneLoader.Append('path/to/', 'model.gltf', scene, function(scene) {
console.log('Model loaded');
});
BABYLON.SceneLoader.ImportMesh('', 'path/to/', 'model.gltf', scene, function(meshes) {
const mesh = meshes[0];
mesh.position.y = 5;
});
const result = await BABYLON.SceneLoader.ImportMeshAsync(
null,
'https://assets.babylonjs.com/meshes/',
'village.glb',
scene
);
console.log('Loaded meshes:', result.meshes);
const result = await BABYLON.SceneLoader.AppendAsync(
'',
'data:' + arrayBuffer,
scene
);
Asset Manager (Batch Loading)
const assetsManager = new BABYLON.AssetsManager(scene);
const meshTask = assetsManager.addMeshTask('model', '', 'path/to/', 'model.gltf');
meshTask.onSuccess = function(task) {
task.loadedMeshes[0].position = new BABYLON.Vector3(0, 0, 0);
};
const textureTask = assetsManager.addTextureTask('texture', 'texture.png');
textureTask.onSuccess = function(task) {
material.diffuseTexture = task.texture;
};
assetsManager.onFinish = function(tasks) {
console.log('All assets loaded');
engine.runRenderLoop(() => scene.render());
};
assetsManager.load();
7. Physics Engine
Havok Physics Setup
import HavokPhysics from '@babylonjs/havok';
const havokInstance = await HavokPhysics();
const havokPlugin = new BABYLON.HavokPlugin(true, havokInstance);
scene.enablePhysics(new BABYLON.Vector3(0, -9.8, 0), havokPlugin);
const sphereAggregate = new BABYLON.PhysicsAggregate(
sphere,
BABYLON.PhysicsShapeType.SPHERE,
{ mass: 1, restitution: 0.75 },
scene
);
const groundAggregate = new BABYLON.PhysicsAggregate(
ground,
BABYLON.PhysicsShapeType.BOX,
{ mass: 0 },
scene
);
Physics Shapes
BABYLON.PhysicsShapeType.SPHERE
BABYLON.PhysicsShapeType.BOX
BABYLON.PhysicsShapeType.CAPSULE
BABYLON.PhysicsShapeType.CYLINDER
BABYLON.PhysicsShapeType.CONVEX_HULL
BABYLON.PhysicsShapeType.MESH
BABYLON.PhysicsShapeType.HEIGHTFIELD
Physics Body Control
const body = aggregate.body;
body.applyForce(
new BABYLON.Vector3(0, 10, 0),
new BABYLON.Vector3(0, 0, 0)
);
body.applyImpulse(
new BABYLON.Vector3(0, 5, 0),
new BABYLON.Vector3(0, 0, 0)
);
body.setLinearVelocity(new BABYLON.Vector3(0, 5, 0));
body.setAngularVelocity(new BABYLON.Vector3(0, 1, 0));
body.setMassProperties({ mass: 2 });
body.setCollisionCallbackEnabled(true);
8. Animations
Direct Animation
BABYLON.Animation.CreateAndStartAnimation(
'anim',
mesh,
'position.y',
30,
120,
mesh.position.y,
10,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);
Animation Class
const animation = new BABYLON.Animation(
'myAnimation',
'position.x',
30,
BABYLON.Animation.ANIMATIONTYPE_FLOAT,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);
const keys = [
{ frame: 0, value: 0 },
{ frame: 30, value: 10 },
{ frame: 60, value: 0 }
];
animation.setKeys(keys);
mesh.animations.push(animation);
scene.beginAnimation(mesh, 0, 60, true);
Animation Groups
const animationGroup = new BABYLON.AnimationGroup('group', scene);
animationGroup.addTargetedAnimation(animation1, mesh1);
animationGroup.addTargetedAnimation(animation2, mesh2);
animationGroup.play();
animationGroup.pause();
animationGroup.stop();
animationGroup.speedRatio = 2.0;
animationGroup.onAnimationEndObservable.add(() => {
console.log('Animation complete');
});
Skeleton Animations (from imported models)
const skeleton = result.skeletons[0];
const ranges = skeleton.getAnimationRanges();
scene.beginAnimation(skeleton, 0, 100, true);
result.animationGroups[0].play();
result.animationGroups[0].setWeightForAllAnimatables(0.5);
Common Patterns
Pattern 1: Scene Setup with Default Environment
const createScene = function() {
const scene = new BABYLON.Scene(engine);
scene.createDefaultCameraOrLight(true, true, true);
const env = scene.createDefaultEnvironment({
createGround: true,
createSkybox: true,
skyboxSize: 150,
groundSize: 50
});
const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {diameter: 2}, scene);
sphere.position.y = 1;
return scene;
};
Pattern 2: Async Scene Loading
const createScene = async function() {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 10, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene);
const result = await BABYLON.SceneLoader.ImportMeshAsync(
null,
'https://assets.babylonjs.com/meshes/',
'village.glb',
scene
);
const havokInstance = await HavokPhysics();
const havokPlugin = new BABYLON.HavokPlugin(true, havokInstance);
scene.enablePhysics(new BABYLON.Vector3(0, -9.8, 0), havokPlugin);
return scene;
};
createScene().then(scene => {
engine.runRenderLoop(() => scene.render());
});
Pattern 3: Interactive Picking
scene.onPointerDown = function(evt, pickResult) {
if (pickResult.hit) {
console.log('Picked mesh:', pickResult.pickedMesh.name);
console.log('Pick point:', pickResult.pickedPoint);
pickResult.pickedMesh.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
}
};
mesh.actionManager = new BABYLON.ActionManager(scene);
mesh.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(
BABYLON.ActionManager.OnPickTrigger,
function() {
console.log('Mesh clicked');
}
)
);
Pattern 4: Post-Processing Effects
const pipeline = new BABYLON.DefaultRenderingPipeline('pipeline', true, scene, [camera]);
pipeline.samples = 4;
pipeline.fxaaEnabled = true;
pipeline.bloomEnabled = true;
pipeline.bloomThreshold = 0.8;
pipeline.bloomWeight = 0.5;
pipeline.bloomKernel = 64;
pipeline.depthOfFieldEnabled = true;
pipeline.depthOfFieldBlurLevel = BABYLON.DepthOfFieldEffectBlurLevel.Low;
pipeline.depthOfField.focusDistance = 2000;
pipeline.depthOfField.focalLength = 50;
const glowLayer = new BABYLON.GlowLayer('glow', scene);
glowLayer.intensity = 0.5;
const highlightLayer = new BABYLON.HighlightLayer('highlight', scene);
highlightLayer.addMesh(mesh, BABYLON.Color3.Green());
Pattern 5: GUI (2D UI)
import { AdvancedDynamicTexture, Button, TextBlock, Rectangle } from '@babylonjs/gui';
const advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI('UI');
const button = BABYLON.GUI.Button.CreateSimpleButton('button', 'Click Me');
button.width = '150px';
button.height = '40px';
button.color = 'white';
button.background = 'green';
button.onPointerUpObservable.add(() => {
console.log('Button clicked');
});
advancedTexture.addControl(button);
const text = new BABYLON.GUI.TextBlock();
text.text = 'Hello World';
text.color = 'white';
text.fontSize = 24;
advancedTexture.addControl(text);
const plane = BABYLON.MeshBuilder.CreatePlane('plane', {size: 2}, scene);
const advancedTexture3D = BABYLON.GUI.AdvancedDynamicTexture.CreateForMesh(plane);
const button3D = BABYLON.GUI.Button.CreateSimpleButton('button3D', 'Click Me');
advancedTexture3D.addControl(button3D);
Pattern 6: Shadow Mapping
const light = new BABYLON.DirectionalLight('light', new BABYLON.Vector3(-1, -2, -1), scene);
light.position = new BABYLON.Vector3(20, 40, 20);
const shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
shadowGenerator.useExponentialShadowMap = true;
shadowGenerator.usePoissonSampling = true;
shadowGenerator.addShadowCaster(sphere);
shadowGenerator.addShadowCaster(box);
ground.receiveShadows = true;
Pattern 7: Particle Systems
const particleSystem = new BABYLON.ParticleSystem('particles', 2000, scene);
particleSystem.particleTexture = new BABYLON.Texture('particle.png', scene);
particleSystem.emitter = new BABYLON.Vector3(0, 5, 0);
particleSystem.minEmitBox = new BABYLON.Vector3(-1, 0, 0);
particleSystem.maxEmitBox = new BABYLON.Vector3(1, 0, 0);
particleSystem.color1 = new BABYLON.Color4(0.7, 0.8, 1.0, 1.0);
particleSystem.color2 = new BABYLON.Color4(0.2, 0.5, 1.0, 1.0);
particleSystem.colorDead = new BABYLON.Color4(0, 0, 0.2, 0.0);
particleSystem.minSize = 0.1;
particleSystem.maxSize = 0.5;
particleSystem.minLifeTime = 0.3;
particleSystem.maxLifeTime = 1.5;
particleSystem.emitRate = 1500;
particleSystem.direction1 = new BABYLON.Vector3(-1, 8, 1);
particleSystem.direction2 = new BABYLON.Vector3(1, 8, -1);
particleSystem.gravity = new BABYLON.Vector3(0, -9.81, 0);
particleSystem.start();
Integration Patterns
Pattern 1: React Integration
import { useEffect, useRef } from 'react';
import * as BABYLON from '@babylonjs/core';
function BabylonScene() {
const canvasRef = useRef(null);
const engineRef = useRef(null);
const sceneRef = useRef(null);
useEffect(() => {
if (!canvasRef.current) return;
const engine = new BABYLON.Engine(canvasRef.current, true);
engineRef.current = engine;
const scene = new BABYLON.Scene(engine);
sceneRef.current = scene;
const camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 10, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvasRef.current, true);
const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene);
const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {diameter: 2}, scene);
engine.runRenderLoop(() => {
scene.render();
});
const handleResize = () => engine.resize();
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
scene.dispose();
engine.dispose();
};
}, []);
return (
<canvas
ref={canvasRef}
style={{ width: '100%', height: '100vh' }}
/>
);
}
Pattern 2: WebXR (VR/AR)
const createScene = async function() {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.FreeCamera('camera', new BABYLON.Vector3(0, 5, -10), scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene);
const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {diameter: 2}, scene);
sphere.position.y = 1;
const env = scene.createDefaultEnvironment();
const xrHelper = await scene.createDefaultXRExperienceAsync({
floorMeshes: [env.ground],
disableTeleportation: false
});
xrHelper.input.onControllerAddedObservable.add((controller) => {
controller.onMotionControllerInitObservable.add((motionController) => {
const trigger = motionController.getMainComponent();
trigger.onButtonStateChangedObservable.add(() => {
if (trigger.pressed) {
console.log('Trigger pressed');
}
});
});
});
return scene;
};
Pattern 3: Node Material (Visual Shader Editor)
const nodeMaterial = await BABYLON.NodeMaterial.ParseFromSnippetAsync('#SNIPPET_ID', scene);
nodeMaterial.build();
mesh.material = nodeMaterial;
const nodeMaterial = new BABYLON.NodeMaterial('node', scene);
const positionInput = new BABYLON.InputBlock('position');
positionInput.setAsAttribute('position');
const worldPos = new BABYLON.TransformBlock('worldPos');
nodeMaterial.addOutputNode(worldPos);
Performance Optimization
1. Mesh Optimization
const merged = BABYLON.Mesh.MergeMeshes(
[mesh1, mesh2, mesh3],
true,
true,
undefined,
false,
true
);
const instance1 = mesh.createInstance('instance1');
const instance2 = mesh.createInstance('instance2');
instance1.position.x = 5;
instance2.position.x = -5;
const buffer = new Float32Array(16 * count);
mesh.thinInstanceSetBuffer('matrix', buffer, 16);
mesh.freezeWorldMatrix();
material.freeze();
const simplified = mesh.simplify(
[
{ quality: 0.8, distance: 10 },
{ quality: 0.4, distance: 50 },
{ quality: 0.2, distance: 100 }
],
true,
BABYLON.SimplificationType.QUADRATIC
);
2. Scene Optimization
const options = new BABYLON.SceneOptimizerOptions();
options.addOptimization(new BABYLON.HardwareScalingOptimization(0, 1));
options.addOptimization(new BABYLON.ShadowsOptimization(1));
options.addOptimization(new BABYLON.PostProcessesOptimization(2));
options.addOptimization(new BABYLON.LensFlaresOptimization(3));
options.addOptimization(new BABYLON.ParticlesOptimization(4));
options.addOptimization(new BABYLON.TextureOptimization(5, 512));
options.addOptimization(new BABYLON.RenderTargetsOptimization(6));
options.addOptimization(new BABYLON.MergeMeshesOptimization(7));
const optimizer = new BABYLON.SceneOptimizer(scene, options);
optimizer.start();
const octree = scene.createOrUpdateSelectionOctree();
scene.blockMaterialDirtyMechanism = true;
scene.skipPointerMovePicking = true;
scene.freezeActiveMeshes();
3. Rendering Optimization
engine.setHardwareScalingLevel(0.5);
scene.onBeforeRenderObservable.add(() => {
const fps = engine.getFps();
if (fps < 30) {
engine.setHardwareScalingLevel(2);
} else if (fps > 55) {
engine.setHardwareScalingLevel(1);
}
});
scene.useDelayedTextureLoading = true;
mesh.cullingStrategy = BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY;
4. Texture Optimization
const texture = new BABYLON.Texture('texture.dds', scene);
texture.updateSamplingMode(BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
texture.anisotropicFilteringLevel = 4;
const texture = new BABYLON.Texture('texture.ktx2', scene);
Common Pitfalls
Pitfall 1: Memory Leaks
Problem: Not disposing resources
function createAndRemoveMesh() {
const mesh = BABYLON.MeshBuilder.CreateBox('box', {}, scene);
scene.removeMesh(mesh);
}
Solution: Properly dispose
function createAndRemoveMesh() {
const mesh = BABYLON.MeshBuilder.CreateBox('box', {}, scene);
mesh.dispose();
}
scene.dispose();
engine.dispose();
Pitfall 2: Performance Issues with Too Many Draw Calls
Problem: Each mesh = one draw call
for (let i = 0; i < 1000; i++) {
const box = BABYLON.MeshBuilder.CreateBox('box' + i, {}, scene);
box.position.x = i;
}
Solution: Use instances or merge
const box = BABYLON.MeshBuilder.CreateBox('box', {}, scene);
for (let i = 0; i < 1000; i++) {
const instance = box.createInstance('instance' + i);
instance.position.x = i;
}
Pitfall 3: Blocking the Main Thread
Problem: Heavy computations blocking render
function createManyMeshes() {
for (let i = 0; i < 10000; i++) {
const mesh = BABYLON.MeshBuilder.CreateSphere('sphere' + i, {}, scene);
}
}
Solution: Use async/incremental loading
async function createManyMeshes() {
for (let i = 0; i < 10000; i++) {
const mesh = BABYLON.MeshBuilder.CreateSphere('sphere' + i, {}, scene);
if (i % 100 === 0) {
await new Promise(resolve => setTimeout(resolve, 0));
}
}
}
Pitfall 4: Incorrect Camera Controls
Problem: Camera not responding
const camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 10, BABYLON.Vector3.Zero(), scene);
Solution: Always attach controls
const camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 10, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
Pitfall 5: Not Handling Async Operations
Problem: Using scene before it's ready
BABYLON.SceneLoader.ImportMesh('', 'path/', 'model.gltf', scene);
const mesh = scene.getMeshByName('meshName');
Solution: Use callbacks or async/await
const result = await BABYLON.SceneLoader.ImportMeshAsync('', 'path/', 'model.gltf', scene);
const mesh = scene.getMeshByName('meshName');
BABYLON.SceneLoader.ImportMesh('', 'path/', 'model.gltf', scene, function(meshes) {
const mesh = meshes[0];
});
Pitfall 6: Physics Not Working
Problem: Forgot to enable physics or create aggregates
const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {}, scene);
sphere.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, {mass: 1}, scene);
Solution: Enable physics first, use aggregates
const havokInstance = await HavokPhysics();
const havokPlugin = new BABYLON.HavokPlugin(true, havokInstance);
scene.enablePhysics(new BABYLON.Vector3(0, -9.8, 0), havokPlugin);
const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {}, scene);
const aggregate = new BABYLON.PhysicsAggregate(
sphere,
BABYLON.PhysicsShapeType.SPHERE,
{mass: 1},
scene
);
Advanced Topics
1. Custom Shaders
BABYLON.Effect.ShadersStore['customVertexShader'] = `
precision highp float;
attribute vec3 position;
attribute vec2 uv;
uniform mat4 worldViewProjection;
varying vec2 vUV;
void main(void) {
gl_Position = worldViewProjection * vec4(position, 1.0);
vUV = uv;
}
`;
BABYLON.Effect.ShadersStore['customFragmentShader'] = `
precision highp float;
varying vec2 vUV;
uniform sampler2D textureSampler;
void main(void) {
gl_FragColor = texture2D(textureSampler, vUV);
}
`;
const shaderMaterial = new BABYLON.ShaderMaterial('shader', scene, {
vertex: 'custom',
fragment: 'custom'
}, {
attributes: ['position', 'uv'],
uniforms: ['worldViewProjection']
});
2. Compute Shaders
const computeShader = new BABYLON.ComputeShader('compute', engine, {
computeSource: `
#version 450
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout(std430, binding = 0) buffer OutputBuffer { vec4 data[]; } outputBuffer;
void main() {
uint index = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * 8u;
outputBuffer.data[index] = vec4(1.0, 0.0, 0.0, 1.0);
}
`
});
3. Procedural Textures
const noiseTexture = new BABYLON.NoiseProceduralTexture('noise', 256, scene);
noiseTexture.octaves = 4;
noiseTexture.persistence = 0.8;
noiseTexture.animationSpeedFactor = 5;
material.emissiveTexture = noiseTexture;
Debugging
scene.debugLayer.show();
scene.forceShowBoundingBoxes = true;
material.wireframe = true;
setInterval(() => {
console.log('FPS:', engine.getFps());
}, 1000);
const instrumentation = new BABYLON.SceneInstrumentation(scene);
instrumentation.captureFrameTime = true;
console.log('Frame time:', instrumentation.frameTimeCounter.average);
Resources
Version Notes
This skill is based on Babylon.js 7.x. For latest features, consult the official documentation.