Babylon.js is a powerful, open-source 3D engine capable of rendering interactive 3D and 2D graphics using JavaScript. It is a great choice for creating games, demos, visualizations, and other 3D applications for the web or even for VR.
Being free, open-source, and cross-platform, Babylon.js is a great alternative to proprietary 3D engines like Unity and Unreal Engine. It is also a great alternative to other open-source 3D engines like Three.js and PlayCanvas as it provides TypeScript types out of the box, is optimized for performance, and provides advanced debugging tools. Its developer experience is excellent, and it has a large and active community making it a great choice for creating 3D applications for the web for both beginners and experts alike.
Getting Started
Babylon.js supports both ES6 and CommonJS module imports:
-
CommonJS Babylon.js npm packages support CommonJS/ES6 imports, UMD, and AMD-importsโโ.
-
For developers seeking optimization through tree shaking, Babylon.js offers ES6 packages. These include @babylonjs/core for the core functionalities, and additional modules like @babylonjs/materials, @babylonjs/loaders, @babylonjs/gui, etc. It's important not to mix ES6 and legacy packagesโโ.
If you want to use the CommonJS module imports, you can install Babylon.js as follows:
npm install --save babylonjs
Then, include it in your JavaScript or TypeScript file:
import * as BABYLON from "babylonjs";
If you want to use the ES6 module imports, you can install Babylon.js as follows:
npm install --save @babylonjs/core
Then, include it in your JavaScript or TypeScript file:
import { Engine, Scene } from "@babylonjs/core";
I prefer the ES6 module imports because they allow for tree shaking, which can significantly reduce the size of the final bundle. However, in this tutorial, I will be using the CommonJS module imports because that's what the Babylon.js playground uses.
Creating Your First Babylon.js Scene
The Babylon.js Playground is an essential tool for learning and developing with Babylon.js. It's a user-friendly environment where you can write code and immediately see the results in a live scene. The playground comes with a default scene, and experimenting with it is a great way to start.
Apart from playing around with the default scene, you can also search the playground if you want to see examples of specific features. For example, if you search for "physics," you will find several examples of physics in action.
The playground is also often used to share code snippets on the Babylon.js forum both when asking for help and when helping others. I often found myself googling specific Babylon.js problems or features and finding a playground example that helped me understand and solve my problem.
Creating and Modifying Meshes
Meshes are fundamental in 3D graphics. In Babylon.js, creating a basic mesh, like a sphere, involves a few lines of code:
var sphere = BABYLON.MeshBuilder.CreateSphere(
"sphere",
{ diameter: 2, segments: 32 },
scene
);
sphere.position.y = 1;
You can also create materials and assign them to meshes to change their appearance. For example, to make a ground plane red, you would write:
const groundMaterial = new BABYLON.StandardMaterial("Ground Material", scene);
groundMaterial.diffuseColor = BABYLON.Color3.Red();
ground.material = groundMaterial;
Textures can also be added to materials:
var groundTexture = new BABYLON.Texture(
Assets.textures.checkerboard_basecolor_png.rootUrl,
scene
);
groundMaterial.diffuseTexture = groundTexture;
Importing and Using Meshes
Babylon.js allows for the importation of complex meshes, which can be scaled and positioned within the scene:
BABYLON.SceneLoader.ImportMesh(
"",
Assets.meshes.MyCustomMesh.rootUrl,
Assets.meshes.MyCustomMesh.filename,
scene,
function (newMeshes) {
newMeshes[0].scaling = new BABYLON.Vector3(0.1, 0.1, 0.1);
}
);
Making the Scene Interactive
Interactivity is a key aspect of web experiences. Attaching controls to a camera enables user interaction through click-and-drag operations.
var camera = new BABYLON.ArcRotateCamera(
"Camera",
0,
0,
10,
BABYLON.Vector3.Zero(),
scene
);
camera.attachControl(canvas, true);
Adding Virtual Reality Support
Virtual reality is an exciting new technology that allows users to experience 3D environments more immersively. Babylon.js has built-in support for virtual reality, which can be enabled with a few lines of code:
const experience = await scene.createDefaultXRExperienceAsync();
const camera = experience.baseExperience.camera;
camera.attachControl(true);
You just create an XR experience, get the camera from the base experience, and attach it to the canvas and you should be all set for VR. If you don't own a VR headset, you can still test your scene in VR using the Immersive Web Emulator Chrome Extension.
Adding Physics
Physics is an important part of many 3D applications. Babylon.js has a built-in physics engine that can be enabled with a few lines of code:
var gravityVector = new BABYLON.Vector3(0, -9.81, 0);
var physicsPlugin = new BABYLON.CannonJSPlugin();
scene.enablePhysics(gravityVector, physicsPlugin);
Physics can be applied to meshes by setting their physicsImpostor
property:
sphere.physicsImpostor = new BABYLON.PhysicsImpostor(
sphere,
BABYLON.PhysicsImpostor.SphereImpostor,
{ mass: 1, restitution: 0.9 },
scene
);
Adding Lights
Lights are essential for creating realistic scenes. In Babylon.js, there are four main types of lights, each offering unique properties and effects:
- Directional Light: Mimics sunlight, emitting parallel light rays across the entire scene. It's defined by a direction vector and has an infinite range.
- Point Light: Resembles a light bulb, radiating light equally in all directions from a single point in space.
- Spot Light: Functions like a flashlight, emitting a conical beam of light from a specific position in a given direction. Its illumination area and decay are controlled by angle and exponent parameters.
- Hemispheric Light: Simulates ambient environment lighting, defined by a direction, usually upwards. Its effect is influenced by setting different color properties.
Each light type can be customized using properties like intensity and range, and you can control which meshes they illuminate. For more complex lighting scenarios, lightmaps can be utilized to pre-calculate and store lighting effects.
For example, to add a directional light to the scene, you could write:
var light = new BABYLON.DirectionalLight(
"DirectionalLight",
new BABYLON.Vector3(0, -1, 0),
scene
);
Adding Shadows
Shadows are an important part of creating realistic scenes as they can help convey the 3D structure of the scene by providing cues about the relative positions and distances of objects, enhancing the perception of depth and dimension. Babylon.js has several types of shadows, including PCF, PCFSoft, and PCSS. For example, to add PCF shadows to the scene, you would write:
var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
shadowGenerator.usePoissonSampling = true;
shadowGenerator.bias = 0.0001;
shadowGenerator.normalBias = 0.01;
shadowGenerator.setDarkness(0.5);
shadowGenerator.useBlurExponentialShadowMap = true;
shadowGenerator.blurKernel = 32;
shadowGenerator.blurScale = 2;
shadowGenerator.blurBoxOffset = 1;
shadowGenerator.useKernelBlur = true;
shadowGenerator.addShadowCaster(sphere);
Adding Audio
Audio is an important part of many 3D applications. Babylon.js has a built-in audio engine that can be enabled with a few lines of code:
var audioEngine = new BABYLON.AudioEngine();
Audio can be added to the scene by creating a sound object:
var sound = new BABYLON.Sound(
"Sound",
`${Assets.sound.cannonBlast.rootUrl}${Assets.sound.cannonBlast.filename}`,
scene,
null,
{ loop: true, autoplay: true }
);
This particular example would play a "cannon blast" sound on a loop in your scene. The cannon blast asset is preloaded in the Babylon.js playground. If you were to load a custom asset in your application, you would simply provide a URL pointing to the sound file on the filesystem. For more details, you can check the documentation on playing sounds in Babylon.js.
Adding User Interface Elements
User interface elements can be used to add interactivity to a scene. Babylon.js provides a GUI library extension built on top of the DynamicTexture
. For example, to add a dialog to the scene containing a button, you would write:
var guiManager = new BABYLON.GUI.GUI3DManager(scene);
const slate = new BABYLON.GUI.HolographicSlate("down");
slate.minDimensions = new BABYLON.Vector2(5, 5);
slate.dimensions = new BABYLON.Vector2(5, 5);
slate.titleBarHeight = 0.75;
slate.title = "Button!";
guiManager.addControl(slate);
var button = BABYLON.GUI.Button.CreateSimpleButton("button", "Click me!");
button.width = 0.5;
button.height = 0.25;
button.background = "green";
button.textBlock.color = "white";
button.onPointerClickObservable.add(() => {
alert("Hi!");
});
slate.content = button;
slate.position = new BABYLON.Vector3(-2, 2, 0);
To use the ES6 version, you'll need to install the @babylonjs/gui
package:
npm install --save @babylonjs/gui
Then, import it into your JavaScript or TypeScript file like this:
import { GUI3DManager, HolographicSlate, Button } from "@babylonjs/gui";
Tip: In case you don't like the controls that allow users to tilt the
HolographicSlate
, you can disable them by settingslate._gizmo._rootMesh.setEnabled(false);
after adding the slate to your scene.
Adding Animations
Animations can be used to add movement to a scene. Babylon.js has several types of animations, including keyframe, bone, and morph target. For example, to add a keyframe animation to the scene, you would write:
var animationBox = new BABYLON.Animation(
"myAnimation",
"scaling.x",
30,
BABYLON.Animation.ANIMATIONTYPE_FLOAT,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);
var keys = [];
keys.push({
frame: 0,
value: 1,
});
keys.push({
frame: 20,
value: 0.2,
});
keys.push({
frame: 100,
value: 1,
});
animationBox.setKeys(keys);
sphere.animations.push(animationBox);
scene.beginAnimation(sphere, 0, 100, true);
Here's an explanation of what the code does:
-
Animation Creation: A BABYLON.Animation object named "myAnimation" is created to animate the scaling.x property, indicating the animation will affect the object's width. It runs at 30 frames per second, with values represented as floats, and loops continuously.
-
Defining Keyframes: Three keyframes are defined:
- At frame 0, the scale is 1 (original size).
- At frame 20, the scale reduces to 0.2.
- At frame 100, the scale returns to 1.
-
Applying and Starting Animation: The animation is assigned to the sphere object and starts immediately, looping between frames 0 and 100. This creates a pulsating effect on the sphere's width.
For a deeper dive into animations, you can check out the Babylon.js Animation Documentation.
Debugging
Debugging is an important part of any development process. Babylon.js has a built-in debug layer that can be enabled with a few lines of code:
scene.debugLayer.show();
The debug layer provides a user-friendly interface for inspecting and modifying the scene. It can also show you the current frame rate and other performance metrics and lets you export the performance data.
In case you are using the ES6 module imports, you'll need to install the @babylonjs/inspector
package:
npm install --save @babylonjs/inspector
Then, import it into your JavaScript or TypeScript file like this:
import "@babylonjs/inspector";
Hosting and Sharing Your Scene
Once you're satisfied with your creation, you can download it as an HTML file and host it on platforms like GitHub Pages, making it accessible to the world.
You can also share your scene with others by sharing the playground URL. For example, the URL for the default scene is https://playground.babylonjs.com/#6QY4X1#1.
In case you would like to integrate your scene with a framework of your choice, you can check out the Babylon.js External Libraries Documentation where you can find examples of Babylon.js being used with frameworks like React, Vue, or Ionic Angular.
Conclusion
Babylon.js is a powerful, open-source 3D engine capable of rendering interactive 3D and 2D graphics using JavaScript. It is well supported and maintained, providing a good developer experience with many interactive playground examples and a supportive community forum, making it a great choice for creating games, demos, visualizations, and other 3D applications for the web (and eventually even for native platforms as I've heard out of the box React Native support may be coming).
This blog post hopefully gave you an overview of some of its capabilities and how to get started with it along with pointers to more in-depth documentation.