MHebes
MHebes

Reputation: 3197

Three.js displacementMap does not affect lighting, only vertices

I'm using Three.js to apply a displacement map to a simple plane. The displacement applies successfully, but the lighting is wrong, as if all the normals remain unchanged. The result is a surface with the right shape that's lit as if it were flat.

displacement map:

displacement map

result:

plane with displacement map, but bad normals

How can I fix this to properly change the lighting?

Here is the relevant bit of code:

// shortened from actual code - please excuse any small typos

var renderer = new THREE.WebGLRenderer();
renderer.setSize(500, 250);

var scene = new THREE.Scene();

var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(100, 100, 100);

var ambient = new THREE.AmbientLight(0xffffff, 0.2);

scene.add(light);
scene.add(ambient);

var camera = new THREE.PerspectiveCamera(60, 2, 1, 20000);

var geometry = new THREE.PlaneBufferGeometry(100, 100, 1000, 1000);
geometry.rotateX(-Math.PI / 2);

var material = new THREE.MeshPhongMaterial();

var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load('circlemap.png');

material.displacementScale = 20;
material.displacementMap = texture;

var mesh = new THREE.Mesh(geometry, material);

scene.add(mesh);

// ... later
renderer.render(scene, camera)

edit: when I set flatShading: true in the material, the normals are updated correctly, but look bad (because of the flat shading):

displacement map working properly with flat shading

Upvotes: 3

Views: 839

Answers (1)

M -
M -

Reputation: 28462

You're going to have to pass a normalMap along with your displacementMap.

See this demo, when normalScale = 0 it's the equivalent of having no normalMap, and you can see that the reflections don't follow the displacement, only the default topography. However, when normalMap is 1, then the reflections do respect the displacement.

You need to generate a normalMap.

Upvotes: 4

Related Questions