# Normal mapping

**Normal mapping** is a texture-based shading technique in computer graphics that simulates surface detail by replacing or perturbing the surface normal used in lighting calculations on a per-pixel basis, without adding any geometry to the model. It is the most commonly used variation of bump mapping: instead of a grayscale height map, a normal map stores a surface direction per pixel as RGB values, and the shader uses this stored vector when evaluating lighting.<sup>[1](https://liu.diva-portal.org/smash/get/diva2%3A21294/FULLTEXT01.pdf)</sup> The technique became a standard part of real-time rendering following work by Heidrich and Seidel in 1999.<sup>[2](https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-22-baking-normal-maps-gpu)</sup>

| Key fact | Detail |
|---|---|
| Origin | Descends from bump mapping, introduced by James Blinn in 1978, which perturbs the surface normal from a height map<sup>[3](https://web.cs.wpi.edu/~matt/courses/cs563/talks/bump/bumpmap.html)</sup> |
| What the texture stores | A per-pixel direction encoded in RGB, scaled to the 0..255 range by `normal * 0.5 + 0.5`<sup>[2](https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-22-baking-normal-maps-gpu)</sup> |
| Effect on geometry | None: normals change at render time, so lighting shows detail but the silhouette stays smooth<sup>[4](https://www.sidefx.com/docs/houdini/shade/normalmaps.html)</sup> |
| Dominant space | Tangent space: the stored vector is a small tilt relative to the surface, not a world-space direction<sup>[5](https://deepraster.com/articles/normal-mapping-tangent-space-explained/)</sup> |
| Green-channel conventions | OpenGL (Y+) versus DirectX (Y−); the two agree on red and blue and differ only in green<sup>[6](https://fsmodworks.com/en/guides/normal-map)</sup> |
| Typical production | Baked by projecting rays from a low-polygon working model onto a high-polygon reference model<sup>[2](https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-22-baking-normal-maps-gpu)</sup> |
| Sampling requirement | Normal maps are linear data and must be sampled as Non-Color / normal-map textures, not sRGB color<sup>[7](https://theuseful.website/guides/opengl-vs-directx-normal-maps)</sup> |

## Origin in bump mapping

In 1978 James Blinn presented bump mapping, which simulates bumps and wrinkles without geometric modification by perturbing the surface normal according to a texture and using the perturbed normal in the Lambertian shading equation.<sup>[3](https://web.cs.wpi.edu/~matt/courses/cs563/talks/bump/bumpmap.html)</sup> Blinn's original method derives the perturbation from the local derivatives of a height function, and one known limitation is that the simulated wrinkles do not extend to the object's silhouette.<sup>[3](https://web.cs.wpi.edu/~matt/courses/cs563/talks/bump/bumpmap.html)</sup>

Normal mapping replaces the height map with a texture that stores the perturbed normals directly, applied on a per-pixel basis.<sup>[1](https://liu.diva-portal.org/smash/get/diva2%3A21294/FULLTEXT01.pdf)</sup> Where the normals are overwritten by the normal map, the output normal is simply the value stored in the texture's RGB channels.<sup>[8](https://publications.lib.chalmers.se/records/fulltext/203180/203180.pdf)</sup> Because the shading normal, not the geometry, is what changes, normal and bump mapping are faster and use less memory than adding real geometry, and a low-resolution model with a normal map baked from a high-resolution model can be visually almost indistinguishable from the high-poly original.<sup>[4](https://www.sidefx.com/docs/houdini/shade/normalmaps.html)</sup>

## Tangent space and coordinate conventions

A tangent-space normal map holds no world-space vector; instead it encodes a slight deviation from the underlying surface, given in that surface's own tangent, bitangent, and normal axes.<sup>[5](https://deepraster.com/articles/normal-mapping-tangent-space-explained/)</sup> The red, green, and blue channels represent these three basis directions.<sup>[9](https://www.cryengine.com/docs/static/engines/cryengine-3/categories/1638401/pages/1605679)</sup> A flat region of the surface corresponds to the neutral value (0.5, 0.5, 1.0) after encoding.<sup>[10](https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/Specification.adoc)</sup>

[Tangent space](https://www.edgepedia.org/tangent-space) has practical advantages over object space. The cost is that the engine must reconstruct the exact same tangent frame at runtime that the baking tool used, and tangent-space vectors are stored per vertex to support this.<sup>[11](https://giuseppeboschiero.com/blog-normal-maps.html)</sup><sup> • </sup><sup>[9](https://www.cryengine.com/docs/static/engines/cryengine-3/categories/1638401/pages/1605679)</sup>

**Two green-channel conventions.** Tangent-space normal maps come in two conventions that differ only in the direction of the green (Y) channel: OpenGL (Y+), used by Blender, Godot, Unity, and the glTF format, and DirectX (Y−), the default of [Unreal Engine](https://www.edgepedia.org/unreal-engine).<sup>[6](https://fsmodworks.com/en/guides/normal-map)</sup><sup> • </sup><sup>[7](https://theuseful.website/guides/opengl-vs-directx-normal-maps)</sup> Loading a DirectX map into an OpenGL-style shader, or the reverse, inverts the perceived slope of every detail that is not a perfect pyramid, making a carved surface look embossed or vice versa; the fix is a single green-channel inversion, not a new bake.<sup>[12](https://www.locker3d.com/2025/02/normal-map-formats-directx-vs-opengl.html)</sup> The glTF 2.0 format strictly mandates the OpenGL standard (+Y up) and provides no runtime toggle, so a DirectX-native engine loading glTF must accommodate the OpenGL convention.<sup>[13](https://salivity.github.io/gltf/article/gl-tf-normal-map-flipping-direct-x-vs-open-gl)</sup> The convention is a sign convention, not a quality difference, and the receiving shader or import setting, not the operating system, defines how the green values are decoded.<sup>[12](https://www.locker3d.com/2025/02/normal-map-formats-directx-vs-opengl.html)</sup><sup> • </sup><sup>[14](https://www.normalmapmaker.com/guides/opengl-vs-directx-normal-map/)</sup>

## Baking normal maps

In the classic baking method, each point on the low-polygon mesh's surface (the working model) is cast outward toward the high-polygon mesh (the reference model). The working model is rasterized into texture space, and a ray is traced from an interpolated boundary cage, a mesh extruded from the working model that the artist can adjust to control how rays are cast, toward the reference model; of the possible hits along the ray, the normal closest to the cage is selected.<sup>[2](https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-22-baking-normal-maps-gpu)</sup> A useful property of this setup is that the dense reference model needs no texture coordinates, since building UVs for very dense meshes is troublesome.<sup>[2](https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-22-baking-normal-maps-gpu)</sup>

**GPU baking.** Because the computation is highly parallel and independent, it suits a stream processor: a midrange Shader Model 3.0 graphics card can generate normal maps faster than most CPU-based tools. The GPU Gems 3 implementation stores the reference mesh and a uniform-grid acceleration structure in textures and traverses the grid with the 3D digital differential analyzer algorithm of Amanatides and Woo (1987), which visits voxels in correct order so that a valid hit occludes later ones.<sup>[2](https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-22-baking-normal-maps-gpu)</sup> In the worked example, the reference model has about 560,000 triangles and the working model only 868; the acceleration data (a 256×256×256 R32F grid texture of 64 MB, a 32 MB triangle-list texture, and geometry textures) totals 108 MB of video memory.<sup>[2](https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-22-baking-normal-maps-gpu)</sup> Shader Model 3.0 limits each pixel-shader loop to 256 iterations, worked around with nested loops (up to 65,536 iterations) or a multipass approach, and antialiasing can be added by tracing more rays or by rendering the map repeatedly with jittered positions at a cost linear in the number of passes: a map that takes about 1 second takes about 16 seconds with 16 samples.<sup>[2](https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-22-baking-normal-maps-gpu)</sup>

## Practical issues

**Seams.** A UV seam inherently produces a tangent-space seam, which is a leading cause of visible normal map seams; a seam visible only after import points to tangents, UV splits, compression, or mipmaps rather than the texture itself.<sup>[15](https://www.tripo3d.ai/blog/explore/smart-mesh-normal-map-tangent-space-pitfalls)</sup><sup> • </sup><sup>[16](https://normalmapgenerator.net/normal-map-artifacts-and-fixes/)</sup> A map baked in one tool also needs the engine to reconstruct the identical tangent frame at runtime.<sup>[11](https://giuseppeboschiero.com/blog-normal-maps.html)</sup>

**Precision and filtering.** At distance, mipmapped normal maps alias, producing strobing or sparkling noise in specular highlights; most mipmapping algorithms simply renormalize the averaged normals, but the shortening of the averaged vector can instead be used as a measure of normal variation to suppress this aliasing.<sup>[17](https://www.tandfonline.com/doi/abs/10.1080/2151237X.2005.10129203)</sup> Texture compression formats have also been evaluated for both object-space and tangent-space normal maps to reduce memory cost.<sup>[18](https://vodacek.zvb.cz/archiv/150.html)</sup>

**Relation to other detail maps.** Bump maps store a single scalar height from which the normal is derived at render or bake time, and displacement maps actually move vertices, changing the silhouette; normal maps do neither.<sup>[5](https://deepraster.com/articles/normal-mapping-tangent-space-explained/)</sup><sup> • </sup><sup>[4](https://www.sidefx.com/docs/houdini/shade/normalmaps.html)</sup> Parallax and parallax occlusion mapping extend the family by shifting the sampled texture to suggest depth with perspective-correct detail.<sup>[19](https://gdcvault.com/play/1013219/Practical-Parallax-Occlusion-Mapping-for)</sup>

## Adoption

It remains a core property of modern PBR material workflows: the glTF 2.0 metallic-roughness model defines a normal texture that perturbs surface normals to create the illusion of additional detail, more efficiently than adding actual geometry.<sup>[20](https://www.khronos.org/gltf/pbr)</sup> Beyond 3D games, normal mapping is applied to 2D pixel art for dynamic lighting of sprites, though style-specific considerations mean general 3D methods may not yield correct results there.<sup>[21](https://arxiv.org/abs/2212.09692)</sup>

## References

1. [Normal Mapping (degree project), Linköping University](https://liu.diva-portal.org/smash/get/diva2%3A21294/FULLTEXT01.pdf)
2. [Diogo Teixeira, Chapter 22. Baking Normal Maps on the GPU, GPU Gems 3, NVIDIA](https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-22-baking-normal-maps-gpu)
3. [Brian Lingard, Bump Mapping (summary of Blinn's method), WPI](https://web.cs.wpi.edu/~matt/courses/cs563/talks/bump/bumpmap.html)
4. [Adding detail with normal, bump, and displacement mapping, SideFX Houdini documentation](https://www.sidefx.com/docs/houdini/shade/normalmaps.html)
5. [Normal Mapping and Tangent Space Explained, DeepRaster](https://deepraster.com/articles/normal-mapping-tangent-space-explained/)
6. [Normal Maps Explained: Tangent Space, RGB Channels and OpenGL vs. DirectX, FS Modworks](https://fsmodworks.com/en/guides/normal-map)
7. [OpenGL vs DirectX Normal Maps: Which One Your Engine Needs, The Useful Website](https://theuseful.website/guides/opengl-vs-directx-normal-maps)
8. [Bump mapping in a game engine (degree project), Chalmers](https://publications.lib.chalmers.se/records/fulltext/203180/203180.pdf)
9. [Tangent Space Normal Mapping, CRYENGINE documentation](https://www.cryengine.com/docs/static/engines/cryengine-3/categories/1638401/pages/1605679)
10. [glTF 2.0 Specification, Khronos Group](https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/Specification.adoc)
11. [Normals Explained: From Surface Math to Normal Maps, Giuseppe Boschiero](https://giuseppeboschiero.com/blog-normal-maps.html)
12. [Normal Map Formats: DirectX vs OpenGL, Locker3d](https://www.locker3d.com/2025/02/normal-map-formats-directx-vs-opengl.html)
13. [glTF Normal Map Flipping: DirectX vs OpenGL, salivity](https://salivity.github.io/gltf/article/gl-tf-normal-map-flipping-direct-x-vs-open-gl)
14. [Free OpenGL vs DirectX Normal Maps, Normal Map Maker](https://www.normalmapmaker.com/guides/opengl-vs-directx-normal-map/)
15. [Smart Mesh Normal Map Tangents: Pitfalls & Best Practices, Tripo3D](https://www.tripo3d.ai/blog/explore/smart-mesh-normal-map-tangent-space-pitfalls)
16. [Normal Map Artifacts: Common Problems and Fixes, NormalMapGenerator](https://normalmapgenerator.net/normal-map-artifacts-and-fixes/)
17. [Mipmapping Normal Maps, Journal of Graphics Tools Vol. 10, No. 3](https://www.tandfonline.com/doi/abs/10.1080/2151237X.2005.10129203)
18. [Real-Time Normal Map DXT Compression, NVIDIA](https://vodacek.zvb.cz/archiv/150.html)
19. [Practical Parallax Occlusion Mapping for Highly Detailed Surface Rendering, GDC Vault](https://gdcvault.com/play/1013219/Practical-Parallax-Occlusion-Mapping-for)
20. [PBR - Physically Based Rendering in glTF, Khronos Group](https://www.khronos.org/gltf/pbr)
21. [Moreira, Coutinho, Chaimowicz, Analysis and Compilation of Normal Map Generation Techniques for Pixel Art, arXiv:2212.09692](https://arxiv.org/abs/2212.09692)

---
*Topic: Encyclopedia › Sports, games, and recreation › Video games and digital play › Game industry › Development and technology › Graphics and rendering technology*

*Initially written Sep 17, 2026 · Reviewed: Sep 30, 2026; Oct 21, 2026 · Edited: Oct 15, 2026; Oct 21, 2026 · Last review: Oct 21, 2026*

*Copyright 2026 EdgeChat AI, a subsidiary of Biostate AI.*

License: Edgepedia Community License 1.0, https://www.edgepedia.org/edgepedia/license
