WebXR — Virtual and Augmented Reality for the Web - Game development

WebXR — Virtual and Augmented Reality for the Web
=================================================

The concepts of virtual reality (VR) and augmented reality (AR) aren't new, but the technology is more accessible than ever. We can also use a JavaScript API to make use of it in web applications. This article introduces WebXR from the perspective of its use in games.

**Note:** You may see references to the non-standard WebVR API. WebVR was never ratified as a standard, was implemented and enabled by default in very few browsers, and supported only a few devices. The **WebVR** API is replaced by the **WebXR** Device API.

VR devices
----------

With the popularity of existing VR headsets such as Meta Quest, Valve Index, and PlayStation VR, the future looks bright — we already have sufficient technology to create meaningful VR gaming experiences.

![Three different VR devices: the Meta Quest 3, the Valve Index, and the Sony PSVR2.](/en-US/docs/Games/Techniques/3D_on_the_web/WebXR/hmds.jpg)

### Development of WebVR

 The WebVR spec, led by Vladimir Vukicevic from Mozilla and Brandon Jones from Google, is being replaced by the WebXR Device API. WebVR may still be available in some browsers while WebXR is finalized.
 For more info, see the WebVR.info website.

The WebXR API
-------------

The core of any WebXR experience is built on top of two foundational concepts:

1. The application must receive real-time data about your headset's position and your controllers' positions in three-dimensional space
2. The application must render a real-time, stereoscopic view to the headset's display(s) according to that positional data

The WebXR API is the central API for capturing information about XR devices connected to a computer. The API can capture headset and controller position, orientation, velocity, acceleration, and other information that you can use in your games.

There are other APIs useful for creating games such as the Gamepad API for non-XR controller inputs and the Device Orientation API for handling display orientation.

### Using the WebXR API

The best place to start with the WebXR API is with our Fundamentals of WebXR guide. After that, see Starting up and shutting down a WebXR session.

Tools and techniques
--------------------

A-Frame is a web framework that offers simple building blocks for WebXR, so you can rapidly build and experiment with VR websites and games. You can read MDN's Building up a basic demo with A-Frame tutorial for more details.

Separately, Three.js is one of the most popular 3D engines for the web, and it can be used for WebXR games. Check out Three.js' How to create VR content documentation to help you make WebXR games with Three.js.

![A 3D representation of a landscape: it's a pinkish sunset, with a blue mountainous land in the background surrounded by a mirror sea and a darker blue island in the second plan.](/en-US/docs/Games/Techniques/3D_on_the_web/WebXR/sechelt.jpg)

Immersion takes priority over gameplay and graphics - you must feel part of the experience. It's not easy to achieve, but it doesn't require realistic images. On the contrary, even basic shapes soaring past at high frame rates can be thrilling if the experience is immersive. Remember: experimenting is key - feel free to go with what works well for your project.

The future of WebXR
-------------------

Consumer devices are available on the market, and we have JavaScript APIs to support them on the web. As hardware becomes more affordable and the ecosystem matures, developers can focus on building experiences through good UX and UI. It's the perfect time to dive in and experiment with WebXR.

See also
--------

* WebVR Device API
* Fundamentals of WebXR
* Building up a basic demo with A-Frame


GLSL Shaders - Game development

GLSL Shaders
============

Shaders use GLSL (OpenGL Shading Language), a special OpenGL Shading Language with syntax similar to C. GLSL is executed directly by the graphics pipeline. There are several kinds of shaders, but two are commonly used to create graphics on the web: Vertex Shaders and Fragment (Pixel) Shaders. Vertex Shaders transform shape positions into 3D drawing coordinates. Fragment Shaders compute the renderings of a shape's colors and other attributes.

GLSL is not as intuitive as JavaScript. GLSL is strongly typed and there is a lot of math involving vectors and matrices. It can get very complicated — very quickly. In this article we will make a simple code example that renders a cube. To speed up the background code we will be using the Three.js API.

As you may remember from the basic theory article, a vertex is a point in a 3D coordinate system. Vertices may, and usually do, have additional properties. The 3D coordinate system defines space and the vertices help define shapes in that space.

Shader types
------------

A shader is essentially a function required to draw something on the screen. Shaders run on a GPU (graphics processing unit), which is optimized for such operations. Using a GPU to deal with shaders offloads some of the number crunching from the CPU. This allows the CPU to focus its processing power on other tasks, like executing code.

### Vertex shaders

Vertex shaders manipulate coordinates in a 3D space and are called once per vertex. The purpose of the vertex shader is to set up the `gl_Position` variable — this is a special, global, and built-in GLSL variable. `gl_Position` is used to store the position of the current vertex.

The `void main()` function is a standard way of defining the `gl_Position` variable. Everything inside `void main()` will be executed by the vertex shader. A vertex shader yields a variable containing how to project a vertex's position in 3D space onto a 2D screen.

### Fragment shaders

Fragment (or texture) shaders define RGBA (red, green, blue, alpha) colors for each pixel being processed — a single fragment shader is called once per pixel. The purpose of the fragment shader is to set up the `gl_FragColor` variable. `gl_FragColor` is a built-in GLSL variable like `gl_Position`.

The calculations result in a variable containing the information about the RGBA color.

Demo
----

Let's build a simple demo to explain those shaders in action. Be sure to read Three.js tutorial first to grasp the concept of the scene, its objects, and materials.

**Note:** Remember that you don't have to use Three.js or any other library to write your shaders — pure WebGL (Web Graphics Library) is more than enough. We've used Three.js here to make the background code a lot simpler and clearer to understand, so you can just focus on the shader code. Three.js and other 3D libraries abstract a lot of things for you — if you wanted to create such an example in raw WebGL, you'd have to write a lot of extra code to actually make it work.

### Environment setup

To start with the WebGL shaders you don't need much. You should:

* Make sure you are using a modern browser with good WebGL support, such as the latest Firefox or Chrome.
* Create a directory to store your experiments in.
* Save a copy of the latest minimized Three.js library inside your directory.
### HTML structure

Here's the HTML structure we will use.

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <title>MDN Games: Shaders demo</title>
    <style>
 body {
 margin: 0;
 padding: 0;
 font-size: 0;
 }
 canvas {
 width: 100%;
 height: 100%;
 }
 </style>
    <script src="three.min.js"></script>
  </head>
  <body>
    <script id="vertexShader" type="x-shader/x-vertex">
 // vertex shader's code goes here
 </script>
    <script id="fragmentShader" type="x-shader/x-fragment">
 // fragment shader's code goes here
 </script>
    <script>
 // scene setup goes here
 </script>
  </body>
</html>
```

It contains some basic information like the document `<title>`, and some CSS to set the `width` and `height` of the `<canvas>` element that Three.js will insert on the page to be the full size of the viewport. The `<script>` element in the `<head>` includes the Three.js library in the page; we will write our code into three script tags in the `<body>` tag:

1. The first one will contain the vertex shader.
2. The second one will contain the fragment shader.
3. The third one will contain the actual JavaScript code generating the scene.

Before reading on, copy this code to a new text file and save it in your working directory as `index.html`. We'll create a scene featuring a simple cube in this file to explain how the shaders work.

### The cube's source code

Instead of creating everything from scratch we can reuse the Building up a basic demo with Three.js source code of the cube. Most of the components like the renderer, camera, and lights will stay the same, but instead of the basic material we will set the cube's color and position using shaders.

Go to the cube.html file on GitHub, copy all the JavaScript code from inside the second `<script>` element, and paste it into the third `<script>` element of the current example. Save and load `index.html` in your browser — you should see a blue cube.

### The vertex shader code

Let's continue by writing a simple vertex shader — add the code below inside the body's first `<script>` tag:

```glsl
void main() {
  gl_Position = projectionMatrix \* modelViewMatrix \* vec4(position.x+10.0, position.y, position.z+5.0, 1.0);
}
```

The resulting `gl_Position` is calculated by multiplying the model-view and the projection matrices by each vector to get the final vertex position, in each case.

**Note:** You can learn more about *model*, *view*, and *projection transformations* from the vertex processing paragraph, and you can also check out the links at the end of this article to learn more about it.

Both `projectionMatrix` and `modelViewMatrix` are provided by Three.js and the vector is passed with the new 3D position, which results in the original cube moving 10 units along the `x` axis and 5 units along the `z` axis, translated via a shader. We can ignore the fourth parameter and leave it with the default `1.0` value; this is used to manipulate the clipping of the vertex position in the 3D space, but we don't need in our case.

### The texture shader code

Now we'll add the texture shader to the code — add the code below to the body's second `<script>` tag:

```glsl
void main() {
  gl_FragColor = vec4(0.0, 0.58, 0.86, 1.0);
}
```

This will set an RGBA color to recreate the current light blue one — the first three float values (ranging from `0.0` to `1.0`) represent the red, green, and blue channels while the fourth one is the alpha transparency (ranging from `0.0` — fully transparent — to 1.0 — fully opaque).

### Applying the shaders

To actually apply the newly created shaders to the cube, comment out the `basicMaterial` definition first:

```js
// const basicMaterial = new THREE.MeshBasicMaterial({color: 0x0095DD});
```

Then, create the `shaderMaterial`:

```js
const shaderMaterial = new THREE.ShaderMaterial({
  vertexShader: document.getElementById("vertexShader").textContent,
  fragmentShader: document.getElementById("fragmentShader").textContent,
});
```

This shader material takes the code from the scripts and applies it to the object the material is assigned to.

Then, in the line that defines the cube we need to replace the `basicMaterial` with the newly created `shaderMaterial`:

```js
// const cube = new THREE.Mesh(boxGeometry, basicMaterial);
const cube = new THREE.Mesh(boxGeometry, shaderMaterial);
```

Three.js compiles and runs the shaders attached to the mesh to which this material is given. In our case the cube will have both vertex and texture shaders applied. That's it — you've just created the simplest possible shader, congratulations! Here's what the cube should look like:

![Three.js blue cube demo](/en-US/docs/Games/Techniques/3D_on_the_web/GLSL_Shaders/cube.png)

It looks exactly the same as the Three.js cube demo but the slightly different position and the same blue color are both achieved using the shader.

Final code
----------

### HTML

```html
<script src="https://end3r.github.io/MDN-Games-3D/Shaders/js/three.min.js"></script>
<script id="vertexShader" type="x-shader/x-vertex">
 void main() {
 gl\_Position = projectionMatrix \* modelViewMatrix \* vec4(position.x+10.0, position.y, position.z+5.0, 1.0);
 }
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
 void main() {
 gl\_FragColor = vec4(0.0, 0.58, 0.86, 1.0);
 }
</script>
```

### JavaScript

```js
const WIDTH = window.innerWidth;
const HEIGHT = window.innerHeight;

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0xdddddd, 1);
document.body.appendChild(renderer.domElement);

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT);
camera.position.z = 50;
scene.add(camera);

