Sunday, July 29, 2012

Lights and Materials in Three.js

‹prev | My Chain | next›

Up today I am going to play around a bit with Three.js lighting and material. I have my avatar island pretty much as far as I am going to take it. Before switching back to Gladius, however, I would like to take a quick look at something that Gladius does well: materials.

For the most part during my Three.js experiment, I have been using MeshNormalMaterial:
var material = new THREE.MeshNormalMaterial();

// The head
var head_shape = new THREE.SphereGeometry(75);
var head = new THREE.Mesh(head_shape, material);
head.position.y = (100 + 35) * .8;

// The body
var body_shape = new THREE.CylinderGeometry(1, 100, 100);
var body = new THREE.Mesh(body_shape, material);
The normal material produces a flat, colorful surface on the mesh, even without any lighting:

The normals, the faces pointing out, are given a nice coloring to make them distinctive from each other. It works well especially when first getting started.

I have also been making extensive use of MeshBasicMaterial:
var material = new THREE.MeshBasicMaterial({
  color: 0x0000bb
This produces:

Again, I do not have any external lighting. This material has its own intrinsic color emanating from it. It is a bit unrealistic in that sense, but it works well for islands, skyboxes and other scenery.

But, if I add a simple light to the scene:
var light = new THREE.PointLight();
light.position.set(50, 150, 150);
I still get the same look:

According to the PointLight documentation, this is to be expected. The PointLight has an effect with the MeshPhongMaterial (named for Phong Shading) and MeshLambertShading (see Lambert Reflectance).

Leaving the PointLight in place, I change the material to MeshPhongMaterial:
var material = new THREE.MeshPhongMaterial({
  color: 0x0000bb
This results in a more satisfactory 3D illumination:

Switching to MeshLambertMaterial:
var material = new THREE.MeshLambertMaterial({
  color: 0x0000bb

Produces a slightly duller (more matte) version:

For now, I am going to stick with the Phong material, but up the shininess to 50 (the default is 30):
var material = new THREE.MeshPhongMaterial({
  color: 0x0000bb,
  shininess: 50
Then I try a series of lights at 10 intensity:
var light = new THREE.PointLight(0xffffff, 10);
light.position.set(50, 150, 150);
The point light results in:

Next, a directional light:
var directionalLight = new THREE.DirectionalLight(0xffffff, 10);
directionalLight.position.set(50, 150, 150); = head;
scene.add( directionalLight );
Which results in:

The spotlight is defined as:
var spotLight = new THREE.SpotLight( 0xffffff, 10);
spotLight.position.set( 50, 150, 150 );
scene.add( spotLight );
And looks like:

That is a pretty hectic introduction to all of this stuff, but I have a better grasp then when I started. There is also a pretty excellent example app demonstrating the differences between different materials with a flying light source.

Day #462


  1. I was having great problems trying to get lights to have any effect with materials, and this tutorial expalined that I needed the Phong or Lambert materials. Thankyou for that.

  2. Thank you for clarifying lights and materials!