The lines that start with angled brackets (less-than symbols) form a minimal HTML document. The HTML lines, except for the script tags, are reproduced below. Not much is going on beyond the creation of a canvas that we will render to later.
This line includes the three.js library, which will handle most of the low-level WebGL rendering details for us.
The next script tag starts a large block of code that is the actual example. The code consists largely of a single function definition.
function init() {
// code omitted
}
window.onload = init;
window.onresize = init;
The two lines at the bottom tell the browser to execute init()
after the window has finished loading, and every time the window is resized. Restarting the code every time the window is resized is not very elegant. It is certainly possible (with more code) to handle a resize sensibly without restarting.
The first line of the function shows how to ask the browser for an HTML element, in this case the canvas.
var canv = document.getElementsByTagName("canvas")[0];
var w = canv.clientWidth;
var h = canv.clientHeight;
This function requests elements "by tag name", i.e. by their standard HTML element types. The function returns an array since there might be any number of canvases on one page. The [0]
at the end just takes the first element of the array. Since we know there is only one canvas, the first one must be the right one. The width and height of the canvas are then extracted for later use.
renderer = new THREE.WebGLRenderer({canvas:canv});
renderer.setSize( w, h );
renderer.setClearColor(new THREE.Color(0xeeeeee), 1);
We now create a Three.js renderer and set it to fit on our canvas. The background color is coded as a six digit hexadecimal number where the first two digits specify the amount of red in the color, the next two the amount of green, and the final two the amount of blue. 0xeeeeee is a very light gray color.
var scene = new THREE.Scene();
A scene is then created. The scene is the root of the Three.js scenegraph.
var camera = new THREE.PerspectiveCamera(
15, // Field of view
w / h, // Aspect ratio
0.1, // Near
10000 // Far
);
camera.position.set( 5, 5, 100 );
Now a camera is created. Several parameters are provided, specifically field of view (wide or narrow), the aspect ratio (how wide the image will be in relation to its height), and also the near and far clipping plane (vertices too close or too far will not be rendered). The position is set to coordinates known by the author (me) to have a view of the scene to be shown.
var control = new THREE.OrbitControls(camera,canv);
The orbit controller moves the camera in response to user mouse actions. Try out all three mouse buttons to get a feeling for how it works.
var cube = new THREE.Mesh(
new THREE.CubeGeometry( 5, 5, 5 ),
new THREE.MeshLambertMaterial( { color: 0xFF0000 } )
);
scene.add( cube );
Next a simple cube (a Three mesh object) is constructed. Note that the constructor for the mesh requires geometry and material objects as arguments. The geometry objects specifies the vertices of the object. The three arguments represent the dimensions of the cube. The material provides all necessary data to render the color of the object. In this case, our material is bright red.
var light = new THREE.PointLight( 0xFFFFFF );
light.position.set( 10, 0, 10 );
scene.add( light );
A point light will provide directional light originating from its position. Since no ambient light is added, we should expect surfaces not directly illuminated by the point light to be pitch black.
var clock = new THREE.Clock();
The clock is a simple object that uses the native JavaScript calls to read the system clock, but converts the results to seconds.
var render = function() {
var dt = clock.getDelta();
control.update(dt);
renderer.render(scene,camera);
requestAnimationFrame(render);
};
requestAnimationFrame(render);
Finally, a function that actually does the rendering is defined. clock.getDelta()
returns the number of seconds since the last call of this function. It should be called only once per render pass and the result used to update the positions of all moving objects (if any) in consistent with this elapsed time. In our case, only the camera is (possibly) moving, so dt
is passed to the camera motion control."requestAnimationFrame" function tells the browser to call the render function as soon as it has the opportunity consistent with all other tasks the browser is doing for you.