In several topics here it was suggested by people that doing lighting in tangent space is better than doing it in world space. Right now I am doing it in camera space, but it's really similar to world space. My question is, why would tangent space be a better choice for this (I am using normal maps if it matters)? Secondly, when going from model space to world space and vice-versa, a scale is applied. This produces a problem when it comes to attenuated light, because the distances are quite different than in world space, which is where my light positions are. How would I deal with this? Thanks in advance

EDIT: Attenuation problem illustrated

I'm not an expert about it but I'll try to explain.

When you compute per pixel lighting in camera space, you transform your normal map from tangent space to camera space. The idea of working in tangent space is to transform the camera and lights to tangent space then perform lighting computations. So instead of transforming normals from your normal map to camera space, you transform other objects to tangent space.

You can perform this transformation in the vertex shader once per face, then you do not need to transform your normals.

Lets consider an example where we work in tangent space and we want to draw a quad that uses a 256x256 normal map (all texels are drawn). In a forward renderer we will transform the lights and the camera to tangent space, lets say 5 objects, and we do it in the vertex shader (once per face), so we do not have to transform the 256x256 normals (they are already in tangent space).

What's the catch ? It works well in a simple forward renderer but wont work with a deferred one. In a deferred renderer you would perform the camera and light transformation in the fragment shader which would be overkill. And if you're interested in clustered rendering it wont work in both forward and deferred, because you get a per pixel list of lights.

For attenuation it does not matter, as long as you are in the same space computations are the same.

• What do you mean it does not matter for attenuation? It depends on the distance from the light to the fragment, which is length(lightToFragmentVec3). This vector is not the same length when light position is transformed to tangent space, because the transformations involve a scale (from world to model space). Am i missing something? I added a picture to my original post to illustrate this – W. Nawrocki Mar 7 '15 at 12:20
• The point is that you do not have to transform the positions to tangent space to compute attenuation, you can do it in world space for example. – Thelvyn Mar 7 '15 at 17:45
• Then I would have to send the vertex position and light position twice, once in tangent space, and once in world space for attenuation. Wouldn't this be a little overkill? – W. Nawrocki Mar 10 '15 at 22:03