World -> Tangent transform

Is there any way to convert a unit length world-space vector to tangent-space inside a shader? I ask because we need a tangent-space up vector for some bump mapped shader effects, because using Unity’s system for converting normal maps to world-space is causing us to run out of shader inputs.

Thanks for any help you can provide.

If it’s inside of the vertex shader, it should be ok.

Otherwise I think it’ll end up being just as expensive as tangent to world requirements (possibly a little cheaper on interpolators as you only need one, but then you’re doing all the rotation per-pixel rather than per-vertex).

Using Unity’s macro;

float3 objUp = mul((float3x3)_World2Object, float3(0,1,0)); // Convert world up to object up so it can be converted to tangent up.
TANGENT_SPACE_ROTATION;
float3 tangentUp = mul(rotation, objUp);

Without Unity’s macro;

float3 objUp = mul((float3x3)_World2Object, float3(0,1,0)); // Convert world up to object up so it can be converted to tangent up.
float3 binormal = cross( v.normal, v.tangent.xyz ) * v.tangent.w;
float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal );
float3 tangentUp = mul(rotation, objUp);

You don’t need to do a matrix multiply. The world’s Y vector in object space is built into _World2Object: _World2Object[1].xyz.

http://aras-p.info/texts/matrices.html

Also, note that normals and tangents aren’t kept normalized when building for mobile devices (and maybe Ouya?), for skinned meshes, so you’d need to do that manually if that’s something you need to support.

Oh, yeah, good call on the world up.

I thought the normals were normalized. You have to tell it not to, using;
#pragma glsl_no_auto_normalization

Right, right. If you write in Cg, the auto-generated GLSL will contain normalize instructions that you didn’t explicitly write out. If you write in GLSL, then you have to do it yourself.

Aah, gotcha. Sorry, I converted all my mobile stuff to explicit GLSL a while back. I’m getting confused between converted and non-converted :slight_smile:

(Gods know how the Unity devs keep track of it all.)

Thanks for the tips, they have been most enlightening. :slight_smile:

Sadly, I found out that they can’t fix my underlying problem, since I realized I specifically need world space for parts of my shaders. Then I found out the ones that I thought I could get away with it (ie. terrain shaders) have so many TEXCOORDs bound for texture coordinates that they aren’t enough for the rest of my requirements. :frowning: