babylonjs-engine

Comprehensive skill for Babylon.js 3D web rendering engine. Use this skill when building real-time 3D experiences, browser-based games, interactive…

INSTALLATION
npx skills add https://github.com/freshtechbro/claudedesignskills --skill babylonjs-engine
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

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

// Get canvas element

const canvas = document.getElementById('renderCanvas');

// Create engine

const engine = new BABYLON.Engine(canvas, true, {

preserveDrawingBuffer: true,

stencil: true

});

// Create scene

const scene = new BABYLON.Scene(engine);

// Render loop

engine.runRenderLoop(() => {

scene.render();

});

// Handle resize

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);

// Camera setup

const camera = new FreeCamera('camera1', new Vector3(0, 5, -10), scene);

camera.setTarget(Vector3.Zero());

camera.attachControl(canvas, true);

// Lighting

const light = new HemisphericLight('light1', new Vector3(0, 1, 0), scene);

light.intensity = 0.7;

// Create mesh

const sphere = CreateSphere('sphere1', { segments: 16, diameter: 2 }, scene);

sphere.position.y = 2;

// Render

engine.runRenderLoop(() => {

scene.render();

});


**Scene Configuration Options**

const scene = new BABYLON.Scene(engine, {

// Optimize for large mesh counts

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);

// Movement settings

camera.speed = 0.5;

camera.angularSensibility = 2000;

camera.keysUp = [87]; // W

camera.keysDown = [83]; // S

camera.keysLeft = [65]; // A

camera.keysRight = [68]; // D


**Arc Rotate Camera (Orbit)**

const camera = new BABYLON.ArcRotateCamera(

'camera',

-Math.PI / 2, // alpha (horizontal rotation)

Math.PI / 2.5, // beta (vertical rotation)

15, // radius (distance)

new BABYLON.Vector3(0, 0, 0), // target

scene

);

camera.attachControl(canvas, true);

// Constraints

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);

// Collision detection

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;

// Shadow setup

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);

// Range and falloff

light.range = 100;

light.radius = 0.1;


**Spot Light (Focused)**

const light = new BABYLON.SpotLight(

'spotLight',

new BABYLON.Vector3(0, 10, 0), // position

new BABYLON.Vector3(0, -1, 0), // direction

Math.PI / 3, // angle

2, // exponent

scene

);

light.intensity = 0.8;


**Light Optimization (Include Only Specific Meshes)**

// Only affect specific meshes

light.includedOnlyMeshes = [mesh1, mesh2, mesh3];

// Or exclude specific meshes

light.excludedMeshes = [mesh4, mesh5];


### 4. Mesh Creation

**Built-in Shapes**

// Box

const box = BABYLON.MeshBuilder.CreateBox('box', {

size: 2,

width: 2,

height: 2,

depth: 2

}, scene);

// Sphere

const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {

diameter: 2,

segments: 32,

diameterX: 2,

diameterY: 2,

diameterZ: 2,

arc: 1,

slice: 1

}, scene);

// Cylinder

const cylinder = BABYLON.MeshBuilder.CreateCylinder('cylinder', {

height: 3,

diameter: 2,

tessellation: 24

}, scene);

// Plane

const plane = BABYLON.MeshBuilder.CreatePlane('plane', {

size: 5,

width: 5,

height: 5

}, scene);

// Ground

const ground = BABYLON.MeshBuilder.CreateGround('ground', {

width: 10,

height: 10,

subdivisions: 2

}, scene);

// Ground from heightmap

const ground = BABYLON.MeshBuilder.CreateGroundFromHeightMap('ground', 'heightmap.png', {

width: 100,

height: 100,

subdivisions: 100,

minHeight: 0,

maxHeight: 10

}, scene);

// Torus

const torus = BABYLON.MeshBuilder.CreateTorus('torus', {

diameter: 3,

thickness: 1,

tessellation: 16

}, scene);

// TorusKnot

const torusKnot = BABYLON.MeshBuilder.CreateTorusKnot('torusKnot', {

radius: 2,

tube: 0.6,

radialSegments: 64,

tubularSegments: 8,

p: 2,

q: 3

}, scene);


**Mesh Transformations**

// Position

mesh.position = new BABYLON.Vector3(0, 5, 10);

mesh.position.x = 5;

mesh.position.y = 2;

// Rotation (radians)

mesh.rotation = new BABYLON.Vector3(0, Math.PI / 2, 0);

mesh.rotation.y = Math.PI / 4;

// Scaling

mesh.scaling = new BABYLON.Vector3(2, 2, 2);

mesh.scaling.x = 1.5;

// Look at

mesh.lookAt(new BABYLON.Vector3(0, 0, 0));

// Parent-child relationships

childMesh.parent = parentMesh;


**Mesh Properties**

// Visibility

mesh.isVisible = true;

mesh.visibility = 0.5; // 0 = invisible, 1 = fully visible

// Picking

mesh.isPickable = true;

mesh.checkCollisions = true;

// Culling

mesh.cullingStrategy = BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY;

// Receive shadows

mesh.receiveShadows = true;


### 5. Materials

**Standard Material**

const material = new BABYLON.StandardMaterial('material', scene);

// Colors

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);

// Textures

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);

// Properties

material.alpha = 0.8;

material.backFaceCulling = true;

material.wireframe = false;

material.specularPower = 64;

// Apply to mesh

mesh.material = material;


**PBR Material (Physically Based Rendering)**

const pbr = new BABYLON.PBRMaterial('pbr', scene);

// Metallic workflow

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);

// Or specular workflow

pbr.albedoTexture = new BABYLON.Texture('albedo.png', scene);

pbr.reflectivityTexture = new BABYLON.Texture('reflectivity.png', scene);

// Environment

pbr.environmentTexture = BABYLON.CubeTexture.CreateFromPrefilteredData('environment.dds', scene);

// Other maps

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**

// Append to scene

BABYLON.SceneLoader.Append('path/to/', 'model.gltf', scene, function(scene) {

console.log('Model loaded');

});

// Import mesh

BABYLON.SceneLoader.ImportMesh('', 'path/to/', 'model.gltf', scene, function(meshes) {

const mesh = meshes[0];

mesh.position.y = 5;

});

// Async version

const result = await BABYLON.SceneLoader.ImportMeshAsync(

null, // all meshes

'https://assets.babylonjs.com/meshes/',

'village.glb',

scene

);

console.log('Loaded meshes:', result.meshes);

// Load from binary

const result = await BABYLON.SceneLoader.AppendAsync(

'',

'data:' + arrayBuffer,

scene

);


**Asset Manager (Batch Loading)**

const assetsManager = new BABYLON.AssetsManager(scene);

// Add mesh task

const meshTask = assetsManager.addMeshTask('model', '', 'path/to/', 'model.gltf');

meshTask.onSuccess = function(task) {

task.loadedMeshes[0].position = new BABYLON.Vector3(0, 0, 0);

};

// Add texture task

const textureTask = assetsManager.addTextureTask('texture', 'texture.png');

textureTask.onSuccess = function(task) {

material.diffuseTexture = task.texture;

};

// Load all

assetsManager.onFinish = function(tasks) {

console.log('All assets loaded');

engine.runRenderLoop(() => scene.render());

};

assetsManager.load();


### 7. Physics Engine

**Havok Physics Setup**

// Import Havok

import HavokPhysics from '@babylonjs/havok';

// Initialize

const havokInstance = await HavokPhysics();

const havokPlugin = new BABYLON.HavokPlugin(true, havokInstance);

// Enable physics

scene.enablePhysics(new BABYLON.Vector3(0, -9.8, 0), havokPlugin);

// Create physics aggregate for mesh

const sphereAggregate = new BABYLON.PhysicsAggregate(

sphere,

BABYLON.PhysicsShapeType.SPHERE,

{ mass: 1, restitution: 0.75 },

scene

);

// Ground (static)

const groundAggregate = new BABYLON.PhysicsAggregate(

ground,

BABYLON.PhysicsShapeType.BOX,

{ mass: 0 }, // mass 0 = static

scene

);


**Physics Shapes**

// Available 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**

// Get body

const body = aggregate.body;

// Apply force

body.applyForce(

new BABYLON.Vector3(0, 10, 0), // force

new BABYLON.Vector3(0, 0, 0) // point of application

);

// Apply impulse

body.applyImpulse(

new BABYLON.Vector3(0, 5, 0),

new BABYLON.Vector3(0, 0, 0)

);

// Set velocity

body.setLinearVelocity(new BABYLON.Vector3(0, 5, 0));

body.setAngularVelocity(new BABYLON.Vector3(0, 1, 0));

// Properties

body.setMassProperties({ mass: 2 });

body.setCollisionCallbackEnabled(true);


### 8. Animations

**Direct Animation**

// Animate property

BABYLON.Animation.CreateAndStartAnimation(

'anim',

mesh,

'position.y',

30, // FPS

120, // total frames

mesh.position.y, // from

10, // to

BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE

);


**Animation Class**

const animation = new BABYLON.Animation(

'myAnimation',

'position.x',

30,

BABYLON.Animation.ANIMATIONTYPE_FLOAT,

BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE

);

// Keyframes

const keys = [

{ frame: 0, value: 0 },

{ frame: 30, value: 10 },

{ frame: 60, value: 0 }

];

animation.setKeys(keys);

