In the first article of this series I introduced the very basics of threeJS, including setting up a camera and integrating a WebGL scene with web page content. In this entry we’ll position that camera in 3D space, point it at an object, and light it. Before doing any of that, we have to understand the nature of that 3D space:
Navigating Space
You’re probably familiar with the x
and y
graph from school: x
goes horizontally, y
vertically. With units on each axis, you can plot the position of any element in positive 2D space. To include negative positions, we must extend the axes to the left and down:
The intersection of these axes is 0 0
, known as the origin.
To plot positions in 3D space we must add a third axis, perpendicular to the first two, going “towards” and away from the viewer. With a slight tilt, we can visualize this z
axis too:
Note that the positive wing of the z
axis is away from us, and the negative wing is closest.
Now the position of any point in space can be plotted as the intersection of three values: x
, y
, and z
:
The camera
we created in the previous article is located at the scene origin by default. We want to position the camera away from the center:
camera.position.set(1380, 0, 0);
The scene
contains the world we are about to create, which will include every object and element, and is created in the next line of our code:
scene = new THREE.Scene();
The scene is automatically located at 0, 0, 0
, and it is also where our central object - the planet Mars - will be placed. We want the camera to look at the same point:
camera.lookAt(scene.position);
Let There Be Light
Right now our scene is an infinite, inky blackness: any object placed within it would be invisible, since there is no source of light. Let’s change that:
light = new THREE.PointLight(0xFFFFFF, 2, 5000);
light.position.set(2000, 2000, 1500);
scene.add(light);
threeJS currently supports six different kinds of lights:
- PointLight
A light with a position, that radiates light evenly in all directions. This makes point lights perfect for simulating the light coming from a star, or a lightbulb.
- DirectionalLight
A light with a direction, but no “beam” (unlike a spotlight, below). Useful for sunlight as seen from the surface of Earth.
- SpotLight
A light that points in a particular direction, with a broad “beam”. Think of a theatrical spotlight cast onto a stage.
- RectAreaLight
A light that projects from a rectangular plane: useful for simulating light cast through a window, or from a florescent panel.
- AmbientLight
A “general” light that comes from all directions: think of the light still visible on a moonless night, for example. It has the effect of filling the scene with a color cast: the brighter the ambient light, the more “washed out” a scene will appear.
- HemisphereLight
Sometimes called a “skylight” in 3D applications. Simulates light coming from above (the sky) and below (any reflection or light from the ground). Perhaps best thought of as ambient light divided into two halves.
I will be exploring each of these light in depth in future articles; for now, let’s focus on the point light. It takes three arguments: the color (a hex value, preceded by 0x
), an intensity, and the point at which the light begins to fall off.
You’ll find it easiest to experiment with he intensity value yourself, to see its effects: you’ll find that too high an intensity “blows out” the color in your scene, like using a too-strong flash held too close to your subject in a photograph.
Without Form and Void
It seems a pity to make it all this way without anything to see. I’ll rush through a simplified version of the remaining code to change that. The complete JavaScript code to this point, aside from bringing in the threeJS library:
let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000),
light = new THREE.PointLight(0xFFFFFF, 2, 5000),
scene = new THREE.Scene();
light.position.set(2000, 2000, 1500);
camera.position.set(1500, 0, 0);
camera.lookAt(scene.position);
scene.add(light);
let marsGeo = new THREE.SphereGeometry (500, 32, 32),
marsMaterial = new THREE.MeshPhongMaterial( { color: 0xff6600 } ),
marsMesh = new THREE.Mesh(marsGeo, marsMaterial);
scene.add(marsMesh);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight)
marsloc.appendChild(renderer.domElement);
renderer.render(scene, camera);
Placed on your webpage together with the code above and that shared in part 1, this should provide the result you see at the top of this article. Obviously, there’s a lot more to add - and this code needs to be explained - which I shall do in part 3.
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/bgKRov