Rendering and viewing a 3D object
In this step, you'll create your first scene and add a couple of objects and a camera. Our first example will contain the following objects:
Object |
Description |
---|---|
|
This is a two-dimensional rectangle that serves as our ground area. In the second screenshot of this chapter, this is rendered as the gray rectangle in the middle of the scene. |
|
This is a three-dimensional cube, which we'll render in red. |
|
This is a three-dimensional sphere, which we'll render in blue. |
|
The camera determines what you'll see in the output. |
|
These are the x, y, and z axes. This is a helpful debugging tool to see where the objects are rendered in 3D space. The x axis is colored red, the y axis is colored green, and the z axis is colored blue. |
I'll first show you how this looks in code (the source with comments can be found in chapter-01/02-first-scene.html
), and then I'll explain what's happening:
function init() { var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(45, window.innerWidth /window.innerHeight, 0.1, 1000); var renderer = new THREE.WebGLRenderer(); renderer.setClearColorHex(0xEEEEEE); renderer.setSize(window.innerWidth, window.innerHeight); var axes = new THREE.AxisHelper(20); scene.add(axes); var planeGeometry = new THREE.PlaneGeometry(60, 20, 1, 1); var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc}); var plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.rotation.x = -0.5 * Math.PI; plane.position.x = 15 plane.position.y = 0 plane.position.z = 0 scene.add(plane); var cubeGeometry = new THREE.BoxGeometry(4, 4, 4) var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true}); var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); cube.position.x = -4; cube.position.y = 3; cube.position.z = 0; scene.add(cube); var sphereGeometry = new THREE.SphereGeometry(4, 20, 20); var sphereMaterial = new THREE.MeshBasicMaterial({color: 0x7777ff, wireframe: true}); var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); sphere.position.x = 20; sphere.position.y = 4; sphere.position.z = 2; scene.add(sphere); camera.position.x = -30; camera.position.y = 40; camera.position.z = 30; camera.lookAt(scene.position); document.getElementById("WebGL-output") .appendChild(renderer.domElement); renderer.render(scene, camera); }; window.onload = init;
If we open this example in the browser, we see something that resembles what we're aiming at (see the screenshot at the beginning of this chapter), but it is still a long way off, as follows:
Before we start making this more beautiful, I'll first walk you through the code a step at a time so that you understand what the code does:
var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); var renderer = new THREE.WebGLRenderer(); renderer.setClearColorHex() renderer.setClearColor(new THREE.Color(0xEEEEEE)); renderer.setSize(window.innerWidth, window.innerHeight);
At the top of the example, we define scene
, camera
, and renderer
. The scene
object is a container that is used to store and keep track of all the objects we want to render and all the lights we want to use. Without a THREE.Scene
object, Three.js isn't able to render anything. More information on the THREE.Scene
object can be found in the next chapter. The sphere and the cube we want to render will be added to scene later on in the example. In this first fragment, we also create a camera
object. The camera
object defines what we'll see when we render a scene. In Chapter 2, Basic Components That Make Up a Three.js Scene, you learn more about the arguments you can pass in to the camera
object. Next we define renderer
. The renderer
object is responsible for calculating what the scene
object will look like in the browser based on the camera
object's angle. We create WebGLRenderer
that uses your graphics card to render the scene in this example.
Tip
If you look through the source code and the documentation of Three.js (which you can find at http://threejs.org/), you'll notice that there are different renderers available besides the WebGL-based one. There is a canvas-based renderer and even an SVG-based one. Even though they work and can render simple scenes, I wouldn't recommend using them. They're very CPU-intensive and lack features such as good material support and shadows.
Here, we set the background color of renderer
to almost white (new THREE.Color(0XEEEEEE)
) with the setClearColor
function and tell renderer
how large the scene needs to be rendered using the setSize
function.
So far, we've got a basic empty scene, a renderer, and a camera. There is, however, nothing yet to render. The following code adds the helper axes and the plane:
var axes = new THREE.AxisHelper( 20 ); scene.add(axes); var planeGeometry = new THREE.PlaneGeometry(60,20); var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc}); var plane = new THREE.Mesh(planeGeometry,planeMaterial); plane.rotation.x=-0.5*Math.PI; plane.position.x=15 plane.position.y=0 plane.position.z=0 scene.add(plane);
As you can see, we create an axes
object and use the scene.add
function to add these axes to our scene. Next, we create the plane. This is done in two steps. First, we define what the plane looks like using the new THREE.PlaneGeometry(60,20)
code. In this case, it has a width of 60
and a height of 20
. We also need to tell Three.js what this plane looks like (for example, its color and its transparency). In Three.js, we do this by creating a material object. For this first example, we'll create a basic material (THREE.MeshBasicMaterial
) with the color 0xcccccc
. Next, we combine these two into a Mesh
object with the name plane
. Before we add plane
to the scene, we need to put it in the correct position; we do this by first rotating it 90 degrees around the x axis, and next, we define its position in the scene using the position properties. If you're already interested in the details of this, look at the 06-mesh-properties.html
example from the code folder of Chapter 2, Basic Components That Make Up a Three.js Scene, which shows and explains rotation and positioning. We then need to do is add plane
to scene
, just like we did with axes
.
The cube
and sphere
objects are added in the same manner, but with the wireframe
property set to true
, which tells Three.js to render a wireframe and not a solid object. Now, let's move on to the final part of this example:
camera.position.x = -30; camera.position.y = 40; camera.position.z = 30; camera.lookAt(scene.position); document.getElementById("WebGL-output") .appendChild(renderer.domElement); renderer.render(scene, camera);
At this point, all the elements we want to render are added to the scene at the correct positions. I've already mentioned that the camera defines what will be rendered. In this piece of code, we position the camera using the x
, y
, and z
position attributes to hover above our scene. To make sure the camera is looking at our objects, we use the lookAt
function to point it at the center of our scene, which is located at position (0, 0, 0) by default. All that is left to do is append the output from the renderer to the <div>
element of our HTML skeleton. We use standard JavaScript to select the correct output element and append it to our div
element with the appendChild
function. Finally, we tell renderer
to render scene
using the camera
object provided.
In the next couple of sections, we'll make this scene more pretty by adding lights, shadows, more materials, and even animations.