// Attach to mesh

mesh.animations.push(animation);

// Start

scene.beginAnimation(mesh, 0, 60, true);


**Animation Groups**

const animationGroup = new BABYLON.AnimationGroup('group', scene);

animationGroup.addTargetedAnimation(animation1, mesh1);

animationGroup.addTargetedAnimation(animation2, mesh2);

// Control

animationGroup.play();

animationGroup.pause();

animationGroup.stop();

animationGroup.speedRatio = 2.0;

// Events

animationGroup.onAnimationEndObservable.add(() => {

console.log('Animation complete');

});


**Skeleton Animations (from imported models)**

// Get skeleton from imported model

const skeleton = result.skeletons[0];

// Get animation ranges

const ranges = skeleton.getAnimationRanges();

// Play animation range

scene.beginAnimation(skeleton, 0, 100, true);

// Or use animation groups

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);

// Quick setup

scene.createDefaultCameraOrLight(true, true, true);

const env = scene.createDefaultEnvironment({

createGround: true,

createSkybox: true,

skyboxSize: 150,

groundSize: 50

});

// Your meshes

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);

// Load model

const result = await BABYLON.SceneLoader.ImportMeshAsync(

null,

'https://assets.babylonjs.com/meshes/',

'village.glb',

scene

);

// Setup physics

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);

// Highlight picked mesh

pickResult.pickedMesh.material.emissiveColor = new BABYLON.Color3(1, 0, 0);

}

};

// Or use action manager

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

// Default pipeline

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;

// Depth of field

pipeline.depthOfFieldEnabled = true;

pipeline.depthOfFieldBlurLevel = BABYLON.DepthOfFieldEffectBlurLevel.Low;

pipeline.depthOfField.focusDistance = 2000;

pipeline.depthOfField.focalLength = 50;

// Glow layer

const glowLayer = new BABYLON.GlowLayer('glow', scene);

glowLayer.intensity = 0.5;

// Highlight layer

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';

// Fullscreen UI

const advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI('UI');

// Button

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);

// Text

const text = new BABYLON.GUI.TextBlock();

text.text = 'Hello World';

text.color = 'white';

text.fontSize = 24;

advancedTexture.addControl(text);

// 3D mesh UI

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);

// Create shadow generator

const shadowGenerator = new BABYLON.ShadowGenerator(1024, light);

shadowGenerator.useExponentialShadowMap = true;

shadowGenerator.usePoissonSampling = true;

// Add shadow casters

shadowGenerator.addShadowCaster(sphere);

shadowGenerator.addShadowCaster(box);

// Enable shadow receiving

ground.receiveShadows = true;


### Pattern 7: Particle Systems

const particleSystem = new BABYLON.ParticleSystem('particles', 2000, scene);

particleSystem.particleTexture = new BABYLON.Texture('particle.png', scene);

// Emitter

particleSystem.emitter = new BABYLON.Vector3(0, 5, 0);

particleSystem.minEmitBox = new BABYLON.Vector3(-1, 0, 0);

particleSystem.maxEmitBox = new BABYLON.Vector3(1, 0, 0);

// Colors

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);

// Size

particleSystem.minSize = 0.1;

particleSystem.maxSize = 0.5;

// Life time

particleSystem.minLifeTime = 0.3;

particleSystem.maxLifeTime = 1.5;

// Emission rate

particleSystem.emitRate = 1500;

// Direction

particleSystem.direction1 = new BABYLON.Vector3(-1, 8, 1);

particleSystem.direction2 = new BABYLON.Vector3(1, 8, -1);

// Gravity

particleSystem.gravity = new BABYLON.Vector3(0, -9.81, 0);

// Start

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;

// Initialize

const engine = new BABYLON.Engine(canvasRef.current, true);

engineRef.current = engine;

const scene = new BABYLON.Scene(engine);

sceneRef.current = scene;

// Setup 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);

// Render loop

engine.runRenderLoop(() => {

scene.render();

});

// Resize handler

const handleResize = () => engine.resize();

window.addEventListener('resize', handleResize);

// Cleanup

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();

// Enable WebXR

const xrHelper = await scene.createDefaultXRExperienceAsync({

floorMeshes: [env.ground],

disableTeleportation: false

});

// XR controller input

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)

// Create from snippet

const nodeMaterial = await BABYLON.NodeMaterial.ParseFromSnippetAsync('#SNIPPET_ID', scene);

// Apply to mesh

nodeMaterial.build();

mesh.material = nodeMaterial;

// Or create programmatically

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

// Merge meshes with same material

const merged = BABYLON.Mesh.MergeMeshes(

[mesh1, mesh2, mesh3],

true, // disposeSource

true, // allow32BitsIndices

undefined,

false, // multiMultiMaterials

true // preserveSerializationHelper

);

