5
votes

I'm using the normal shader in three.js r.58, which I understand requires a normal map. However, I'm using a dynamic displacement map, so a pre-computed normal map won't work in this situation.

All the examples I've found of lit displacement maps either use flat shading or pre-computed normal maps. Is it possible to calculate the normals dynamically based on the displaced vertices instead?

Edit: I've posted a demo of a sphere with a displacement map showing flat normals:

Sphere with displacement but incorrect normals

Here's a link to the github repo with all of my examples illustrating this problem, and the solutions I eventually found: https://github.com/meetar/three.js-normal-map-0

3
Normal maps in three.js are in tangent space, not object space. There should be no problem using a displacement map and a normal map simultaneously.WestLangley
I don't want to use a pre-computed normal map. How can I compute the normals automatically, based on the vertices after the displacement map is applied?meetar
The normal map is for adding detail. It sounds like you what you mean is you want to change the vertex normals. This has nothing to do with a tangent-space normal map.WestLangley
Okay, in that case: how can I update the vertex normals based on the displaced vertices?meetar
Your original vertex normals should be good enough, unless you have severe distortion. Besides, your original vertex normals are likely smooth (to give you smooth shading). What would be your algorithm for generating new smooth vertex normals?WestLangley

3 Answers

4
votes

This answer is based on your comments above.

You can do what you want, but it is quite sophisticated, and you will of course have to modify the three.js 'normal' shader.

Have a look at http://alteredqualia.com/three/examples/webgl_cubes_indexed.html. Look at the fragment shader, and you will see

vec3 normal = normalize( cross( dFdx( vViewPosition ), dFdy( vViewPosition ) ) );

Alteredqualia is using a derivative normal in the fragment shader ( instead of an attribute normal ) because the vertex positions are changing in the vertex shader, and the normal is not known.

What he is doing is calculating the normal using the cross product of the x and y screen-space derivatives of the fragment position.

This will set the normal as the face normal. It will be discontinuous at hard edges.

three.js r.58

3
votes

What I was describing above is called a "bump map" and it comes as a default with the three.js phong shader. I combined the normalmap shader with chunks of the phong shader responsible for bump mapping:

http://meetar.github.io/three.js-normal-map-0/bump.html

Though the normals are a bit noisy they are basically correct.

sphere with displacement and bump mapping

2
votes

You can also calculate a normal map from the displacement map with JavaScript. This results in smooth normals, and is a good option if your displacement map isn't changing too often.

This method uses the code found in this demo: http://mrdoob.com/lab/javascript/height2normal/

Demo here: http://meetar.github.io/three.js-normal-map-0/index14.html

enter image description here