# If bump maps override face normals for lighting calculations, why do flat shaded bump mapped models look different from smooth-shaded bump mapped?

I am confused in regards to this. From my understanding, a bump map sort of 'overrides' the normals provided by the mesh faces for lighting calculations.

I also know that in flat-shading, a pixel is shaded based on color calculated with the normal of its face only, while smooth-shading interpolates the normals calculated at each vertex per pixel and shades the pixel accordingly. As such, flat shaded faces have the same color throughout while smooth-shaded dont

A bump/normal map essentially shades the triangle per pixel just like smooth shading, but the normal used is taken from the map/texture as opposed to some linearly interpolated vertex normal. So logically, since normal/bump maps do this overriding of the normals to be used for shading, one would expect that a smooth-shaded bump map model should look identical to a flat-shaded bump-mapped one

After all, in both a smooth and flat shaded bump mapped normal, the bump map overides the normal in both cases.

Yet here is what a smooth-shaded Bump mapped Suzzane looks like:

And this is what a flat-shaded bump mapped Suzzane looks like:

The difference is very subtle but it is indeed there. What exactly causes them both to look different? Isnt a bump map overriding the mesh normals in each case?

• Aug 20, 2021 at 21:35
• @AllenSimpson I still don't get it. From everything I've read, Tangent Space is (U,V,N) where N is the underlying geometric normal of the shaded triangle. The normal encoded in the Tangent Space map replaces the interpolated vertex normal due to smooth shading. The change-of-basis is calculated once per triangle, not once per pixel, for economy? In that case, I would expect the interpolated normal to be chucked out as irrelevant, and the smooth shading of the mesh to have no effect. Aug 21, 2021 at 10:01
• ..or is the tangent-space basis precalculated once-per-vertex, and then that is interpolated across the triangle? That would make sense, and smooth-shading would still enable/disable the interpolation of what is considered to be the N-component of the map, in world space. That would explain it. Aug 21, 2021 at 10:10
• @Robin that could be, I've never dove into the code Aug 21, 2021 at 19:58

According to the manual

The Bump node generates a perturbed normal from a height texture, for bump mapping. The height value will be sampled at the shading point and two nearby points on the surface to determine the local direction of the normal.

This makes sense if you think about it for a moment. The bump map cannot completely overwrite the original normal because the map image itself has no information about which way the normal is facing in 3 dimensions because it does not contain a 3d vector like a normal map does. It only contains height information, which Blender samples to get a direction vector which is combined with the original meshes normal vector to create the offset. That original mesh normal vector enters the Bump node via the unconnected Normal input, and is affected by shade smooth.

For example, if we sample the bump map and get a height of 20, then one unit* to the left we get a height of 25, and one unit up we get a height of 30, we can make three points: (0, 0, 20), (1, 0, 25),and (0, 1, 30) from which we can do a little linear algebra and come up with a direction vector like (-0.45, -0.89, 0.09) which is then combined the mesh normal to get the final vector. **

a = Vector( (0, 0, 20) )
b = Vector( (1, 0, 25) )
c = Vector( (0, 1, 30) )

n=(b-a).cross(c-a)
n.normalize()


To give an example, we take a default cube with a bevel modifier and setup a viewer (emission) material to show its normals: It shouldn't be too surprising that the face pointing up is blue (RGB 0, 0, 1), the face pointing left is red (RGB 1, 0, 0) and the face pointing forward is green (RGB 0, 1, 0). Note the absolute vector node so we can see negative colors. We can also see magenta (RGB 0.5, 0, 0.5) and other colors on the bevels.

Now add in a checkerboard texture as a bump map:

And look the effect that has on the normals: The areas where the checkerboard is solid white or solid black have the same normal values as the unbumped example. The only changes to the normals occur where there is a color transition. So in effect, the bump mapping node acts like a directed edge detector for its input image.

*unit is left a little vague here, a pixel on the UV map might seem ideal, but it really depends on how the object was unwrapped.

** disclaimer: I did not read Blenders code, this is based on general principles.

• So it basically takes both a point/pixel from the texture and 2 points close to the point/pixel on the mesh we are shading to sort of get a local 'angle' since the bump map doesnt have a way of telling WHERE exactly it points, just the magnitude or height of how much it points?
– Hash
Aug 20, 2021 at 21:33
• I believe it's using 3 points from the texture to determine the angle, where closeness must come from the UV unwrapped geometry, so the texture points may not actually be nearby on the image if the mesh point lies near a UV seam. Aug 20, 2021 at 22:11
• Could you explain what you mean exactly again? If bump map values dont tell us direction, how does using 3 points from the bump map texture give us direction/angle?
– Hash
Aug 20, 2021 at 22:17
• I edited in a paragraph to the answer, does that help? Aug 20, 2021 at 22:35
• Regarding your edit, if we add that direction vector to the mesh normal, wont that give us a vector with a magnitude greater than 1? Shouldnt normal vectors have a magnitude = 1? And what specfic linear algebra operation did we do to combine those 3 points to give us (-0.45,-0.89, 0.09) exactly?
– Hash
Aug 21, 2021 at 9:36