Normal texture shader

We are currently trying to export our scene to the USD format.
For normal textures, if we already have a tangent-space normal map with values in the 0,1 range, why do we need to remap it to the -1,1 range? What is the purpose of this transformation? I came across the following documentation mentioning this step, but it doesn’t really explain the reasoning behind it.

“Expects normal in tangent space [(-1,-1,-1), (1,1,1)]. This means your texture
reader implementation should provide data to this node that is properly scaled
and ready to be consumed as a tangent space normal.
If the texture has 8 bits per component, then scale and bias must be adjusted
to be (2.0, 2.0, 2.0, 1.0) and (-1, -1, -1, 0) respectively in order to
satisfy tangent space requirements. Normal map data is commonly expected to be
linearly encoded. However, many image-writing tools automatically set the
profile of three-channel, 8-bit images to SRGB. To prevent an unwanted
transformation, the sourceColorSpace must also be set to “raw”.”

The constraint/expectation is specifically attached to the specification for UsdPreviewSurface, from which you are quoting. It’s not a declaration about “the cosmically right way to do normal mapping” :slight_smile: , it was the decision our graphics folks made to keep the PreviewSurface code simpler, pushing the transformation it would otherwise have to do itself out into the UsdUVTexture node/implementation, since we needed to provide a basic value scale/offset ability for that node anyways.

Thanks for the reply.

So, to have the correct rendering result, should I set these two factors in UsdShadeShader in general? I did some round-trip tests for importing the USD file into our system first, and then I exported the file by setting this transformation. It seems that I can get the correct result.

Yes, in fact I think there is a validator that usdchecker runs that flags a UsdUVTexture Shader prim/node that:

  1. Is connected to a UsdPreviewSurface’s inputs:normal input
  2. reads from an 8-bit texture (and therefore is almost certainly in the range 0..1)

And tells you you probably want the scale/bias on the node set to the appropriate values to compensate.

I see! Thanks for the reply.