Closed TiernoGs closed 11 months ago
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
: https://github.com/mmp/pbrt-v4/blob/425faa0843d9f3518a7564b434cb340ad85bda41/src/pbrt/materials.h#L98
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:
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.
I can tested on Blender since I have a full operative plugin. BTW.. in Blender, Z is up
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 !
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.
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:
And the expected result when using Blender Cycles:
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