mrdoob/three.js — Issue #1075: normalizing the normal matrix for large scale objects?
Author: avinoamr
Created: 2012-01-11 18:37:31+00:00
State: open

I'm trying to implement very large-scale terrain on the GPU following Harald Vistnes paper in Game Programming Gems #6: GPU Terrain Rendering. You can see it here:

http://www.imperfect-creation.com/terrain_gpu_example/

As you can see, the shading is off even though it's using standard Blinn-Phong per-pixel shading using `THREE.ShaderLibs`. I've narrowed down the problem to this GLSL line:

https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLShaders.js#L1372

Specifically, the normal vector is extracted from a normal map, and is then transformed by the normal matrix which (almost) flattens the normal values to ~0, ~0, ~0. My suspicion is that because I'm using very large scale (`terrain.scale.set( 100000, 100000, 1000 )`) , the normal matrix has extremely low numbers which are then malformed by precision problems on the GPU.

To test this theory, I tried normalizing the normalMatrix uniform before setting it and the problem was solved. In the example above, just activate the 'fixShading' check box to see it works.

You can see my updated normalization code here:
https://github.com/avinoamr/three.js/commit/06c53bc9ea6d6f7d966170aa29c0673fa09deae8

What's your take on this? Am I missing something? I've done some research into the math of it, and couldn't find any reference that suggested normalizing the normalMatrix so I assume that I'm misusing it some how. I realize that such large-scale isn't ideal (although 100,000 isn't such a huge number), and I can easily work around it with an elegant solution, but I'm still interested in understanding this problem.