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

Normals: Tangent space to world space transforms errors #381

Closed
TiernoGs opened this issue Sep 1, 2023 · 4 comments
Closed

Normals: Tangent space to world space transforms errors #381

TiernoGs opened this issue Sep 1, 2023 · 4 comments

Comments

@TiernoGs
Copy link

TiernoGs commented Sep 1, 2023

Hello @mmp,

I recently stumbled accross a bug when using normal maps.
Apparently, when using instances (or even different objects) that share the same uvs, normals applied through a normal map follows the active rotation of the object. This shouldn't be the case as source direction is unique for infinite lights.

Here is the scene that gives me an error: scene.zip
Command: pbrt.exe scene.pbrt --spp 4 --log-level verbose --seed 0 --nthreads 8 --disableWavelengthJitter

The pbrt render:

render

And the expected result when using Blender Cycles:

blender

In my opinion, it doesn't come from the reading of the normal map texture but either from the transform in the surface intersection shading geometry setup or the tangent to world space transformation.

Maybe this is also related to the issue with normals on gpu #377 ?

Thanks

@mmp
Copy link
Owner

mmp commented Sep 5, 2023

Very interesting. Thanks for reporting this!

The underlying issue comes from pbrt being a little weird in how it handles shading normals: it wants to have surface partial derivatives that, when you take their cross product, you get the desired shading normal. Then the way it handles normal maps is a bit unusual as well: by the time the normal map is evaluated, we no longer have access to the full object space->rendering space transformation, which would be nice to have around to bring the normal map's object-space normal into rendering space...

For this case, the problem comes from this line in src/pbrt/materials.h:

Frame frame = Frame::FromZ(ctx.shading.n);

It constructs a coordinate frame about the pre-normal mapped shading normal and then calls Frame::FromLocal() to bring the normal mapped shading normal out of the tangent space coordinate system (with the normal aligned with (0,0,1)) into rendering space. The problem is that FromZ chooses arbitrary basis vectors for x and y, while we'd like at least x to be aligned with (1,0,0) in tangent space.

Sooooo..... Replacing that line with:

    Frame frame = Frame::FromXZ(Normalize(ctx.shading.dpdu), Vector3f(ctx.shading.n));

gives this image:

image

which is at least consistent regardless of the rotations, though it doesn't match blender.

I'm not sure what the discrepancy is (pbrt being left handed and blender right-handed?) and would like to figure that out, but will at least check in that fix after testing it with more scenes.

@pbrt4bounty
Copy link
Contributor

I can tested on Blender since I have a full operative plugin. BTW.. in Blender, Z is up

@TiernoGs
Copy link
Author

Hello, thank you for your reply, the updated line works just fine now :)
No need to look deeper into the light orientation, the blender cycles render was a way to highlight the normal map bug.
I'm closing the issue, thanks !

@mmp mmp reopened this Sep 17, 2023
@mmp mmp closed this as completed in 83e4599 Sep 17, 2023
@mmp
Copy link
Owner

mmp commented Sep 17, 2023

Interestingly, this fixes a number of errors in other scenes that use normal mapping; compare the curb, bistro glass doors, and menu to the left of the doors.

old
new

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

No branches or pull requests

3 participants