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 enter image description here


1 Answer 1


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.

  • \$\begingroup\$ 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 \$\endgroup\$ Mar 7, 2015 at 12:20
  • \$\begingroup\$ 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. \$\endgroup\$
    – Thelvyn
    Mar 7, 2015 at 17:45
  • \$\begingroup\$ 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? \$\endgroup\$ Mar 10, 2015 at 22:03

You must log in to answer this question.

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