const boxGeometry = new THREE.BoxGeometry(10, 10, 10);

const shaderMaterial = new THREE.ShaderMaterial({
  vertexShader: document.getElementById("vertexShader").textContent,
  fragmentShader: document.getElementById("fragmentShader").textContent,
});

const cube = new THREE.Mesh(boxGeometry, shaderMaterial);
scene.add(cube);
cube.rotation.set(0.4, 0.2, 0);

function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}
render();
```

### CSS

```css
body {
  margin: 0;
  padding: 0;
  font-size: 0;
}
canvas {
  width: 100%;
  height: 100%;
}
```

### Result

Conclusion
----------

This article has taught the very basics of shaders. Our example doesn't do much but there are many more cool things you can do with shaders — check out some really cool ones on ShaderToy for inspiration and to learn from their sources.

See also
--------

* Learning WebGL — for general WebGL knowledge
* WebGL Shaders and GLSL at WebGL Fundamentals — for GLSL specific information


Explaining basic 3D theory - Game development

Explaining basic 3D theory
==========================

This article explains all of the basic theory that's useful to know when you are getting started working with 3D.

Coordinate system
-----------------

3D essentially is all about representations of shapes in a 3D space, with a coordinate system used to calculate their position.

![Coordinate system](/en-US/docs/Games/Techniques/3D_on_the_web/Basic_theory/mdn-games-3d-coordinate-system.png)

WebGL uses the right-hand coordinate system — the `x` axis points to the right, the `y` axis points up, and the `z` axis points out of the screen, as seen in the above diagram.

Objects
-------

Different types of objects are built using vertices. A **Vertex** is a point in space having its own 3D position in the coordinate system and usually some additional information that defines it. Every vertex is described by these attributes:

* **Position**: Identifies it in a 3D space (`x`, `y`, `z`).
* **Color**: Holds an RGBA value (R, G and B for the red, green, and blue channels, alpha for transparency — all values range from `0.0` to `1.0`).
* **Normal:** A way to describe the direction the vertex is facing.
* **Texture**: A 2D image that the vertex can use to decorate the surface it is part of instead of a simple color.

You can build geometry using this information — here is an example of a cube:

![Cube](/en-US/docs/Games/Techniques/3D_on_the_web/Basic_theory/mdn-games-3d-cube.png)

A face of the given shape is a plane between vertices. For example, a cube has 8 different vertices (points in space) and 6 different faces, each constructed out of 4 vertices. A normal defines which way the face is directed in. Also, by connecting the points we're creating the edges of the cube. The geometry is built from a vertex and the face, while material is a texture, which uses a color or an image. If we connect the geometry with the material we will get a mesh.

Rendering pipeline
------------------

The rendering pipeline is the process by which images are prepared and output onto the screen. The graphics rendering pipeline takes the 3D objects built from **primitives** described using **vertices**, applies processing, calculates the **fragments** and renders them on the 2D screen as **pixels**.

![Rendering pipeline](/en-US/docs/Games/Techniques/3D_on_the_web/Basic_theory/mdn-games-3d-rendering-pipeline.png)

Terminology used in the diagram above is as follows:

* A **Primitive**: An input to the pipeline — it's built from vertices and can be a triangle, point or line.
* A **Fragment**: A 3D projection of a pixel, which has all the same attributes as a pixel.
* A **Pixel**: A point on the screen arranged in the 2D grid, which holds an RGBA color.

Vertex and fragment processing are programmable — you can write your own shaders that manipulate the output.

Vertex processing
-----------------

Vertex processing is about combining the information about individual vertices into primitives and setting their coordinates in the 3D space for the viewer to see. It's like taking a photo of the given scenery you have prepared — you have to place the objects first, configure the camera, and then take the shot.

![Vertex processing](/en-US/docs/Games/Techniques/3D_on_the_web/Basic_theory/mdn-games-3d-vertex-processing.png)

There are four stages to this processing: the first one involves arranging the objects in the world, and is called **model transformation**. Then there's **view transformation** which takes care of positioning and setting the orientation of the camera in the 3D space. The camera has three parameters — location, direction, and orientation — which have to be defined for the newly created scene.

![Camera](/en-US/docs/Games/Techniques/3D_on_the_web/Basic_theory/mdn-games-3d-camera.png)

**Projection transformation** (also called perspective transformation) then defines the camera settings. It sets up what can be seen by the camera — the configuration includes *field of view*, *aspect ratio* and optional *near* and *far planes*. read the Camera paragraph in the Three.js article to learn about those.

![Camera settings](/en-US/docs/Games/Techniques/3D_on_the_web/Basic_theory/mdn-games-3d-camera-settings.png)

The last step is **viewport transformation**, which involves outputting everything for the next step in the rendering pipeline.

Rasterization
-------------

Rasterization converts primitives (which are connected vertices) to a set of fragments.

![Rasterization](/en-US/docs/Games/Techniques/3D_on_the_web/Basic_theory/mdn-games-3d-rasterization.png)

Those fragments — which are 3D projections of the 2D pixels — are aligned to the pixel grid, so eventually they can be printed out as pixels on a 2D screen display during the output merging stage.

Fragment processing
-------------------

Fragment processing focuses on textures and lighting — it calculates final colors based on the given parameters.

![Fragment processing](/en-US/docs/Games/Techniques/3D_on_the_web/Basic_theory/mdn-games-3d-fragment-processing.png)

### Textures

Textures are 2D images used in the 3D space to make the objects look better and more realistic. Textures are combined from single texture elements called texels the same way picture elements are combined from pixels. Applying textures onto objects during the fragment processing stage of the rendering pipeline allows us to adjust it by wrapping and filtering it if necessary.

Texture wrapping allows us to repeat the 2D image around the 3D object. Texture filtering is applied when the original resolution or the texture image is different from the displayed fragment — it will be minified or magnified accordingly.

### Lighting

The colors we see on the screen is a result of the light source interacting with the surface colors of the object's material. Light might be absorbed or reflected. The standard **Phong Lighting Model** implemented in WebGL has four basic types of lighting:

* **Diffuse**: A distant directional light, like the sun.
* **Specular**: A point of light, just like a light bulb in a room or a flashlight.
* **Ambient**: The constant light applied to everything on the scene.
* **Emissive**: The light emitted directly by the object.
Output merging
--------------

During the output manipulation stage all the fragments of the primitives from the 3D space are transformed into a 2D grid of pixels that are then printed out on the screen display.

![Output merging](/en-US/docs/Games/Techniques/3D_on_the_web/Basic_theory/mdn-games-3d-output-merging.png)

During output merging some processing is also applied to ignore information that is not needed — for example the parameters of objects that are outside the screen or behind other objects, and thus not visible, are not calculated.

Conclusion
----------

Now you know the basic theory behind 3D manipulation. If you want to move on to practice and see some demos in action, follow up with the tutorials below:

* Building up a basic demo with Three.js
* Building up a basic demo with Babylon.js
* Building up a basic demo with PlayCanvas
* Building up a basic demo with A-Frame

Go ahead and create some cool cutting-edge 3D experiments yourself!


Building up a basic demo with A-Frame - Game development

Building up a basic demo with A-Frame
=====================================

The WebXR and WebGL APIs already enable us to start creating virtual reality (VR) and augmented reality (AR) experiences inside web browsers, but the community is still waiting for tools and libraries to appear, to make this easier. Mozilla's A-Frame framework provides a markup language allowing us to build 3D VR landscapes using a system familiar to web developers, which follows game development coding principles; this is useful for quickly and successfully building prototypes and demos, without having to write a lot of JavaScript or GLSL. This article explains how to get up and running with A-Frame, and how to use it to build up a simple demo.

High level overview
-------------------

The current version of A-Frame is 0.3.2, which means it's highly experimental, but it already works and you can test it right away in the browser. It runs on desktop, mobile (iOS and Android), and Oculus Rift, Gear VR and HTC Vive.

A-Frame is built on top of WebGL, and provides pre-built components to use in applications — models, video players, skyboxes, geometries, controls, animations, cursors, etc. It is based on the entity component system, which is known in the game development world, but it targets web developers with a familiar markup structure, manipulable with JavaScript. The end result is 3D web experiences, which are VR-enabled by default.

Environment setup
-----------------

Let's start by setting up an environment to create something with A-Frame. We'll then build up a demo and run it. You should start off by:

* Making sure you are using a modern browser with good WebGL support (and WebVR support if you have available VR hardware) such as the latest Firefox or Chrome — download Firefox Nightly or Chrome (v54 or higher).
* (Optional) set up a VR device such as Oculus Rift or Google Cardboard.
* Create a new directory to store your project in.
* Save a copy of the latest A-Frame JavaScript library file inside your directory (check the GitHub repository for latest stable a dev builds).
* Open the A-Frame documentation in a separate tab — it is useful to refer to.
HTML structure
--------------

The first step is to create an HTML document — inside your project directory, create a new `index.html` file, and save the follow HTML inside it:

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <title>MDN Games: A-Frame demo</title>
    <script src="aframe.min.js"></script>
  </head>
  <body>
    <!-- HTML goes here -->
  </body>
</html>
```

