Ethan McTague
Ethan McTague

Reputation: 2358

Model renders using MeshBasicMaterial but not MeshPhongMaterial

I am making a page with three.js. I have made this code, which works:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 7;

var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

var pointLight = new THREE.PointLight(0xFFFFFF);
pointLight.position.x = 20;
pointLight.position.y = 20;
pointLight.position.z = 20;

scene.add(pointLight);
var material = new THREE.MeshBasicMaterial( { color: 0xFFFFFF } );

var thebox, loader = new THREE.OBJLoader();
loader.load("https://dl.dropbox.com/s/kasjdw78lx3bkk0/weirdshape.obj?dl=0", function (obj) {
  obj.material = material;
  obj.traverse(function(child) { child.material = material; });
  scene.add(obj);
  thebox = obj;
  render();
});

function render() {
  thebox.rotation.y += 0.01;
  thebox.rotation.x += 0.01;
  thebox.rotation.z += 0.01;
  requestAnimationFrame( render );
    renderer.render( scene, camera );
}

This code does work, but when I try to change the MeshBasicMaterial to a MeshPhongMaterial, all I see is a black screen, even though my lighting seems to be in order. How can I fix this?

Upvotes: 2

Views: 380

Answers (1)

WestLangley
WestLangley

Reputation: 104763

Read your source .obj file. Your model has no vertex normals. MeshPhongMaterial requires normals.

You can have three.js compute some. In your loader callback function, add:

if ( child.geometry ) child.geometry.computeVertexNormals();

Note: Because the loader in this case returns BufferGeometry, this work-around is correct. If your loader returned Geometry, instead, then you may have to first call geometry.computeFaceNormals() if they do not exist either.

three.js r.73

Upvotes: 2

Related Questions