4
$\begingroup$

You can get a UV map based Tangent using the Tangent node set on UV Map, or by using the Attribute Node with the attribute 'tangent' entered (you'll get the tangent of the active UV map.) If I understand correctly, this is a tangent based on the mesh normals and a UV map. I want to get a tangent of a custom normal and a UV map, such as if you used an Object or World space normal map texture.

How are these UV tangents calculated? Can this be re-created with nodes, or is it precomputed? I can't find any data block for it.

I have looked in the source code for the Eevee tangent node and also Cycles OSL tangent node. The Eevee version just seems to be calling the tangent attribute, so whatever calculation is being done is somewhere else and I can't find it.

The Cycles OSL node is a bit harder to puzzle out. It takes an attribute named geom:tangent as its default input, but returns nothing when set to 'uv_map' direction type unless you enter an actual UV map name instead of geom:tangent. Then it works and produces something that looks like a radial tangent, but is not the same as what the Tangent node is giving. You can re-create the math from the OSL code as nodes and get the same result. Here's a GIF showing each:

enter image description here

What else is going on here? What am I missing?

$\endgroup$
2
  • $\begingroup$ Interesting Q. I'm trying to understand the problem here, forgive me... :) If the mesh has a Custom Split Normals data layer, the 'Normal' output of Geometry (WSpace) and Texture Coordinate (OSpace) nodes reflect that, and so does the UV-Map-based Tangent node? $\endgroup$
    – Robin Betts
    Dec 18, 2021 at 11:29
  • 1
    $\begingroup$ @RobinBetts Yes, but not for Object/World Normals from a texture or generated procedurally. $\endgroup$
    – Ascalon
    Dec 18, 2021 at 18:57

1 Answer 1

5
$\begingroup$

A UV tangent can't be created with nodes* other than with a tangent node, or techniques to reverse engineer the tangent from a node that uses it implicitly, like a normal map node sent a 1.0, 0.5, 0.5 color. A radial tangent can be computed with nodes, but it is a per-sample radial tangent, while a radial tangent node gives per-vertex radial tangents. A radial tangent is simply the cross-product of the surface normal and a unit-length, object-space vector.

I'm not sure how UV tangents are calculated in raytracers like Cycles. In rasterizers like Eevee, they are calculated via screen space derivatives: the UV of a fragment immediately above/below and immediately to the right/left is compared, and a vector is created on that basis of the change in UV. GPUs compute 2x2 blocks of samples, and said blocks of samples always exist on the same face, so this is simple to do with shader programming, but unfortunately Blender doesn't expose screen space derivatives to nodes.

*edit: at least, not out of out-of-the-box nodes. I don't know whether OSL has tools that would allow this or not.

$\endgroup$
1
  • $\begingroup$ Hmm, that's what I figured. It looks like the root of Eevee's Tangent is using dFdx and dFdy on the UVs themselves, which is the 2x2 samples you refer to. You can do this with OSL with the dX and dY commands. $\endgroup$
    – Ascalon
    Dec 18, 2021 at 8:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .