19
\$\begingroup\$

I am using Assimp asset importer (http://assimp.sourceforge.net/lib_html/index.html) to parse 3d models.

So far, I've simply pulled out the normal vectors which are defined for each vertex in my meshes. Yet I have also found various tutorials on normal maps...

As I understand it for normal maps, the normal vectors are stored in each texel of a normal map, and you pull these out of the normal texture in the shader.

Why is there two ways to get the normals, which one is considered best-practice and why?

\$\endgroup\$

1 Answer 1

33
\$\begingroup\$

Short Answer

Normal maps and Normals are two different things: Normals are a geometric property of any mesh/surface its use is not exclusive for shading and lighting calculations but have actually many other uses for example in physics. Normal maps are textures that encode alternative normal vectors used in computer graphics to simulate bumps.

Long Answer

Normals in geometry a normal is a vector or a line that is perpendicular to a given object (e.g. plane normal, vertex normal ). Normals in graphics are usually used for light calculations, such as calculating Diffuse reflection across a surface by taking the dot product between the light direction and surface normals. Normals are usually calculated based on the geometrical properties of the mesh (Faces/Vertices), by taking the cross product of any two non-parallel edges that lies on the same plane.

In OpenGL normals are specified per vertex (hence called vertex attributes) even though they might be calculated only for each face in this case you need to specifiy the same normal for each vertex in a face. Normals can be interpolated by OpenGL across each vertex of a face(triangle) so you can calculate the reflected light per pixel not per vertex, hence giving a more accurate result.

Normal Mapping: on the other hand is a technique in computer graphics that encodes Normals in a texture map, so each normal is encoded per texel. It is usually used for faking the lighting of bumps and dents (e.g. bump mapping, parallax mapping).

Since normals are calculated based on the geometrical properties of the mesh/surface, Normal Maps will give you alternative Normals that can simulate the bumps to add detail to the surface without adding more polygons.

Normal maps are usually generated using a much more detailed 3D model, then calculating the normals based on this model and encoding it in a Normal Map.

Why do we need both?

Well talking only about rendering, normals and normal maps are usually used together to achieve the final lighting effect, a good example might be a bump shader, where you need the normals map normal to achieve the bump lighting effect, and you will still need the geometric normal to calculate what is called the tangent space. Tangent space is usually used to provide re-usability for normal maps.

Keep in mind that a normal is considered a geometrical attribute of the surface and has many more uses than only light calculations. Normal maps on the other hand are usually used for superficial effects.

Extending the answer to explain why tangent spaces are important:

Short answer: Tangent spaces are used to make normal maps independent of the underlying geometry.

[EDIT] Added Image to represent normal map in tangent space and normal map in world space.

enter image description here

Long answer: The below picture shows the UV plane and the normal that defines the tangent space, when generating a normal map we will already know that the used space will always have the Normal pointing in the Z direction (that's why normal maps look bluish), this will help us ignore the surface curvature**, .

Tangent space gives us the advantage that our normal maps encoding isn't bound to a specific mesh normals. Suppose we encode our normal map in world or object space, then each normal we encode will have a direction based on how the original mesh normals vary in world space, not to mention your normal map will be affected by the model transformations.

enter image description here

In the above two pictures it's pretty clear that tangents space makes normal maps(right), independent of the underlying geometry because all normals are encoded in almost the same direction with small variation to simulate the effect of the bumps.

**surface curvature is defined by the amount which a geometric object deviates from being flat, or straight in the case of a line but this is defined in different ways depending on the context.

Tangent space representation

\$\endgroup\$
5
  • 1
    \$\begingroup\$ If you can find an image depicting how a normal texture alone cannot be consistently used without a normal and tangent field defined on a per-vertex basis, you'll make this the best answer on this puzzling issue for most beginner graphics programmers! \$\endgroup\$
    – teodron
    Commented Oct 21, 2013 at 11:31
  • \$\begingroup\$ Nice answer but normals are not interpolated by OpenGL across each face. You have to do it by yourself and supply the interpolated normal to OpenGL ( or to your shader code ). \$\endgroup\$ Commented Oct 21, 2013 at 13:02
  • 1
    \$\begingroup\$ @AnastasiosG I think he's talking about the default behaviour of varying data as it gets interpolated across a triangle whenever a fragment is computed for a specific primitive. I know there was a flag that you could use to tell OpenGL to use one specific normal out of the possible 3 vertex normals of a triangle, but that's not the default behaviour as I am aware of. \$\endgroup\$
    – teodron
    Commented Oct 21, 2013 at 13:32
  • 1
    \$\begingroup\$ @AnastasiosG I thought such detail won't do the answer any favor since this isn't about how to use OpenGL. But if that helps, in the fixed pipeline era you needed glShadeModel(GL_SMOOTH) inorder to tell openGL to interpolate. In the programmable pipeline era you define the variables as varying or in/out in the shader so OpenGL can interpolate. \$\endgroup\$
    – concept3d
    Commented Oct 21, 2013 at 15:57
  • \$\begingroup\$ I would like to add that bump maps are simply (geometric) normals that are raised/lowered based on a black and white texture. :) \$\endgroup\$
    – Entalpi
    Commented May 4, 2019 at 10:57

You must log in to answer this question.

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