I know I’m late to the game, and there are really good answers already, but I figured I’d throw in my sense of Normal Maps as well.
There is no meaningful “origin” in Tangent-space. It is a Linear Transformation, not an Affine Transformation (An Affine Transformation includes translation). What Tangent-space does have is a “Basis”. A Basis is a set of 3 (orthogonal) vectors that you can use to take a vector from one space to another. It’s kind of like a rotation, especially when no scale is involved. It lets us map a vector in one space to a vector in another. This is roughly the same math that gets your characters animated, or gets your objects into the proper place in the world, and then onto the screen!
So what is our Basis in Tangent-space? You may have seen “TBN” in some shaders. The Basis is defined by the Tangent, Binormal (really, Bitangent, but the misnomer has gone so far, the distinction is pointless) and Normal of your mesh. So what defines Tangent and Binormal? It’s actually quite arbitrary. There can be an infinite number of othogonal vectors on the plane defined by the Normal. We have to pick two, and be consistent. The UV’s of a triangle give us a great definition, and for every face a Tangent can be defined. There is some fancy math to map these into the space the Normal is in, but the first image in this thread shows the result quite nicely. But that’s per face. Generally, much like Vertex Normals, we need smoothly varying Vertex Tangents across a mesh. So, just like how a vertex Normal is a weighted sum of the adjacent face normals, a vertex Tangent will be the weighted sum of the adjacent tangents, often with a post-pass done to make sure everything is still orthogonal. “Tangent-space” is then the smoothly interpolated TBN between all the vertices, and actually varies per sample point!
That’s great, but how does that relate to a Normal Map? In a Transformation, you take each component of the source vector, and multiply it against each vector in the Basis, and add those three vectors up to get your resultant vector. The Vertex Normal in Tangent-space is just the 0,0,1 vector transformed by the Basis. It is saying to use 100% of “N” 0Tangent + 0Binormal + 1*Normal (0T 0B 1N in shorthand, if you will). If you think about a flat Normal Map being solid blue, this makes a lot of sense. But why 128,128,255 Blue, not 0,0,255? Normal Maps are range-compressed because Normals can go from -1 to 1 in each channel, and a texture can only go from 0-1. That’s why when you unpack a normal map you Multiply by 2 then subtract 1. (Always in that order! Graphics Cards do Multiply->Add really well, but less-so on Add->Multiply) Red is multiplier for Tangent, Green for Binormal, and Blue for Normal.
So what if we want our normal to be bent “up” in a Normal Map. Really, the best we can do is say that we want to bend along the Binormal or Tangent, because “up” is constantly changing. If you wanted more Binormal, you would trade some Green and get something like 0T .7B .7N. Maybe it’s just easier to think of a Normal Map as how much you need to bend the Vertex Normal, but at heart, it is the vector that when multiplied by our very arbitrary basis, will yield the correct vector in another, useful space, like World-space. This is why you actually get better results form Normal Map bakes if you can guarantee your sampling Tangents and your Display Tangents are computed identically.
Alright, so why such a mindbending and difficult space? Why not Object-space, can’t we do the same rotations but without this crazy varying basis? Yes, actually, but Tangent-space normals have some very interesting properties.
[ul]
[li]You can guarantee that the Z component will always be greater than 0, because it must point out from the face. This gives Tangent-space normals their characteristic blue color (because it will always be greater than 128 when range-compressed), and means that for compression, you can actually completely drop the Z Component, and recompute it using the Pythagorean Theorem.
[/li][li]Tangent-space Normal Maps are also far more reusable. Imagine having a single solid-mesh cube. A standard in-game crate. Every face would require different texture colors in Object-space, but a single Tangent-space image of one side could be transformed by the TBN for each face and re-used.
[/li][li]Tangent-space has interesting properties for blending as well. You can treat the Tangent-space Normals more as “offsets from default” instead of “this direction in space”, and get more pleasing blending. For example, if you had .7T 0B .7N blended with 0T .7B .7N, a vector lerp would give you .35T .35B .7N which would look washed out. Artistically, you really want something more like .66T .66B .66N, and there are several fast approximations to get that in Tangent-space, largely because you can make huge assumptions about the Z.
[/li][/ul]
I’m sorry for rambling, and a bit of this is probably gibberish, but I hope small parts of it may be helpful. I hope that at the very least I didn’t make things more confusing.
Cheers!