This contains some basic information like the document `charset` and `<title>`. The `<script>` element includes the A-Frame framework in the page; we will write our example code inside the `<body>` element.

### Initializing the scene

A scene is the place where everything happens. When creating new objects in the demo, we will be adding them all to the scene to make them visible on the screen. In A-Frame, the scene is represented by a Scene entity.

**Note:** An Entity is any element — it can be an object like a box, cylinder or cone, but it can also be a camera, light or sound source.

Let's create the scene by adding an `<a-scene>` element inside the `<body>` element:

```html
<a-scene></a-scene>
```

### Adding a cube

Adding the cube to the scene is done by adding a simple `<a-box>` element inside the `<a-scene>` element. Add it now:

```html
<a-box color="#0095DD" position="0 1 0" rotation="20 40 0"></a-box>
```

It contains a few parameters already defined: `color`, `position` and `rotation` — these are fairly obvious, and define the base color of the cube, the position inside the 3D scene, and the rotation of the cube.

**Note:** The distance values (e.g. for the cube y position) are unitless, and can basically be anything you deem suitable for your scene — millimeters, meters, feet, or miles — it's up to you.

### Adding a background: Sky box

A sky box is a background for the 3D world, represented by an `<a-sky>` element. In our case we will use a simple color, but it could also be an image, etc. Looking around would give an impression of being inside an open sky, a wooden barn — wherever you like! Add the following HTML before the `<a-cube>` element:

```html
<a-sky color="#DDDDDD"></a-sky>
```

At this point, if you save the code and refresh your browser you can already see the cube on the screen with our custom background:

![A 3D representation's illustration of a blue cube displayed on a lighter grey background.](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_A-Frame/cube.png)

Here's the code we have created so far:

You can also check it out on GitHub.

A-Frame takes care of setting up everything you need:

* A default light source and camera are included, so the cube is visible.
* The controls are already working: you can use the mouse for looking around and the keyboard for movement
 (try the `W`, `A`, `S`, and `D` keys).
* There's even an "Enter VR mode" button in the bottom right corner of the screen, to allow you to shift to full screen, stereoscopic image viewing if you have the necessary VR hardware set up and ready.
### Specifying a camera

A camera entity can be created by adding an `<a-camera>` element to the scene. We can set the position of the camera explicitly and move it back a little bit from the center of the scene, so we'll be able to see the shapes. Add this just before the closing `</a-scene>` element:

```html
<a-camera
 position="0 1 4"
 cursor-visible="true"
 cursor-scale="2"
 cursor-color="#0095DD"
 cursor-opacity="0.5">
</a-camera>
```

We've also defined a cursor for the given camera, using the `cursor-*` attributes (by default it is invisible.) — we've set its scale so it will more easily visible, its color, and some opacity so it won't completely cover the objects behind it.

### Adding lights

The basic light types in A-Frame are directional and ambient. The first type is a directional light placed somewhere on the scene while the second one reflects the light from the first type, so it looks more natural; this can be set globally. Add the new code below your previous additions — this uses the standard `<a-light>` element:

```html
<a-light type="directional" color="#FFF" intensity="0.5" position="-1 1 2">
</a-light>
<a-light type="ambient" color="#FFF"></a-light>
```

The directional light has a white color, its intensity is set to `0.5`, and it is placed at position `-1 1 2`. The ambient light only needs a color, which is also white.

### Adding some advanced geometry

We have a cube on the scene already; now let's try adding more shapes. We are not limited to the default entities like `<a-cube>` — using `<a-entity>` we can create custom advanced shapes. Let's try adding a torus — add this element below the previous code:

```html
<a-entity
 geometry="
 primitive: torus;
 radius: 1;
 radiusTubular: 0.1;
 segmentsTubular: 12;"
 rotation="10 0 0"
 position="-3 1 0">
</a-entity>
```

Our entity has a torus primitive, which represents its shape. We are passing some initial variables to that shape: the radius of the outer edge of the torus, the radius of the tube, and number of segments along the circumference of the tube face respectively. Rotation and position are set in the same way as we saw earlier.

### Defining a material

The torus is now visible on the scene, but its color doesn't look very good — this is because we have to create a material to define the appearance of the entity. Edit the `<a-entity>` defining the torus to look like the following:

```html
<a-entity
 geometry="
 primitive: torus;
 radius: 1;
 radiusTubular: 0.1;
 segmentsTubular: 12;"
 material="
 color: #EAEFF2;
 roughness: 0.1;
 metalness: 0.5;"
 rotation="10 0 0"
 position="-3 1 0">
</a-entity>
```

In the new `material` attribute, we set up the `color` of the material, then its `roughness` (a rougher material will scatter reflected light in more directions than a smooth material) and `metalness` (how metallic the material is).

Adding some JavaScript to the mix
---------------------------------

It is possible to populate the scene with entities created using JavaScript too, so let's use it to add a third shape, a cylinder. Add a new `<script>` element at the end of the `<body>` element, just after the `<a-scene>` element, then add the following JavaScript code inside it:

```js
const scene = document.querySelector("a-scene");
const cylinder = document.createElement("a-cylinder");
cylinder.setAttribute("color", "#FF9500");
cylinder.setAttribute("height", "2");
cylinder.setAttribute("radius", "0.75");
cylinder.setAttribute("position", "3 1 0");
scene.appendChild(cylinder);
```

We're getting a reference to the scene handler first, then we create the cylinder element as an A-Frame entity. After that it's all about setting the proper attributes: `color`, `height`, `radius` and `position`. The last line adds the newly created cylinder to the scene. That's it — you've created three different shapes with A-Frame! Here's how it looks right now:

![An illustration of 3D representation of three different geometry shapes displayed on a grey background: the first one is a darker grey torus, the second is a blue cube and the last one is a yellow cylinder.](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_A-Frame/shapes.png)

It is impressive to be able to create such a scene with just a few lines of HTML and JavaScript.

Animation
---------

We've already used `rotation` and `position` to move the shapes on the scene, and we can also scale them. These attributes can be manipulated to create the illusion of animation.

### Rotation

There's a special `<a-animation>` entity that can help us animate elements. Add the `<a-animation>` element seen below to the `<a-box>` element as a child, as shown:

```html
<a-box color="#0095DD" rotation="20 40 0" position="0 1 0">
  <a-animation
 attribute="rotation"
 from="20 0 0"
 to="20 360 0"
 direction="alternate"
 dur="4000"
 repeat="indefinite"
 easing="ease">
  </a-animation>
</a-box>
```

As with any other entities, you can define key properties for the animation. We'll be animating the `rotation` attribute from `20 0 0` to `20 360 0`, so it will do a full spin. The animation direction is set to alternate so the animation will be played forward, and then back. The duration is set to 4 seconds, and it will be repeated indefinitely. The animation uses `ease` for easing, with tween.js being implemented internally.

### Scaling

We can also add animation to entities with custom geometry like the torus, in much the same way. Add the following `<a-animation>` element to your torus:

```html
<a-entity
 geometry="
 primitive: torus;
 radius: 1;
 radiusTubular: 0.1;
 segmentsTubular: 12;"
 material="
 color: #EAEFF2;
 roughness: 0.1;
 metalness: 0.5;"
 rotation="10 0 0"
 position="-3 1 0">
  <a-animation
 attribute="scale"
 to="1 0.5 1"
 direction="alternate"
 dur="2000"
 repeat="indefinite"
 easing="linear">
  </a-animation>
</a-entity>
```

The attribute we want to animate for the torus is `scale`. The initial, default scale is `1 1 1`, and we're going to animate it to `1 0.5 1`, so the `y` axis will be scaled from `1` to `0.5`. The easing we're going to use is `linear`. By setting the direction to `alternate` the scale will be animated to `0.5`, and then animated back to `1` during 2 seconds. Again, the animation is being repeated indefinitely.

### Moving

We could use the `<a-animation>` to change the position of the third shape, or we could use JavaScript instead. Add this code at the end of the `<script>` tag:

```js
let t = 0;
function render() {
  t += 0.01;
  requestAnimationFrame(render);
  cylinder.setAttribute("position", `3 ${Math.sin(t \* 2) + 1} 0`);
}
render();
```

We're using the `render()` function to update the cylinder's position on every frame. Try changing the given values on the `y` axis and see how it affects the movement.

Conclusion
----------

Everything is rendered properly and animating — congratulations on building your first A-Frame scene! Here's how the final version looks and works:

If you have a VR device available, now is a good time to try out your scene with it too.

**Note:** You can also check it out on GitHub.

That was easier than you thought, right? A-Frame targets web developers by offering easy to use web markup and all the advantages that brings, such as JavaScript manipulation. It is easy to start with, but also provides a powerful API for advanced concepts, as well as dealing with cross browser differences and suchlike. The community is growing, just like the number of supported VR devices — it's a great time to start experimenting with such frameworks.

See also
--------

* A-Frame website
* Introducing A-Frame 0.1.0 article
* Made with A-Frame Tumblr
* A-Frame physics plugin
* A-Frame gamepad controls plugin


Building up a basic demo with Babylon.js - Game development

Building up a basic demo with Babylon.js
========================================

Babylon.js is one of the most popular 3D game engines used by developers. As with any other 3D library it provides built-in functions to help you implement common 3D functionality more quickly. In this article we'll take you through the real basics of using Babylon.js, including setting up a development environment, structuring the necessary HTML, and writing the JavaScript code.

We will try to create a simple demo first — a cube rendered on the screen. If you have already worked through our *Building up a basic demo* series with Three.js, PlayCanvas or A-Frame (or you are familiar with other 3D libraries) you'll notice that Babylon.js works on similar concepts: camera, light and objects.

Environment setup
-----------------

To start developing with Babylon.js, you don't need much. You should start off by:

* Making sure you are using a modern browser with good WebGL support, such as the latest Firefox or Chrome.
* Creating a directory to store your experiments in.
* Saving a copy of the latest Babylon.js engine inside your directory.
* Opening the Babylon.js documentation in a separate tab — it is useful to refer to.
HTML structure
--------------

Here's the HTML structure we will use:

```html
<!doctype html>
<html lang="en-GB">
  <head>
    <meta charset="utf-8" />
    <title>MDN Games: Babylon.js demo</title>
    <style>
 html,
 body,
 canvas {
 margin: 0;
 padding: 0;
 width: 100%;
 height: 100%;
 font-size: 0;
 }
 </style>
  </head>
  <body>
    <script src="babylon.js"></script>
    <canvas id="render-canvas"></canvas>
    <script>
 const canvas = document.getElementById("render-canvas");
 /\* all our JavaScript code goes here \*/
 </script>
  </body>
</html>
```

It contains some basic information like the document `<title>`, and some CSS to set the width and height of the `<canvas>` element (which Babylon.js will use to render the content on) to fill the entire available viewport space. The first `<script>` element includes the Babylon.js library in the page; we will write our example code in the second one. There is one helper variable already included, which will store a reference to the `<canvas>` element.

Before reading on, copy this code to a new text file and save it in your working directory as `index.html`.

Initializing the Babylon.js engine
----------------------------------

We have to create a Babylon.js engine instance first (passing it the `<canvas>` element to render on) before we start developing our game. Add the following code to the bottom of your second `<script>` element:

```js
const engine = new BABYLON.Engine(canvas);
```

The `BABYLON` global object contains all the Babylon.js functions available in the engine.

Creating a scene
----------------

A scene is the place where all the game content is displayed. While creating new objects in the demo, we will be adding them all to the scene to make them visible on the screen. Let's create a scene by adding the following lines just below our previous code:

```js
const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(0.8, 0.8, 0.8);
```

Thus, the scene is created and the second line sets the background color to light gray.

Creating a rendering loop
-------------------------

To make the scene actually visible we have to render it. Add these lines at the end of the `<script>` element, just before the closing `</script>`.

```js
function renderLoop() {
  scene.render();
}
engine.runRenderLoop(renderLoop);
```

We're using the engine's `runRenderLoop()` method to execute the `renderLoop()` function repeatedly on every frame — the loop will continue to render indefinitely until told to stop.

Creating a camera
-----------------

Now the setup code is in place we need to think about implementing the standard scene components: camera, light and objects. Let's start with the camera — add this line to your code below the scene creation and the line where we defined the `clearColor`.

```js
const camera = new BABYLON.FreeCamera(
  "camera",
  new BABYLON.Vector3(0, 0, -10),
  scene,
);
```

There are many cameras available in Babylon.js; `FreeCamera` is the most basic and universal one. To initialize it you need to pass it three parameters: any name you want to use for it, the coordinates where you want it to be positioned in the 3D space, and the scene you want to add it to.

**Note:** You probably noticed the `BABYLON.Vector3()` method in use here — this defines a 3D position on the scene. Babylon.js is bundled with a complete math library for handling vectors, colors, matrices etc.

Let there be light
------------------

There are various light sources available in Babylon.js. The most basic one is the `PointLight`, which works like a flashlight — shining a spotlight in a given direction. Add the following line below your camera definition:

```js
const light = new BABYLON.PointLight(
  "light",
  new BABYLON.Vector3(10, 10, 0),
  scene,
);
```

The parameters are very similar to the previously defined camera: the name of the light, a position in 3D space and the scene to which the light is added.

Geometry
--------

Now the scene is properly rendering we can start adding 3D shapes to it. To speed up development Babylon.js provides a bunch of predefined primitives that you can use to create shapes instantly in a single line of code. There are cubes, spheres, cylinders and more complicated shapes available. Let's start by defining the geometry for a box shape — add the following new code below your previous additions:

```js
const box = BABYLON.Mesh.CreateBox("box", 2, scene);
```

A mesh is a way the engine creates geometric shapes, so material can be easily applied to them later on. In this case we're creating a box using the `Mesh.CreateBox` method with its own name, a size of 2, and a declaration of which scene we want it added to.

**Note:** The size or position values (e.g. for the box size) are unitless, and can basically be anything you deem suitable for your scene — millimeters, meters, feet, or miles — it's up to you.

If you save and refresh now, your object will look like a square, because it's facing the camera. The good thing about objects is that we can move them on the scene however we want, for example rotating and scaling. Let's apply a little rotation to the box, so we can see more than one face — again, add these lines below the previous one:

```js
box.rotation.x = -0.2;
box.rotation.y = -0.4;
```

The box looks black at the moment, because we haven't defined any material to apply to its faces. Let's deal with that next.

Material
--------

Material is that thing covering the object — the colors or texture on its surface. In our case we will use a simple blue color to paint our box. There are many types of materials that can be used, but for now the standard one should be enough for us. Add these lines below the previous ones:

```js
const boxMaterial = new BABYLON.StandardMaterial("material", scene);
boxMaterial.emissiveColor = new BABYLON.Color3(0, 0.58, 0.86);
box.material = boxMaterial;
```

The `StandardMaterial` takes two parameters: a name, and the scene you want to add it to. The second line defines an `emissiveColor` — the one that will be visible for us. We can use the built-in `Color3` function to define it. The third line assigns the newly created material to our box.

Congratulations, you've created your first object in a 3D environment using Babylon.js! It was easier than you thought, right? Here's how it should look:

![Blue Babylon.js 3D box on the gray background.](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Babylon.js/cube.png)

And here's the code we have created so far:

You can also check it out on GitHub.

More shapes
-----------

We have a box on the scene already; now let's try adding more shapes.

### Torus

Let's try adding a torus — add the following lines below the previous code:

```js
const torus = BABYLON.Mesh.CreateTorus("torus", 2, 0.5, 15, scene);
torus.position.x = -5;
torus.rotation.x = 1.5;
```

This will create a torus and add it to the scene; the parameters are: name, diameter, thickness, tessellation (number of segments) and the scene to add it to. We also position it a bit to the left and rotate it on the `x` axis so it can be seen better. Now let's add a material:

```js
const torusMaterial = new BABYLON.StandardMaterial("material", scene);
torusMaterial.emissiveColor = new BABYLON.Color3(0.4, 0.4, 0.4);
torus.material = torusMaterial;
```

It looks similar to the box element — we're creating the standard material, giving it a grayish color and assigning it to the torus.

### Cylinder

Creating a cylinder and its material is done in almost exactly the same way as we did for the torus. Add the following code, again at the bottom of your script:

```js
const cylinder = BABYLON.Mesh.CreateCylinder("cylinder", 2, 2, 2, 12, 1, scene);
cylinder.position.x = 5;
cylinder.rotation.x = -0.2;
const cylinderMaterial = new BABYLON.StandardMaterial("material", scene);
cylinderMaterial.emissiveColor = new BABYLON.Color3(1, 0.58, 0);
cylinder.material = cylinderMaterial;
```

The cylinder parameters are: name, height, diameter at the top, diameter at the bottom, tessellation, height subdivisions and the scene to add it to. It is then positioned to the right of the cube, rotated a bit so its 3D shape can be seen, and given a yellow material.

Here's how the scene should look right now:

![Light gray torus, blue box and yellow cylinder created with Babylon.js on the gray background.](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Babylon.js/shapes.png)

This works, but it is a bit boring. In a game something is usually happening — we can see animations and such — so let's try to breathe a little life into those shapes by animating them.

Animation
---------

We already used `position` and `rotation` to adjust the position of the shapes; we could also scale them. To show actual animation, we need to make changes to these values inside the rendering loop at the end of our code, so they are updated on every frame. Define a helper variable — `t` — that we will use for animations, just before the `renderLoop`, and decrement it on every frame inside the loop, like this:

```js
let t = 0;
function renderLoop() {
  scene.render();
  t -= 0.01;
  // animation code goes here
}
engine.runRenderLoop(renderLoop);
```

The `t` variable will be incremented on every rendered frame.

### Rotation

Applying rotation is as easy as adding this line at the end of the `renderLoop` function:

```js
box.rotation.y = t \* 2;
```

It will rotate the box along the `y` axis.

### Scaling

Add this line below the previous one to scale the torus:

```js
torus.scaling.z = Math.abs(Math.sin(t \* 2)) + 0.5;
```

There's a little bit of adjustment made to make the animation look and feel nice. You can experiment with the values and see how it affects the animation.

### Moving

By changing the position of the cylinder directly we can move it on the scene — add this line below the previous one:

```js
cylinder.position.y = Math.sin(t \* 3);
```

The cylinder will float up and down on the `y` axis thanks to the `Math.sin()` function.

Conclusion
----------

Here's the final code listing, along with a viewable live example:

You can also see it on GitHub and fork the repository if you want to play with it yourself locally. Now you know the basics of Babylon.js engine; happy experimentation!


Building up a basic demo with PlayCanvas - Game development

Building up a basic demo with PlayCanvas
========================================

**PlayCanvas** is a popular 3D WebGL game engine, originally created by Will Eastcott and Dave Evans. It is open sourced on GitHub, with an editor available online and good documentation. The online editor is free for public projects with up to two team members, but there are also paid plans if you'd like to run a commercial private project with more developers.

![PlayCanvas website.](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/playcanvas-cover.png)

Games and demos
---------------

PlayCanvas has a few well-known demos published that showcase its possibilities.

* Tanx is a multiplayer tank game where you can drive your tank around, shooting at other players as you go.
* Swooop is a flying game where you pilot your plane around a magical island, collecting jewels and fuel as you go.
* Visualizations like the Star Lord and BMW i8 also take advantage of the engine and showcase what's possible.

![A list of PlayCanvas demos: Tanx, Swooop, Star Lord, BMW i8.](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/playcanvas-demos.png)

**Note:** Check out the list of featured demos to find more examples.

Engine vs. editor
-----------------

The engine itself can be used as a standard library by including its JavaScript file directly in your HTML, so you can start coding right away; in addition the PlayCanvas toolset comes with an online editor that you can use to drag and drop components onto the scene — a great way to create games and other apps requiring scenes if you're more of a designer than a coder. Those approaches are different but work equally well regarding achieving end goals.

PlayCanvas engine
-----------------

Built for modern browsers, PlayCanvas is a fully-featured 3D game engine with resource loading, an entity and component system, advanced graphics manipulation, collision and physics engine (built with ammo.js), audio, and facilities to handle control inputs from various devices (including gamepads). That's quite an impressive list of features — let's see some in action, check out the Building up a basic demo with PlayCanvas engine for details.

PlayCanvas editor
-----------------

Instead of coding everything from the beginning you can also use the online editor. This can be a more pleasant working environment if you are not someone who likes to code. See the Building up a basic demo with PlayCanvas editor for details.

Summary
-------

Of course, it depends on your approach — designers may favor the online editor while programmers will prefer having the full control over the coding environment and will probably use the engine's source files. The good thing is that you have a choice and can pick whatever tools suit you best.


Building up a basic demo with Three.js - Game development

Building up a basic demo with Three.js
======================================

A typical 3D scene in a game — even the simplest one — contains standard items like shapes located in a coordinate system, a camera to actually see them, lights and materials to make it look better, animations to make it look alive, etc. **Three.js**, as with any other 3D library, provides built-in helper functions to help you implement common 3D functionality more quickly. In this article we'll take you through the real basics of using Three, including setting up a development environment, structuring the necessary HTML, the fundamental objects of Three, and how to build up a basic demo.

**Note:** We chose Three because it is one of the most popular WebGL libraries, and it is easy to get started with. We are not trying to say it is better than any other WebGL library available, and you should feel free to try another library, such as CopperLicht or PlayCanvas.

Environment setup
-----------------

To start developing with Three.js, you don't need much. You should:

* Make sure you are using a modern browser with good WebGL support, such as the latest Firefox or Chrome.
* Create a directory to store your experiments in.
* Save a copy of the latest minimized Three.js library inside your directory.
* Open the Three.js documentation in a separate tab — it is useful to refer to.
HTML structure
--------------

Here's the HTML structure we will use:

```html
<!doctype html>
<html lang="en-GB">
  <head>
    <meta charset="utf-8" />
    <title>MDN Games: Three.js demo</title>
    <style>
 body {
 margin: 0;
 padding: 0;
 }
 canvas {
 width: 100%;
 height: 100%;
 }
 </style>
  </head>
  <body>
    <script src="three.min.js"></script>
    <script>
 const WIDTH = window.innerWidth;
 const HEIGHT = window.innerHeight;
 /\* all our JavaScript code goes here \*/
 </script>
  </body>
</html>
```

It contains some basic information like the document `<title>`, and some CSS to set the `width` and `height` of the `<canvas>` element, that Three.js will insert on the page to 100% to fill the entire available viewport space. The first `<script>` element includes the Three.js library in the page, and we will write our example code inside the second. There are two helper variables already included, which store the window's `width` and `height`.

Before reading further, copy this code to a new text file, and save it in your working directory as `index.html`.

Renderer
--------

A renderer is a tool which displays scenes right in your browser. There are a few different renderers: WebGL is the default, and others you can use are Canvas, SVG, CSS, and DOM. They differ in how everything is rendered, so the WebGL implementation will implement differently than the CSS one. Despite the variety of ways they achieve the goal, the experience will look the same for the user. Thanks to this approach, a fallback can be used, if a desired technology is not supported by the browser.

```js
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0xdddddd, 1);
document.body.appendChild(renderer.domElement);
```

We are creating a new WebGL renderer, setting its size to fit the whole available space on the screen, and appending the DOM structure to the page. You might have noticed the `antialias` parameter in the first line — this renders the edges of shapes more smoothly. The `setClearColor()` method sets our background to a light gray color, instead of the default black one.

Add this code into our second `<script>` element, just below the JavaScript comment.

Scene
-----

A scene is the place where everything happens. When creating new objects in the demo, we add them all inside the scene to become visible on the screen. In three.js, the scene is represented by a `Scene` object. Let's create it, by adding the following line below our previous lines:

```js
const scene = new THREE.Scene();
```

Later, we will be using the `.add()` method, to add objects to this scene.

Camera
------

We have the rendered scene, but we still need to add a camera to view our handiwork — imagine a movie set without any cameras. The following lines put the camera in place in the 3D coordinate system, and point it in the direction of our scene, so we can finally see something:

```js
const camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT);
camera.position.z = 50;
scene.add(camera);
```

Add the above lines to your code, below those previously added.

There are other types of camera available (Cube, Orthographic), but the simplest is Perspective. To initialize it, we have to set its field of view and aspect ratio: the former is used to set how much is seen, and the latter is important for the objects on the screen to have the right proportions when rendered, and not look stretched. Let's explain values we are setting for the code above:

* The value we set for the field of view, 70, is something we can experiment with: the higher the value, the greater the amount of scene the camera will show. Imagine a normal camera view, versus a fish eye effect, which allows a lot more to be seen. The default value is 50.
* The aspect ratio is set to the current width and height of the window so it will be dynamically adjusted. We could set a fixed ratio — for example 16 ⁄ 9, which is the aspect ratio of a widescreen TV. The default value is 1.
* The `z` position, with the value of 50 units, is the distance between the camera and the center of the scene on the `z` axis. Here we're moving the camera back, so the objects in the scene can be viewed. 50 feels about right. It's not too near, or too far, and the sizes of the objects allow them to stay on the scene, within the given field of view. The `x` and `y` values, if not specified, will default to 0.

You should experiment with these values and see how they change what you see in the scene.

**Note:** The distance values (e.g. for the camera z position) are unitless, and can be anything you deem suitable for your scene: millimeters, meters, feet, or miles. It's up to you.

Rendering the scene
-------------------

Everything is ready, but we still can't see anything. Although we've set up the renderer, we still need to render everything. Our `render()` function will do this job, with a little help from `requestAnimationFrame()`, which causes the scene to be re-rendered constantly on every frame:

```js
function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}
render();
```

On every new frame the `render` function is invoked, and the `renderer` renders the `scene` and the `camera`. Right after the function declaration, we're invoking it for the first time to start the loop, after which it will be used indefinitely.

Again, add this new code below your previous additions. Try saving the file and opening it in your browser. You should now see a gray window. Congratulations!

Geometry
--------

Now our scene is properly rendering, we can start adding 3D shapes. To speed up development, Three.js provides a bunch of predefined primitives, which you can use to create shapes instantly in a single line of code. There's cubes, spheres, cylinders, and more complicated shapes available. Detail like drawing required vertices and faces, for a given shape, is handled by the Three framework, so we can focus on higher level coding. Let's start, by defining the geometry for a cube shape, adding the following just above the `render()` function:

```js
const boxGeometry = new THREE.BoxGeometry(10, 10, 10);
```

In this case, we define a simple cube that is 10 x 10 x 10 units. The geometry itself is not enough though, we also need a material that will be used for our shape.

Material
--------

A material is what covers an object, the colors, or textures on its surface. In our case, we will choose a simple blue color to paint our box. There are a number of predefined materials which can be used: Basic, Phong, Lambert. Let's play with the last two later, but for now, the Basic one should be enough:

```js
const basicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095dd });
```

Add this line below the previously added.

Our material is now ready, what next?

Mesh
----

To apply the material to a geometry, a mesh is used. This takes on a shape, and adds the specified material to every face:

```js
const cube = new THREE.Mesh(boxGeometry, basicMaterial);
```

Again, add this line below the one you previously added.

Adding the cube to the scene
----------------------------

We've now created a cube, using the geometry and material defined earlier. The last thing to do is to place the cube to our scene. Add this line below the previous one:

```js
scene.add(cube);
```

If you save, and refresh your Web browser, our object will now look like a square, because it's facing the camera. The good thing about objects, is that we can move them on the scene, however we want. For example, rotating and scaling as we like. Let's apply a little rotation to the cube, so we can see more than one face. Again, adding our code below the previous:

```js
cube.rotation.set(0.4, 0.2, 0);
```

Congratulations, you've created an object in a 3D environment! This might have proven easier than you first thought? Here's how it should look:

![Blue cube on a gray background rendered with Three.js.](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Three.js/cube.png)

And here's the code we have created so far:

You can also check it out on GitHub.

More shapes and materials
-------------------------

Now we will add more shapes to the scene, and explore other shapes, materials, lighting, and more. Let's move the cube to the left, to make space for some friends. Adding the following line just below the previous one:

```js
cube.position.x = -25;
```

Now onto more shapes and materials. What might happen when you add a torus, wrapped in the Phong material? Try adding the following lines, just below the lines defining the cube.

```js
const torusGeometry = new THREE.TorusGeometry(7, 1, 6, 12);
const phongMaterial = new THREE.MeshPhongMaterial({ color: 0xff9500 });
const torus = new THREE.Mesh(torusGeometry, phongMaterial);
scene.add(torus);
```

These lines will add a torus geometry; the `TorusGeometry()` method's parameters define, and the parameters are `radius`, `tube diameter`, `radial segment count`, and `tubular segment count`. The Phong material should look more glossy than the box's simple Basic material, though right now our torus will just look black.

We can choose more fun predefined shapes. Let's play some more. Add the following lines, below those defining the torus:

```js
const dodecahedronGeometry = new THREE.DodecahedronGeometry(7);
const lambertMaterial = new THREE.MeshLambertMaterial({ color: 0xeaeff2 });
const dodecahedron = new THREE.Mesh(dodecahedronGeometry, lambertMaterial);
dodecahedron.position.x = 25;
scene.add(dodecahedron);
```

This time, we are creating a dodecahedron, a shape containing twelve flat faces. The parameter, `DodecahedronGeometry(),` defines the size of the object. We're using a Lambert material, similar to Phong, but should be less glossy. Again it's black, for now. We're moving the object to the right, so it's not in the same position as the box, or torus.

As mentioned above, the new objects currently just look black. To have both, the Phong and Lambert materials properly visible, we need to introduce a source of light.

Lights
------

There are various types of light sources available in Three.js. The most basic is `PointLight`, which works like a flashlight, shining a spotlight in a defined direction. Add the following lines, below your shape definitions:

```js
const light = new THREE.PointLight(0xffffff);
light.position.set(-10, 15, 50);
scene.add(light);
```

We define a white point of light, set its position a little away from the center of the scene, so it can light up some parts of the shapes, finally adding it to the scene. Now everything works as it should, all three shapes are visible. You should check the documentation for other types of lights, like Ambient, Directional, Hemisphere, or Spot. Experiment placing them on our scene, to see how they affect it.

![Shapes: blue cube, dark yellow torus and dark gray dodecahedron on a gray background rendered with Three.js.](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Three.js/shapes.png)

This looks a little boring though. In a game, something is usually happening. We might see animations and such. So let's try breathing a little life into these shapes, by animating them!

Animation
---------

We already used rotation, to adjust the position of the cube. We can also scale the shapes, or change their positions. To show animation, we need to make changes to these values inside the render loop, so they update on each frame.

### Rotation

Rotating is straightforward. You add a value to a given direction of rotation on each frame. Add this line of code, right after the `requestAnimationFrame()` invocation inside the `render` function:

```js
cube.rotation.y += 0.01;
```

This rotates the cube on every frame, by a tiny bit, so the animation looks smooth.

### Scaling

We can also scale an object. Applying a constant value, we would make it grow, or shrink just once. Let's make things more interesting. First, we implement a helper variable, called `t,` for counting elapsed time. Add it right before the `render()` function:

```js
let t = 0;
```

Now let's increase the value by a given constant value, on each frame of the animation. Add the following lines, just below the `requestAnimationFrame()` invocation:

```js
t += 0.01;
torus.scale.y = Math.abs(Math.sin(t));
```

We use `Math.sin`, ending up with quite an interesting result. This scales the torus, repeating the process, as `sin` is a periodic function. We're wrapping the scale value in `Math.abs`, to pass the absolute values, greater or equal to 0. As sin is between -1 and 1, negative values might render out torus in unexpected way. In this case it looks black half the time.

Now, onto movement.

### Moving

Aside from rotation, and scaling, we can additionally move objects around the scene. Add the following, again just below our `requestAnimationFrame()` invocation:

```js
dodecahedron.position.y = -7 \* Math.sin(t \* 2);
```

This will move the dodecahedron up and down, by applying the `sin()` value to the y-axis on each frame, and a little adjustment to make it look cooler. Try changing these values, to see how it affects the animations.

Conclusion
----------

Here's the final code:

You can also see it on GitHub and fork the repository, if you want to play with it locally. Now you understand the basics of Three.js, you can jump back to the parent page, 3D on the Web.

You could also try learning raw WebGL, to gain a better understanding of what's going on underneath. See our WebGL documentation.


Building up a basic demo with the PlayCanvas engine - Game development

Building up a basic demo with the PlayCanvas engine
===================================================

Built for modern browsers, **PlayCanvas** is a fully-featured 3D game engine with resource loading, an entity and component system, advanced graphics manipulation, collision and physics engine (built with ammo.js), audio, and facilities to handle control inputs from various devices (including gamepads).

That's quite an impressive list of features — let's see some in action.

![PlayCanvas engine repository on GitHub.](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/engine/playcanvas-github.png)

We will try putting together a simple demo first — a cube rendered on the screen. If you have already worked through our Building up a basic demo with Three.js article (or you are familiar with other 3D libraries) you'll notice that PlayCanvas works on similar concepts: camera, light and objects.

Environment setup
-----------------

To start developing with PlayCanvas, you don't need much. You should start off by:

* Making sure you are using a modern browser with good WebGL support, such as the latest Firefox or Chrome.
* Creating a directory to store your experiments in.
* Saving a copy of the latest PlayCanvas engine inside your directory.
* Opening the PlayCanvas documentation in a separate tab — it is useful to refer to.
HTML structure
--------------

Here's the HTML structure we will use.

```html
<!doctype html>
<html lang="en-GB">
  <head>
    <meta charset="utf-8" />
    <title>MDN Games: PlayCanvas demo</title>
    <style>
 body {
 margin: 0;
 padding: 0;
 }
 canvas {
 width: 100%;
 height: 100%;
 }
 </style>
  </head>
  <body>
    <script src="playcanvas-latest.js"></script>
    <canvas id="application-canvas"></canvas>
    <script>
 const canvas = document.getElementById("application-canvas");
 /\* all our JavaScript code goes here \*/
 </script>
  </body>
</html>
```

It contains some basic information like the document `<title>`, and some CSS to set the width and height of the `<canvas>` element that PlayCanvas will use to 100% so that it will fill the entire available viewport space. The first `<script>` element includes the PlayCanvas library in the page; we will write our example code in the second one. There is one helper variable already included, which will store a reference to the `<canvas>` element.

Before reading on, copy this code to a new text file and save it in your working directory as `index.html`.

PlayCanvas application
----------------------

To begin developing our game we have to create the PlayCanvas application first (using the given `<canvas>` element), and then start the update loop. Add the following code to the bottom of your second `<script>` element:

```js
const app = new pc.Application(canvas);
app.start();
```

The `pc` global object contains all the PlayCanvas functions available in the engine.

Next, we'll set the Canvas to fill the window, and automatically change its resolution to be the same as the Canvas size. Again, add the following lines at the bottom of your script.

```js
app.setCanvasFillMode(pc.FILLMODE\_FILL\_WINDOW);
app.setCanvasResolution(pc.RESOLUTION\_AUTO);
```

Camera
------

Now when the setup code is in place we need to think about implementing the standard scene components: camera, lights and objects. Let's start with the camera — add these lines to your code, below the previous ones.

```js
const camera = new pc.Entity();
camera.addComponent("camera", {
  clearColor: new pc.Color(0.8, 0.8, 0.8),
});

app.root.addChild(camera);
camera.setPosition(0, 0, 7);
```

The code above will create a new `Entity`.

**Note:** An Entity is any object used in the scene — it can be an object like a box, cylinder or cone, but it can also be a camera, light or sound source.

Then it adds a `camera` component to it with the light gray `clearColor` — the color will be visible as the background. Next, the `camera` object is added to the root of our application and positioned to be 7 units away from the center of the scene on the `z` axis. This allows us to make some space to visualize the objects that we will create later on.

**Note:** The distance values (e.g. for the camera z position) are unitless, and can basically be anything you deem suitable for your scene — millimeters, meters, feet, or miles — it's up to you.

Try saving the file and loading it in your browser. You should now see a gray window. Congratulations!

Geometry
--------

Now the scene is properly rendering we can start adding 3D shapes to it. To speed up development PlayCanvas provides a bunch of predefined primitives that you can use to create shapes instantly in a single line of code. There are cubes, spheres, cylinders and more complicated shapes available. Drawing everything for given shape is taken care of by the engine, so we can focus on the high level coding. Let's start by defining the geometry for a cube shape — add the following new code below your previous additions:

```js
const box = new pc.Entity();
box.addComponent("model", { type: "box" });
app.root.addChild(box);
box.rotate(10, 15, 0);
```

It will create an `Entity` with the `box` model component and add it to the root of the application, our scene. We also rotate the box a bit to show that it's actually a 3D cube and not a square.

The cube is visible, but it is completely. To make it look better we need to shine some light onto it.

Lights
------

The basic light types in PlayCanvas are directional and ambient. The first type is a directional light placed somewhere on the scene while the second one reflects the light from the first type, so it looks more natural; this can be set globally. Again, add the new code below your previous additions.

```js
const light = new pc.Entity();
light.addComponent("light");
app.root.addChild(light);
light.rotate(45, 0, 0);
```

It will create a light `Entity` component and add it to the scene. We can rotate the light on the `x` axis to make it shine on more than one side of the cube. It's time to add the ambient light:

```js
app.scene.ambientLight = new pc.Color(0.2, 0.2, 0.2);
```

The code above assign a dark grey ambient light for the whole scene. The box look better now, but it could get some colors to look even better - for that we need to create material for it.

Material
--------

The basic PlayCanvas material is called PhongMaterial — add the following lines below the previous code.

```js
const boxMaterial = new pc.PhongMaterial();
boxMaterial.diffuse.set(0, 0.58, 0.86);
boxMaterial.update();
box.model.model.meshInstances[0].material = boxMaterial;
```

By diffusing the light on the object, we can give it its own color — we'll choose a nice familiar blue.

**Note:** In PlayCanvas, the color channel values are provided as floats in the range `0-1`, instead of integers of `0-255` as you might be used to using on the Web.

After the material is created and its color is set, it has to be updated so our changes are going to be applied. Then all we need to do is set the `box`'s material to the newly created `boxMaterial`.

Congratulations, you've created your first object in a 3D environment using PlayCanvas! It was easier than you thought, right? Here's how it should look:

![Blue cube on a gray background rendered with PlayCanvas.](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/engine/cube-playcanvas.png)

And here's the code we have created so far:

You can also check it out on GitHub.

More shapes
-----------

Now we will add more shapes to the scene. Let's move the cube 2 units to the left to make space for some friends — add the following line just below the previous code:

```js
box.translate(-2, 0, 0);
```

Now let's add a new shape — how about a cylinder?

### Cylinder

Add the following lines at the bottom of your JavaScript code:

```js
const cylinder = new pc.Entity();
cylinder.addComponent("model", { type: "cylinder" });
app.root.addChild(cylinder);
cylinder.rotate(15, 0, 0);
```

This looks very similar to the code we used for creating a cube, but instead of the `box` component we are adding a `cylinder`. It is also rotated around the `x` axis to show it's actually a 3D shape. To make the cylinder have a color, let's say yellow, we need to create the material for it, as before. Add the following lines:

```js
const cylinderMaterial = new pc.PhongMaterial();
cylinderMaterial.diffuse.set(1, 0.58, 0);
cylinderMaterial.update();
cylinder.model.model.meshInstances[0].material = cylinderMaterial;
```

### Cone

Creating a cone and its material is done in almost exactly the same way as we did for the cylinder. Add the following code, again, at the bottom of your script:

```js
const cone = new pc.Entity();
cone.addComponent("model", { type: "cone" });
app.root.addChild(cone);
cone.translate(2, 0, 0);

const coneMaterial = new pc.PhongMaterial();
coneMaterial.diffuse.set(0.9, 0.9, 0.9);
coneMaterial.update();
cone.model.model.meshInstances[0].material = coneMaterial;
```

The code above will create a new `cone`, add it to the `app` and move it by 2 units to the right so it's not overlapping the cylinder. Then the material is created, given a gray color, and assigned to the cone `Entity`.

Here's how it should look right now:

![Shapes: blue cube, yellow cylinder and gray cone on a light gray background rendered with PlayCanvas.](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/engine/shapes-playcanvas.png)

This works, but it is a bit boring. In a game something is usually happening — we can see animations and such — so let's try to breathe a little life into those shapes by animating them.

Animation
---------

We already used `translate` or `rotate` to adjust the position of the shapes; we could also change their positions directly with `setPosition`, or scale them. To show actual animation, we need to make changes to these values inside the rendering loop, so they are updated on every frame. There's a special `update` event that we can use for that — add the following code just below the previous additions:

```js
let timer = 0;
app.on("update", (deltaTime) => {
  timer += deltaTime;
  // code executed on every frame
});
```

The callback takes the `deltaTime` as the parameter, so we have the relative time that has passed since the previous invocation of this update. For time based animations we'll use a `timer` variable that will store the time that has passed since the start of the app by adding the `deltaTime` to it on every update.

### Rotation

Rotating is quite easy — all you need to do is to add a defined value to the given direction of rotation on each frame. Add this line of code inside the `app.on("update")` callback function, right after the addition of the `deltaTime` to the `timer` variable:

```js
box.rotate(deltaTime \* 10, deltaTime \* 20, deltaTime \* 30);
```

It will rotate the `box` by `deltaTime*10` on the `x` axis, `deltaTime*20` on the `y` axis and `deltaTime*30` on the `z` axis, on very frame — giving us a smooth animation.

### Scaling

We can also scale a given object — there's a function for that called `setLocalScale`. Add the following, again into the callback:

```js
cylinder.setLocalScale(1, Math.abs(Math.sin(timer)), 1);
```

Here we are using `Math.sin` to scale the cylinder in a cycle, bigger and smaller again. We're wrapping the `y` scale value in `Math.abs` to pass the absolute values (greater or equal to 0); `sin` varies between -1 and 0, and for negative values the cylinder scaling can render unexpectedly (in this case it looks black half the time.)

Now onto the movement part.

### Moving

Beside rotation and scaling we can also move objects around the scene. Add the following code to achieve that.

```js
cone.setPosition(2, Math.sin(timer \* 2), 0);
```

This will move the `cone` up and down by applying the `sin` value to the `y` axis on each frame, with a little bit of adjustment to make it look cooler. Try changing the value to see how it affects the animation.

Conclusion
----------

Here's the final code listing, along with a viewable live example:

You can also see it on GitHub and fork the repository if you want to play with it yourself locally. Now you know the basics of PlayCanvas engine; happy experimentation!

Summary
-------

Now you can continue reading the PlayCanvas editor article, go back to the Building up a basic demo with PlayCanvas page, or go back a level higher to the main 3D Games on the Web page.


Building up a basic demo with PlayCanvas editor - Game development

Building up a basic demo with PlayCanvas editor
===============================================

Instead of coding everything from scratch you can also use the online **PlayCanvas editor**. This can be a more pleasant working environment if you are not someone who likes to code.

Creating an account
-------------------

The PlayCanvas Editor is free — all you have to do to begin with is register your account and login:

![PlayCanvas Editor - Login](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-login.png)

When you first sign up, you are taken straight into the editor and given a simple starter tutorial involving editing a 3D rolling ball game. You can finish this before you continue our tutorial if you like. When you are ready to continue with our tutorial, go to your canvas homepage — for example mine is `https://playcanvas.com/end3r`. Here's what the page looks like — you can create projects and manage them, change their settings etc.

Creating a new project
----------------------

Start a brand new project by clicking on the *New* button:

![PlayCanvas Editor - Panel](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-panel.png)

The resulting dialog box will show a few different options. There are starter kits available, but we don't want to load models or start a platform game.

1. We want to start small, so we will use the empty project — click on the Blank Project option and enter a name for it (we are using "MDN Games demo".)
2. Enter a description if you want — it is optional.
3. Click *Create* to have it created.

![PlayCanvas Editor - New project](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-newproject.png)

Next you'll see your project's page — there's not much yet. By clicking the *Editor* button we'll launch the online PlayCanvas editor where we'll create our scene with the shapes. Do this now.

![PlayCanvas Editor - Project](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-project.png)

Creating the scene
------------------

Here's how the scene looks initially in the editor. Even though it's a blank new project we don't have to start entirely from scratch — the camera and directional light are prepared already, so you don't have to worry about them.

![PlayCanvas Editor - Scene](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-scene.png)

Now onto the creative part. To add an entity to the scene you have to click on the big plus button located in the top left area of the editor, next to the Hierarchy text. When hovering over that button with your mouse the label will say 'Add Entity' — that's exactly what we want to do. An Entity is any object used in the scene — it can be an object like a box, cylinder or cone, but it can also be a camera, light or sound source. After clicking the button you'll see a dropdown list containing a lot of various entities to choose from. Go ahead and click *Box* — it will be added to the scene.

![PlayCanvas Editor - New box](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-newbox.png)

The box is created with the default values — width, height and depth are set to 1, and it is placed in the middle of the scene. You can drag it around or apply new values in the right panel.

![PlayCanvas Editor - Box](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-box.png)

To add some colors to the scene we need a new material that will be used on the newly created box. Click on the plus button in the *Assets* tab, and click on the *Material* option in the dropdown list that appears to create a new material.

![PlayCanvas Editor - New material](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-newmaterial.png)

Click on your new material in the assets tab and its entity inspector will appear on the right-hand side of the display. Now edit the *Name* text field to give it a unique name (we've chosen *boxMaterial*). A unique name will help us remember what this material is for — we will add more later!

![PlayCanvas Editor - Box material](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-boxmaterial.png)

To change its color we'll use the *Diffuse* option in the entity inspector. Click *Diffuse*, then select the colored box next to the Color label — it will open a color wheel. From here you can click your desired color or enter it in the bottom text field as a hex value. We've chosen a blue color with a hex value of `0095DD` — enter this code in the text field and press return for it to be accepted.

**Note:** Yes, you read that right — you need to enter the hex value without the hash/pound symbol.

![PlayCanvas Editor - Diffuse color](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-diffusecolor.png)

Now we can apply the colored material to the shape by clicking and dragging its icon from the bottom part of the screen (the little dot on the left-hand side of the material's name — it can be a bit fiddly to select; just persevere) onto the box on the scene.

![PlayCanvas Editor - Box drop](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-boxdrop.png)

So, at this point we've created a blue box. Click on the box to bring up its entity sidebar — you'll see options for changing its position, rotation, and scale. Try applying the rotation values X: 10 and Y: 20.

![PlayCanvas Editor - Rotate](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-rotate.png)

Now click on the play arrow in the top right corner of the scene to launch and render the scene — it will be opened in a separate browser tab.

![PlayCanvas Editor - Launch](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-launch.png)

This looks great! Let's add more shapes to the scene to make it look more interesting.

![PlayCanvas Editor - Boxrender](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-boxrender.png)

Adding more shapes
------------------

To make way for more shapes, move the box to the left to make some room for the next shape. You can do this by giving it an X position value of -2.

Adding other shapes involves a very similar process to adding the box. Click on the Root folder in the hierarchy panel (to make sure that the new shape appears in the root, and not as a child of the Box) then Click on the big *Add Entity* (plus) button and select cylinder from the dropdown list — it will add a new cylinder shape to the scene.

![PlayCanvas Editor - Cylinder](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-cylinder.png)Now follow the same steps as we did before when coloring the cube:

* Create a new material using the *Add Asset* (plus) button.
* Make sure the New Material in the Assets panel is selected, to bring up the entity inspector.
* Give the material a new name, along the lines of `cylinderMaterial`.
* Click diffuse, then click the color picker — give it an orange color (we used FF9500.)
* Drag and drop the `cylinderMaterial` icon onto the cylinder object on the screen to apply that color.

![PlayCanvas Editor - Cylinder material](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-cylindermaterial.png)

Follow the same approach again to add a cone to the scene, giving it a grayish color (we used EAEFF2.) You should now have three shapes on your scene, something like the below screenshot.

![PlayCanvas Editor - Cone](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-cone.png)

Animating our scene
-------------------

Animating 3D models might be considered an advanced thing to do, but all we want to do is to control a few properties of a given object — we can use a script component to do that. Click on the plus button in the Assets panel, select the Script option, and name your new script file `boxAnimation.js`.

![PlayCanvas Editor - Box animation](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-boxanimation.png)

If you double click on it, you'll be moved to a code editor. As you can see, the file contains some boilerplate code already:

```js
pc.script.create("boxAnimation", function (app) {
  class BoxAnimation {
    constructor(entity) {
      this.entity = entity;
    }

    // Called once after all resources are loaded and before the first update
    initialize() {}

    // Called every frame, dt is time in seconds since last update
    update(dt) {}
  }

  return BoxAnimation;
});
```

The most interesting part is the `update()` function, which is where we can put any code that we want repeated on every frame. Add the following line inside this function, to rotate the cube on every frame:

```js
this.entity.rotate(dt \* 10, dt \* 20, dt \* 30);
```

In the line above `this.entity` refers to the object to which the script will be attached (the box); using the `dt` variable, which contains the delta time passed since the previous frame, we can rotate the box by a different amount around all three axes.

1. Save the changes using the Save button in the top right of the code editor, then return to the main editor tab. Here, follow these steps:
2. Be sure you have the box selected on the scene.
3. Click on *Add component*, then *Script* in the entity inspector.
4. At the bottom of the screen you can see the list of scripts available — for now there's only `boxAnimation.js` — clicking it will add the animation script to the box object.

![PlayCanvas Editor - Box script](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-boxscript.png)

### The cylinder

Now we'll do the same steps for cylinder. First:

1. Create a new Script asset.
2. Name it `cylinderAnimation.js`.
3. Double click the script icon to launch the code editor.

This time instead of rotating the object we will try to scale it. For that we'll need a timer to store the total amount of time passed since the start of the animation. Add this code to the `initialize()` function:

```js
this.timer = 0;
```

And those two lines to the `update()` function:

```js
this.timer += dt;
this.entity.setLocalScale(1, Math.abs(Math.sin(this.timer)), 1);
```

The `setLocalScale()` method applies the given values to the X, Y and Z axes of the object. In our case we're modifying the scale of the cylinder on the Y axis, giving it as a value the `Math.sin()` of the timer, with `Math.abs()` applied to the result of that to have the values always above zero (0-1; sin values are normally between -1 and 1.) This gives us a nice scaling effect as a result.

Remember to add the `cylinderAnimation.js` file to the Cylinder object to apply the given animations.

### The cone

Time to play with the last object — the cone. Create a `coneAnimation.js` file and double click it to open it in the editor.

Next, add the following line to the `initialize()` function:

```js
this.timer = 0;
```

To move the cone up and down we will use the `setPosition()` method — add the code below to the `update()` function:

```js
this.timer += dt;
this.entity.setPosition(2, Math.sin(this.timer \* 2), 0);
```

The position of the cone will be animated on each frame by being passed the `Math.sin()` value of the `timer` at each point in time — we have doubled the `this.timer` value to make it move higher.

Add the `coneAnimation.js` script to the cone object, as before.

Test the demo out
-----------------

Launch the demo to see the effects — all the shapes should animate. Congratulations, you've completed the tutorial!

![PlayCanvas Editor - Shapes](/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas/editor/playcanvas-editor-shapes.png)

Summary
-------

Now you can check the PlayCanvas engine article if you haven't seen it yet, go back to the Building up a basic demo with PlayCanvas page, or go back a level higher to the main 3D Games on the Web page.


Bounding volume collision detection with THREE.js - Game development

Bounding volume collision detection with THREE.js
=================================================

This article shows how to implement **collision detection between bounding boxes and spheres using the Three.js** library. It is assumed that before reading this you have read our 3D collision detection introductory article first, and have basic knowledge about Three.js.

Using `Box3` and `Sphere`
-------------------------

Three.js has objects that represent **mathematical volumes** and shapes — for 3D AABB and bounding spheres we can use the **`Box3`** and **`Sphere`** objects. Once instantiated, they have methods available to do intersection tests against other volumes.

### Instantiating boxes

To create a **`Box3` instance**, we need to provide the **lower and upper boundaries** of the box. Usually we will want this AABB to be "linked" to an object in our 3D world (like a character.) In Three.js, `Geometry` instances have a `boundingBox` property with `min` and `max` boundaries for the object. Keep in mind that in order for this property to be defined, you need to manually call `Geometry.computeBoundingBox` beforehand.

```js
const knot = new THREE.Mesh(
  new THREE.TorusKnotGeometry(0.5, 0.1),
  new MeshNormalMaterial({}),
);

knot.geometry.computeBoundingBox();
const knotBBox = new Box3(
  knot.geometry.boundingBox.min,
  knot.geometry.boundingBox.max,
);
```

**Note:** The `boundingBox` property takes the `Geometry` itself as reference, and not the `Mesh`. So any transformations such as scale, position, etc. applied to the `Mesh` will be ignored while computing the calculating box.

A more simple alternative that fixes the previous issue is to set those boundaries later on with `Box3.setFromObject`, which will compute the dimensions taking into account a 3D entity's **transformations *and* any child meshes** as well.

```js
const knot = new THREE.Mesh(
  new THREE.TorusKnotGeometry(0.5, 0.1),
  new MeshNormalMaterial({}),
);

const knotBBox = new Box3(new THREE.Vector3(), new THREE.Vector3());
knotBBox.setFromObject(knot);
```

### Instantiating spheres

Instantiating **`Sphere` objects** is similar. We need to provide the sphere's center and radius, which can be added to the `boundingSphere` property available in `Geometry`.

```js
const knot = new THREE.Mesh(
  new THREE.TorusKnotGeometry(0.5, 0.1),
  new MeshNormalMaterial({}),
);

const knotBSphere = new Sphere(
  knot.position,
  knot.geometry.boundingSphere.radius,
);
```

Unfortunately, there is no equivalent of `Box3.setFromObject` for Sphere instances. So if we apply transformations or change the position of the `Mesh`, we need to manually update the bounding sphere. For instance:

```js
knot.scale.set(2, 2, 2);
knotBSphere.radius = knot.geometry.radius \* 2;
```

### Intersection tests

#### Point vs. `Box3` / `Sphere`

Both `Box3` and `Sphere` have a **`containsPoint`** method to do this test.

```js
const point = new THREE.Vector3(2, 4, 7);
knotBBox.containsPoint(point);
```

#### `Box3` vs. `Box3`

The **`Box3.intersectsBox`** method is available for performing this test.

```js
knotBbox.intersectsBox(otherBox);
```

**Note:** This is different from the `Box3.containsBox` method, which checks whether the Box3 *fully* wraps another one.

#### `Sphere` vs. `Sphere`

In a similar fashion as before, there is a **`Sphere.intersectsSphere`** method to perform this test.

```js
knotBSphere.intersectsSphere(otherSphere);
```

#### `Sphere` vs. `Box3`

Unfortunately this test is not implemented in Three.js, but we can patch Sphere to implement a Sphere vs. AABB intersection algorithm.

```js
// expand THREE.js Sphere to support collision tests vs. Box3
// we are creating a vector outside the method scope to
// avoid spawning a new instance of Vector3 on every check

THREE.Sphere.__closest = new THREE.Vector3();
THREE.Sphere.prototype.intersectsBox = function (box) {
  // get box closest point to sphere center by clamping
  THREE.Sphere.__closest.set(this.center.x, this.center.y, this.center.z);
  THREE.Sphere.__closest.clamp(box.min, box.max);

  const distance = this.center.distanceToSquared(THREE.Sphere.__closest);
  return distance < this.radius \* this.radius;
};
```

### Demos

We have prepared some live demos to demonstrate these techniques, with source code to examine.

* Point vs. Box and Sphere
* Box vs. Box and Sphere
* Sphere vs. Box and Sphere

![A knot object, a large sphere object and a small sphere object in 3-D space. Three vectors are drawn on the small sphere. The vectors point in the directions of the three axes that define the space. Text at the bottom reads: Drag the ball around.](/en-US/docs/Games/Techniques/3D_collision_detection/Bounding_volume_collision_detection_with_THREE.js/screen_shot_2015-10-20_at_15.19.16.png)

Using `BoxHelper`
-----------------

As an alternative to using raw `Box3` and `Sphere` objects, Three.js has a useful object to make handling **bounding boxes easier: `BoxHelper`** (previously `BoundingBoxHelper`, which has been deprecated). This helper takes a `Mesh` and calculates a bounding box volume for it (including its child meshes). This results in a new box `Mesh` representing the bounding box, which shows the bounding box's shape, and can be passed to the previously seen `setFromObject` method in order to have a bounding box matching the `Mesh`.

`BoxHelper` is the **recommended** way to handle 3D collisions with bounding volumes in Three.js. You will miss sphere tests, but the tradeoffs are well worth it.

The advantages of using this helper are:

* It has an `update()` method that will **resize** its bounding box Mesh if the linked Mesh rotates or changes its dimensions, and update its **position**.
* It **takes into account the child meshes** when computing the size of the bounding box, so the original mesh and all its children are wrapped.
* We can easily debug collisions by **rendering** the `Mesh`es that `BoxHelper` creates. By default they are created with a `LineBasicMaterial` material (a three.js material for drawing wireframe-style geometries).

The main disadvantage is that it **only creates box bounding volumes**, so if you need spheres vs. AABB tests you need to create your own `Sphere` objects.

To use it, we need to create a new `BoxHelper` instance and supply the geometry and — optionally — a color that will be used for the wireframe material. We also need to add the newly created object to the `three.js` scene in order to render it. We assume our scene variable to be called `scene`.

```js
const knot = new THREE.Mesh(
  new THREE.TorusKnotGeometry(0.5, 0.1),
  new THREE.MeshNormalMaterial({}),
);
const knotBoxHelper = new THREE.BoxHelper(knot, 0x00ff00);
scene.add(knotBoxHelper);
```

In order to also have our actual `Box3` bounding box, we create a new `Box3` object and make it assume the `BoxHelper`'s shape and position.

```js
const box3 = new THREE.Box3();
box3.setFromObject(knotBoxHelper);
```

If we change the `Mesh` position, rotation, scale, etc. we need to call the `update()` method so the `BoxHelper` instance matches its linked `Mesh`. We also need to call `setFromObject` again in order to make the `Box3` follow the `Mesh`.

```js
knot.position.set(-3, 2, 1);
knot.rotation.x = -Math.PI / 4;
// update the bounding box so it stills wraps the knot
knotBoxHelper.update();
box3.setFromObject(knotBoxHelper);
```

Performing **collision tests** is done in the same way as explained in the above section — we use our Box3 object in the same way as described above.

```js
// box vs. box
box3.intersectsBox(otherBox3);
// box vs. point
box3.containsPoint(point.position);
```

### Demos

There are **two demos** you can take a look at on our live demos page. The first one showcases point vs. box collisions using `BoxHelper`. The second one performs box vs. box tests.

![A knot object, a sphere object and a cube object in 3-D space. The knot and the sphere are encompassed by a virtual bounding box. The cube is intersecting the bounding box of the sphere. Text at the bottom reads: Drag the cube around. Press Esc to toggle B-Boxes.](/en-US/docs/Games/Techniques/3D_collision_detection/Bounding_volume_collision_detection_with_THREE.js/screen_shot_2015-10-19_at_12.10.06.png)