Is it possible to compute tangents in shader?

I was able to implement a tri planar shader like in this tutorial:

It basically automatically UV maps textures onto a mesh using the world coordinates and normals instead of mesh UV’s. This is great for arbitrary organic meshes like caves that would be a nightmare to have seamlessly align if you were doing uv’s manually.

However, there are issues with normal mapping seams at edges of meshes. I had to do some minimal UV unwrapping so that good tangents and binormals would get generated for my meshes, or else the normal maps looked like a giant polygonal mess of seams. Now it looks great, but I can still see normal map seams at mesh edges.

This is because the tangents don’t flow in the same direction between mesh edges in the world. In one mesh, my tangents might be flowing top to bottom, and in another mesh, left to right, and this results in the normal map seams. If I disable normal mapping, there are no seams since the base color textures align perfectly.

I was hoping to not rely on mesh tangents and compute the tangents in the shader somehow using world space positions and normals somehow, just like I am with the uv’s.

Thing is I don’t even see a way to override what tangents are fed into the normal mapping inside the material editor.

This is possible with some math. This is an HLSL implementation, you’ll have to convert to nodes. Note that TangentX and Y are not continuous (as you move WorldNormal around smoothly, they will pop at certain transition points).

void FindBestAxisVectors2(float3 InZAxis, out float3 OutXAxis, out float3 OutYAxis )
float3 UpVector = abs(InZAxis.z) < 0.999 ? float3(0,0,1) : float3(1,0,0);
OutXAxis = normalize( cross( UpVector, InZAxis ) );
OutYAxis = cross( InZAxis, OutXAxis );

Used like so, where you already know WorldNormal

float3 TangentX;
float3 TangentY;
FindBestAxisVectors2(WorldNormal, TangentX, TangentY);

I think a similar function (‘FindBestAxisVectors’) is also implemented in Random.usf which means you should be able to directly call it in a custom node in the material editor.

It’s different after all so you should really go with the code above.

The link you provided says it’s taking me to an invalid attachment.

So I can try looking into those solutions, but I’m still wondering how to make the normal mapping take into account custom tangents. I don’t see any way to feed that into the material when I’m providing a normal map. As far as I can tell, if I use a normal map, it just automatically uses mesh tangents.

I found this article:

Lots of crazy math, but at last there is GLSL code at the bottom. I wonder how well this will work for what I need?