I am writing a basic rasterizer and I'm testing to see if my normals are set up and handled properly by shading a sphere with its vertex normals to obtain enter image description here

For context, we are looking in the +Z direction with -Y upwards.

As I have it, the vertex normals are transformed by the inverse transpose of the model-to-world space matrix and the inverse transpose of the view matrix. If I move the camera around the sphere, I see no colour changes which is also to say that the colours on the sphere seem to be constantly "facing" the camera (I suppose as expected when in view space coordinates).

If I don't transform the normals with the view matrix, then the colours are the same, but the colours on the sphere no longer "face" the camera.

Here is where I'm conflicted:

  • It seems that normals are conventionally transformed via MV (as opposed to the full MVP), so that would imply that the behaviour mentioned above is intended.
  • It seems counter-intuitive that the surface normals should change based on the viewing angle. Say I want to use the normals in a reflection model. Doesn't this mean reflections on an object change in a static scene depending on where I'm looking?
  • 1
    $\begingroup$ It's up to you whether you do your lighting calculations in world space or view space, for the formed you just have tranform with $M^{-T}$, for the latter you additionally need $V$. Since a camera matrix (and consequently a view matrix) isn't supposed to contain anything but a translation and rotation, then $n^Tu = n^TV^TVu = (Vn)^TVu$, so the space doesn't matter. If you introduced a non-uniform scale the inverse transpose will still save you: $n^Tu = n^TV^{-1}Vu = (V^{-T}n)^T(Vu)$. $\endgroup$
    – lightxbulb
    Commented Jul 6 at 21:57
  • $\begingroup$ I see. Forgive me for my naivety and please correct me if I'm wrong, but as I understand it, some lighting models such as Blinn-Phong are implemented in the fragment shading stage of the graphics pipeline which comes after all the transformations (i.e. MVP, perspective divide, viewport transform). So, I don't quite understand how one can "do your lighting calculations in world space or view space". Again, I am new to graphics and trying to untangle my understanding, so thank you for your help! $\endgroup$
    – Scene
    Commented Jul 7 at 1:52
  • $\begingroup$ You pass in the normals without having applied the projection matrix to those, then they get interpolated over the triangle and you're supposed to normalize them per pixel and do your shading calculations. You also have the option to do the shading in the vertex shader, which would be Gouraud shading. So it is up to you. See a tutorial, e.g. learnopengl.com. $\endgroup$
    – lightxbulb
    Commented Jul 7 at 7:07

1 Answer 1


Vertex data generally provides the normal vector in object space. It sounds like this is being done in the example provided.

From there we can visualize the normal in object space, world space or view space, there is no "canonical" space to visualize normal vectors.

If you provide a small axis graphic showing the axis for each of those coordinate systems then they would each look slightly different. (ie an arrow pointing in the x,y,z directions to show the directions of each major axis)

In object and world space each axis would be fixed as we move around we would be able to look at the axis from different directions. The normal vectors on the model would also look different from different directions.

In view space, all the axis would move with the camera. No matter where the camera moves the x,y,z axis would always face the same direction. We expect this to be true since we are transforming the geometry into camera (ie view) space. NOTE: We can still visualize those transformed vectors like we did with object and world space by creating an "alternate" camera that lets us look at the "main" camera then transform it's view space normal vectors into the alt camera view space.

For simplicity normal vectors are usually transformed into either object space (ie they are not transformed at all) which is handy for visualizing normal vectors when looking at individual models. Or into world space using the model to world matrix. This puts all the normal vectors in a common space which allows them to be compared to each other. Visualizing normal vectors in view space isn't as common since there isn't much to look at (other then to verify that the vectors are pointing in the expected directions) and requires additional complexity to view them from different directions.

As lightxbulb pointed out, we can do lighting calculations in the space of choice. Visualizing normal vectors is one of many motivators on choosing which basis lighting calculations are done in. For example if we are doing lighting calculations in world space then we probably want to visualize normal vectors in world space. This allows comparing light computations to vectors.

Yet another approach is to draw the geometry twice. Once with lighting and a second time drawing the normal vectors as small lines showing their direction, the lines can also be colored. This gives excellent feedback on the vector direction and allows direct comparison to the lit and possibly textured object.

  • $\begingroup$ Thank you for the clear and detailed explanation. I do have a question: in visualization, how would we draw the normal vectors as lines without passing them through all the transformations (i.e. projection, perspective divide, viewport)? $\endgroup$
    – Scene
    Commented Jul 7 at 16:38
  • $\begingroup$ It is important to separate the geometry from the normal vectors. The geometry does goes through the mvp but the normals only get transformed into the space we want to view them in. $\endgroup$
    – pmw1234
    Commented Jul 7 at 21:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.