// Instances (for repeated meshes)

const instance1 = mesh.createInstance('instance1');

const instance2 = mesh.createInstance('instance2');

instance1.position.x = 5;

instance2.position.x = -5;

// Thin instances (even more efficient)

const buffer = new Float32Array(16 * count); // 16 floats per matrix

mesh.thinInstanceSetBuffer('matrix', buffer, 16);

// Freeze meshes (static meshes)

mesh.freezeWorldMatrix();

// Freeze materials

material.freeze();

// Simplify meshes (LOD)

const simplified = mesh.simplify(

[

{ quality: 0.8, distance: 10 },

{ quality: 0.4, distance: 50 },

{ quality: 0.2, distance: 100 }

],

true, // parallelProcessing

BABYLON.SimplificationType.QUADRATIC

);


### 2. Scene Optimization

// Scene optimizer

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();

// Octree (spatial partitioning)

const octree = scene.createOrUpdateSelectionOctree();

// Frustum culling

scene.blockMaterialDirtyMechanism = true;

// Skip pointer move picking

scene.skipPointerMovePicking = true;

// Freeze active meshes

scene.freezeActiveMeshes();


### 3. Rendering Optimization

// Hardware scaling

engine.setHardwareScalingLevel(0.5); // Render at half resolution

// Adaptive quality

scene.onBeforeRenderObservable.add(() => {

const fps = engine.getFps();

if (fps < 30) {

// Reduce quality

engine.setHardwareScalingLevel(2);

} else if (fps > 55) {

// Increase quality

engine.setHardwareScalingLevel(1);

}

});

// Incremental loading

scene.useDelayedTextureLoading = true;

// Culling strategy

mesh.cullingStrategy = BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY;


### 4. Texture Optimization

// Compressed textures

const texture = new BABYLON.Texture('texture.dds', scene);

// Mipmaps

texture.updateSamplingMode(BABYLON.Texture.TRILINEAR_SAMPLINGMODE);

// Anisotropic filtering

texture.anisotropicFilteringLevel = 4;

// KTX2 compression

const texture = new BABYLON.Texture('texture.ktx2', scene);


## Common Pitfalls

### Pitfall 1: Memory Leaks

**Problem**: Not disposing resources

// ❌ Bad - memory leak

function createAndRemoveMesh() {

const mesh = BABYLON.MeshBuilder.CreateBox('box', {}, scene);

scene.removeMesh(mesh);

}


**Solution**: Properly dispose

// ✅ Good

function createAndRemoveMesh() {

const mesh = BABYLON.MeshBuilder.CreateBox('box', {}, scene);

mesh.dispose();

}

// Dispose entire scene

scene.dispose();

// Dispose engine

engine.dispose();


### Pitfall 2: Performance Issues with Too Many Draw Calls

**Problem**: Each mesh = one draw call

// ❌ Bad - 1000 draw calls

for (let i = 0; i < 1000; i++) {

const box = BABYLON.MeshBuilder.CreateBox('box' + i, {}, scene);

box.position.x = i;

}


**Solution**: Use instances or merge

// ✅ Good - 1 draw call

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

// ❌ Bad - blocks rendering

function createManyMeshes() {

for (let i = 0; i < 10000; i++) {

const mesh = BABYLON.MeshBuilder.CreateSphere('sphere' + i, {}, scene);

}

}


**Solution**: Use async/incremental loading

// ✅ Good - incremental

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

// ❌ Bad - forgot attachControl

const camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 10, BABYLON.Vector3.Zero(), scene);


**Solution**: Always attach controls

// ✅ Good

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

// ❌ Bad

BABYLON.SceneLoader.ImportMesh('', 'path/', 'model.gltf', scene);

const mesh = scene.getMeshByName('meshName'); // null!


**Solution**: Use callbacks or async/await

// ✅ Good

const result = await BABYLON.SceneLoader.ImportMeshAsync('', 'path/', 'model.gltf', scene);

const mesh = scene.getMeshByName('meshName');

// Or with callback

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

// ❌ Bad

const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', {}, scene);

sphere.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, {mass: 1}, scene);

// Error: Physics not enabled!


**Solution**: Enable physics first, use aggregates

// ✅ Good

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

// Show inspector

scene.debugLayer.show();

// Show bounding boxes

scene.forceShowBoundingBoxes = true;

// Show wireframes

material.wireframe = true;

// Log FPS

setInterval(() => {

console.log('FPS:', engine.getFps());

}, 1000);

// Instrumentation

const instrumentation = new BABYLON.SceneInstrumentation(scene);

instrumentation.captureFrameTime = true;

console.log('Frame time:', instrumentation.frameTimeCounter.average);

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card