2

I have a very simple example: a spot light pointed at a plane. I am expecting to see a cone of light whose diameter depends on the setting of the spot light angle. I cannot see any cone, the whole plane is illuminated, even for very narrow settings of angle.

Here is my jfiddle: http://jsfiddle.net/blwoodley/WLtL4/1/

I'd love to know the source code that produced this picture from https://github.com/mrdoob/three.js/pull/3291 by West Langley. It obviously is working fine in that case.

So I must be doing something obviously wrong, but I can't figure it out.

Some of the code from the jfiddle, it doesn't get much simpler than this:

function init() {

container = document.createElement('div');
document.body.appendChild(container);

camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 100000);
camera.position.x = 100;
camera.position.y = 100;
camera.position.z = 200;
camera.lookAt({x: 0,y: 0,z: 0});

scene = new THREE.Scene();

var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var floorMaterial = new THREE.MeshLambertMaterial({ color: 0x222222, side:THREE.DoubleSide  });
floor = new THREE.Mesh(new THREE.PlaneGeometry(2000,2000,10,10), floorMaterial);
floor.rotation.x = Math.PI / 2;
floor.position.y = -40;
scene.add(floor);

var light;
light = new THREE.SpotLight(0x008888);
light.position.set(0, 40, 0);
light.lookAt(floor);
light.angle = Math.PI/4;
light.intensity = 30;
light.distance=0;
scene.add(light);

// RENDERER
webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = "relative";

container.appendChild(webglRenderer.domElement);
window.addEventListener('resize', onWindowResize, false);

}

Bob Woodley
  • 1,246
  • 15
  • 30

2 Answers2

1

This is subtle.

You are using MeshLambertMaterial for the plane. You need to change it to MeshPhongMaterial, so the lighting is rendered properly.

As explained here, for MeshLambertMaterial, the illumination calculation is performed only at each vertex.

For MeshPhongMaterial, the illumination calculation is performed at each texel.

So make these changes

floorGeometry = new THREE.PlaneGeometry( 1000, 1000 ); // no need to tessellate it now

var floorMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff } ); // 0x222222 is too dark

light.intensity = 1; // a reasonable value

Updated fiddle: http://jsfiddle.net/WLtL4/5/

three.js r.63

Community
  • 1
  • 1
WestLangley
  • 102,557
  • 10
  • 276
  • 276
  • Thank you so much. Just a few minutes ago, I discovered that changing the arguments to PlaneGeometry to (1000,1000,100,100) made the LambertMaterial responsive to the SpotLight angle, which makes sense given your explanation. But yes, the Phong material gives an even better result. – Bob Woodley Dec 10 '13 at 04:22
0

Also try to disable target for testing. I'm getting really weird behavior from it. Sometimes it makes it not render the light at all, no idea why yet. I'll make a demo of the problem later.

Eskel
  • 795
  • 1
  • 8
  • 21