Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normal maps don't play nice #10

Closed
emackey opened this issue May 8, 2017 · 8 comments
Closed

Normal maps don't play nice #10

emackey opened this issue May 8, 2017 · 8 comments
Labels

Comments

@emackey
Copy link

emackey commented May 8, 2017

I have a test model called Normal-Tangent Test, where I try rotating the UVs of a normal map around. The reflected vectors are not supposed to be swayed by such shenanigans.

In particular, the light source is not supposed to "spin around", and in this screenshot I'm using the "Bridge" environment and you can clearly see the bridge spinning around.

threejs_normaltangent_notright

Here's sbtron's viewer with correct reflections.

And here are some notes I made when creating this model showing it working correctly in ThreeJS.

@emackey
Copy link
Author

emackey commented May 8, 2017

(And, off-topic, but once this issue is resolved, you may wonder to yourself what's the most ridiculously expensive PBR textures that have ever been placed on a COLLADA duck? Well probably you weren't going to ever wonder that but in case you did I have it covered.)

@donmccurdy donmccurdy added the bug label May 9, 2017
@donmccurdy
Copy link
Owner

donmccurdy commented May 10, 2017

@emackey Thanks for filing this! I'm having a difficult time understanding why it would behave differently here than with the OBJ example. It doesn't seem like any parameters we pass to MeshStandardMaterial should have an effect like this.. For the OBJ demo you have working with three.js, is the glTF file generated from that OBJ? They seem to have different numbers of vertices, anyway. Or perhaps GLTF2Loader is parsing the UVs differently than OBJLoader.

And, the COLLADA duck models are wonderful 😁

@donmccurdy
Copy link
Owner

/cc @takahirox

@emackey
Copy link
Author

emackey commented May 10, 2017

The GLTF came through a work-in-progress update to the COLLADA converter. I haven't dug into the details of what's different between it and the OBJ yet, I'll try to carve out some time for that. The OBJ and the COLLADA came from their respective export plugins in Blender, which may have differences. Also I should try loading the COLLADA into ThreeJS as well, to see what that does.

Still, this glTF model shows the correct reflections in the BabylonJS viewer, so this issue represents a difference in glTF 2.0 behavior between the two engines for the same model.

@emackey emackey mentioned this issue May 10, 2017
2 tasks
@emackey
Copy link
Author

emackey commented May 10, 2017

I became suspicious that the normal map problems are the result of mis-interpreting the green channel, as described here: KhronosGroup/glTF#952

However, when I tried this with a "DirectX" normal map (as described in that issue), I got a consistent result, but a consistently 180-degree wrong result. Strange. Still I think we should wait for more input on the Khronos issue before we proceed here. (See below)

nowwithdirectxnormals

@emackey
Copy link
Author

emackey commented May 11, 2017

It's been confirmed that the OpenGL (right-handed, +Y up) form of the normal map texture is the form that should officially be used. This means the BabylonJS viewer is doing it correctly, and there may be an issue with the ThreeJS glTF loader.

@donmccurdy
Copy link
Owner

Great, thanks for looking into this. We can fix the loader for this model trivially, by adding:

materialParams.normalScale = new THREE.Vector2(-1, 1);

Result:
screen shot 2017-05-10 at 10 23 45 pm

... but I'm a bit confused by this. We do not otherwise touch the normalScale property. I don't know three.js's default (it doesn't seem to be documented). On the other hand, the BabylonJS default is documented and matches neither DirectX nor OpenGL:

BabylonJS: x-axis = left, y-axis = down
OpenGL: x-axis = right, y-axis = up
DirectX: x-axis = right, y-axis = down

So if flipping x gives the right result for a model assumed to have OpenGL normals, that implies the three.js default to be x=left,y=up, which would be surprising.. I will try to check on the three.js default.

@donmccurdy
Copy link
Owner

Fixed: mrdoob/three.js#11825

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants