简体   繁体   中英

Why is Shader Graph Transform node affected by UV mapping?

I've had an issue with normal maps not behaving correctly in my custom shader and finally managed to find the cause. It turns out it was the way UV of my objects were mapped. In UV0 I stored a mapping to a color palette texture - the UVs were all scrambled together as the only thing that mattered was that they are on a pixel with the correct color. In UV1 I stored the traditional UV uwrap, which I used to apply the normal map. To get the normal map I used a set-up like this: 普通的

I'm doing my own light calculations so I need to transform the normal from tangent space to world space before using it.

This approach was causing two issues - weird artifacts and the normals being "stuck" to the object: 人工制品

The sphere on the right is upside down and if you look at the normals they are also upside down. The artifacts are on both spheres, but they are visible on the right one from this perspective.

What seems to be the cause is the way I used UV0 to map the object to a color palette. It somehow affects the tangent to world space transformation done by the Transform node (I know it's this node because removing it makes the artifacts disappear). Also, swapping the UV channels so that the traditional unwrap is in UV0 and the palette mapping is in UV1 fixes the issue:

正确的

There are no artifacts and the normals aren't stuck to the object.

So why is the transform node affected by UV mapping? I thought it does the transformation based on the geometry of the object. And if it uses UV maps, why is there no dropdown to select which UV it's going to use?

The tangent space (aka texture space ) is partially defined by the geometry (the normal) but also by the uv coordinates (the tangent).

Just as the normal is derived from the vertex position, the tangent is inferred from the UVs. It's essentially an object space vector (xyz) that points to the U axis (horizontally in your UV space) and is perpendicular to the normal.

The normal map is a vector in texture space, and the channels of the bitmap can be seen as the offsets from the vertex defined tangent space for each of its vectors.

half3 TangentToObjectSpace(half3 input, half3 nml, half3 tgt, half3 btg) {
    return tgt * input.x + btg * input.y + nml * input.z;
}

As you can see the input.x (normal map red channel, which defines the horizontal part of the vector) is modulating the tangent. We need another vector for the green channel, which we can generate using a cross product : provided the two existing vectors you get a new one perpendicular to both. The catch: for flipped UV shells this generated vector is pointing in the wrong direction. In Unity tangents are actually vector4, and the last component (w) is the flip of the binormal .

Unity uses the tangent space of the first UV coordinate by default, which is why you fixed your issue by swapping them:)

It's very, very likely that the Transform node is dependent on the UV selection insofar it depends on the output of the Texture Sample node. So it`s probably a subtle difference of the output in the sample node that makes the transform node behave this way, and not some hidden UV setting on the transform node.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM