Home Technical Talk

Don’t use gamma on normal maps

I shared this on LinkedIn, might help some people here too.

Don’t use Gamma on normal maps


Normal maps should be saved in linear color space, without color correction from Gamma or sRGB. 

A lot of game PBR texture pipelines use sRGB color space, which is fundamentally very similar to Gamma 2.2. It’s so close, they’re pretty much interchangeable, from an artist’s standpoint.

It’s important to use sRGB on 24bit bitmaps for colored inputs like Diffuse, Emissive, Reflection and Refraction. 

Color textures that could be captured with a camera should be stored using sRGB color space, while all the other maps (normal, rough, metal, occlusion) should be saved in linear color space.

Gamma 1.0 = Linear, same thing.

You can use a histogram to check if a map has been saved wrong. Histograms are cool! Look for a peak in the center, that’s what you want to see.


Replies

  • stray
    Offline / Send Message
    stray polycounter lvl 2
    In context of what was brought up in other thread it should be noted: Blender in particular makes the texture look pale when the image Color Space is set to "Non-color", but it will read correctly by the Normal Map node. It can get a little confusing because of that.


  • Eric Chadwick
    Ugh, yeah lots of tools don’t display normal maps the right way in their thumbnails/viewers.

    Here’s another tip:

    Normalize your textures!



    I made a couple SBSAR procedural filters for normalizing textures, since I couldn't find reliable tools for this. Maybe these filters can help you!

    Normal maps should always be normalized before final delivery, to make sure the vectors are mathematically correct for optimal shading. It's easy to edit textures in tools like Photoshop etc. but it's not easy to normalize them properly.

    Sometimes the shader will normalize for you, but it's not always guaranteed to happen. When a map isn't normalized, and the shader doesn't do it, you could see bad lighting and aliasing.

    Same with anisotropy textures.

    I did a webinar about how to make Iridescence and Anisotropy using glTF, and shared a bit about normalizing textures, you can jump to 21:35 to hear about that:

    https://www.youtube.com/watch?v=PyMgrV8BErY

    Normalize a 3D vector:
    Substance_Normalize3D (zip file)
    - This is a Substance 3D Asset which can be used with Adobe Substance Player and other applications which support SBSAR.
    - This normalizes a 3D vector stored in the red and green and blue channels of a bitmap.
    - Useful for normal mapping, flow maps, etc.

    Normalize a 2D vector:
    - Substance_NormalizeRG (zip file) 
    - Normalize a 2D vector stored in the red and green channels of a bitmap.
    - Useful for anisotropy textures, maybe other things too?
  • Eric Chadwick

    Why do we have to "normalize" our normal maps?

    Here's an example that hopefully helps illustrate it!



    Notice how the lighting is messed up in the edited normal map. You can't see the windows anymore on the dome and donut, and even the flat background is reflecting the wrong colors.

    This came up in my last post; I shared some Substance filters to normalize both normal and anisotropy maps. I showed an example with anisotropy, and how that can go wrong.

    What about normal maps? Yeah, they can get pretty bad too!

    Usually you shouldn't edit a normal map directly, instead you should use dedicated tools that build a normal map properly. But why does this matter?

    Each pixel in a normal map uses the red, green, and blue channels to encode x, y, and z coordinates of a vector. These vectors are used by shaders to change lighting on your surfaces. It's pretty cool. But if the RGB data is altered by painting or compositing, then those vectors can get messed up.

    So... it's best to normalize, after you're done editing.

    LMK if you have any questions. It can be pretty weird to wrap your head around.
  • Klunk
    Offline / Send Message
    Klunk quad damage
    there's some interesting maths regarding combining normal maps..... you can add the normals together and normalize the result but this does not give the correct result as it generates a kind of blended/average result. To do the math correctly you create a transform  matrix from the base normal and then transform the overlaying normal into that space by multiplying it with the inverse of that matrix.... then you can add it to the base normal and normalize. In basic terms combining a [0,0,1] normal map ( 0.5, 0.5, 1.0 rgb) with an existing map leaves it unchanged .
  • Eric Chadwick
    +1 ^^

    A great read if people want to dive deeper:

    And a free tool to combine normal maps, by @Farfarer
    RNM Normal Map Combiner
    "A little Python/OpenGL app for combining tangent space normal maps together. Uses the Reoriented Normal Map method described by Colin Barré-Brisebois and Stephen Hill."

  • stray
    Offline / Send Message
    stray polycounter lvl 2
    Okay, so "normalized" means normalized when in range [-1;1]...
    I've read there is a packing method where blue channel is discarded, some other map stuffed in, then normal map is reconstructed in material.
    So if I'm understanding this correctly, this method is rooted in the fact that the map only describes unit vectors, all of which are looking "up" (z-component always positive).

    Testing this assumption with some nodes seems to give correct results. As far as I can tell at least...


    Is it really how it works?
  • Eric Chadwick
    The shader can be designed to normalize for you, but it does make it a tad bit slower. It’s a tradeoff.
Sign In or Register to comment.