Chapter 01Creating a Scene

To render a BJS scene in a web page, the page must include a script tag that specifies where the browser can find the BSJ source code file. The source code file can be either downloaded from GitHub and installed on the server that is hosting the website or it can be fetched using the CDN link as shown below.

<script src="https://cdn.babylonjs.com/babylon.js"></script>

When the browsers loads the BJS script file into the web page, it loads it as a Immediately Invoked Function Expression (iife). This iife creates a global variable named BABYLON that we can use to access the BJS API. The documentation for the BJS API can be found here. You may want to bookmark this page for future reference.

A BJS scene is rendered in a HTML5 canvas element, so the web page displaying the BJS scene must include a canvas element and set it’s id property to some string.

<canvas id="renderCanvas1"></canvas>

The source code for a BJS scene can be defined in either a separate JavaScript file or can be written inline, within in the HTML file, between opening and closing script tags. If the source code is written in a separate file, an additional script tag must be added after the script tag that loads the BJS source code. It is recommended that you insert both script tags directly above the closing body tags. Although our sandboxes include the code for the scenes directly in the HTML file, it recommended that you write your scenes in separate JavaScript files since, as you will see, some scenes can contain hundreds of lines of code.

Before we explore the JavaScript code for a minimal BJS scene, we’d like to remind and encourage you to experiment with the code we’ve provided. As mentioned in the introduction, to render the scene after you’ve made changes to it, press the button. If you find that nothing appears in the rendering area or it appears different from what you expect, view the console in your browser’s developer tools to see if any errors are logged.

<script>
  var canvas = document.getElementById("renderCanvas");
  var engine = new BABYLON.Engine(canvas, true);

  function createScene (canvas, engine) {
    let scene = new BABYLON.Scene(engine);
    let camera = new BABYLON.ArcRotateCamera("Camera", Math.PI/4, Math.PI/4, 6, BABYLON.Vector3.Zero(), scene);
    camera.attachControl(canvas, true);
    let light1 = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(1, 1, 0), scene);
    let box = BABYLON.MeshBuilder.CreateBox("box", scene);
    return scene;
  };

  var scene = createScene(canvas, engine);

  engine.runRenderLoop(function () {
    scene.render();
  });

  window.addEventListener("resize", function () {
    engine.resize();
  });
</script>

<canvas id="renderCanvas"></canvas>

Example Explained

You may have noticed in the code for the demonstration that we did not include a script tag to load the BJS source code. This is because we’ve added it to the top of this web page. So even though you won’t see us load the BJS script file in the sandboxes, remember to load it in your web pages.

Lets now go through, line-by-line, the code that defines this BJS scene.

The first line gets the canvas element from the web page’s DOM.

var canvas = document.getElementById("renderCanvas");

The second line, creates a BABYLON.engine object. The engine is BJS’ main workhorse which will be used to continuously render the scene.

var engine = new BABYLON.Engine(canvas, true);

The createScene function creates a new BABYLON.Scene object, adds two necessary objects to the scene, a camera and a light, and adds a box to the scene.

function createScene (canvas, engine) {
  let scene = new BABYLON.Scene(engine);
  let camera = new BABYLON.ArcRotateCamera("Camera", Math.PI/4, Math.PI/4, 6, BABYLON.Vector3.Zero(), scene);
  camera.attachControl(canvas, true);
  let light1 = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(1, 1, 0), scene);
  let box = BABYLON.MeshBuilder.CreateBox("box", scene);
  return scene;
};

The camera defines the viewport to the scene through which the user sees the scene. BJS provides various types of cameras. We’ll discuss each of them in a later section. In this example, we use a Babylon.ArcRotateCamera which points toward a target location in the 3D space of the scene, the origin (0,0,0) in this case, and can be rotated about that point using mouse and touch events. The camera is then attached to the canvas element so that mouse and touch events from the canvas can be used by the camera to move the camera around the target location. Click on a region of the scene and drag your mouse around the scene to see how the camera can be moved around the target location.

Lights are used to illuminate the elements in the scene. As with cameras, BJS provides various types of lights which we’ll discuss in detail in a later section. Here we use a BABYLON.HemisphericLight which simulates the natural (or ambient) light in an environment. Comment out the line of code that assigns the HemisphericLight object to the variable light to see what happens when lights are omitted from a scene.

The box is added usingg the BABYLON.MeshBuilder class. We’ll see in a later section how to use the MeshBuilder class to create a wide variety of 3D objects.

After defining the ‘createScene’ function, we call it, passing it the canvas and engine variables that were declared earlier, and store in the variable named scene the reference to the scene object returned from the function.

var scene = createScene(canvas, engine);

Although we’ve created a scene, we have yet to render it. Since a BJS scene is a dynamic object, the engine must continuously render the scene. To do so, we call engine.runRenderLoop which continuously executes the function passed to it. In this demonstration, the function passed to engine.runRenderLoop simply calls scene.render to render the scene continuously.

engine.runRenderLoop(function () {
  scene.render();
});

Alas, we register an event listener for the “resize” event and pass to it a function which calls engine.resize so that when the size of the canvas changes the engine can resize the view.

window.addEventListener("resize", function () {
  engine.resize();
});