Three.js lightMap vs aoMap: What is the Difference?
When rendering 3D scenes in Three.js, baking lighting into textures
is a highly effective way to achieve realistic visuals without the
performance cost of real-time lights and shadows. Two primary texture
maps used for this purpose are lightMap and
aoMap (Ambient Occlusion map). While both influence how
light interacts with a material, they serve distinct purposes: a
lightMap stores pre-calculated direct and indirect
illumination, whereas an aoMap simulates soft, localized
shadows in crevices and corners where ambient light cannot reach.
Understanding the technical differences between these two maps is
crucial for optimizing your Three.js materials and scene
performance.
What is a lightMap?
A lightMap contains baked lighting data, which includes
both direct light (such as the sun or lamps) and indirect bounced light
(global illumination).
- Color and Intensity: Unlike grayscale maps, a
lightMapis typically a full-color (RGB) texture. It dictates the exact color and brightness of the light hitting a surface. - Functionality: In Three.js, when you apply a
lightMapto a material (such asMeshStandardMaterialorMeshBasicMaterial), it adds illumination to the surface. It can be used to make a scene look fully lit even when there are zero real-time lights active in your Three.js scene. - Three.js Property:
material.lightMap - Control: You can adjust its influence using
material.lightMapIntensity(default is1.0).
What is an aoMap?
An aoMap (Ambient Occlusion map) is a grayscale texture
used to simulate contact shadows in areas where geometry blocks ambient
light, such as corners, creases, and joints.
- Color and Intensity: It is a monochrome (grayscale) map where white represents fully lit areas and black represents fully shadowed areas.
- Functionality: The
aoMapdoes not contain directional light, colored light, or specular reflections. Instead, it acts as a multiplier for the ambient (indirect) light in the scene. It darkens crevices to add depth and realism, but it does not affect direct light sources. If a strong directional light hits an occluded area, that area will still be lit. - Three.js Property:
material.aoMap - Control: You can adjust its strength using
material.aoMapIntensity(default is1.0).
Key Differences
| Feature | lightMap | aoMap |
|---|---|---|
| Primary Purpose | Bakes overall lighting (brightness, color, and bounced light) onto a surface. | Bakes micro-shadows in crevices where ambient light is blocked. |
| Color Space | RGB (Color) | Grayscale (Monochrome) |
| Interaction with Lights | Adds light to the material; can completely replace real-time lights. | Multiplies (darkens) ambient light; does not affect direct light. |
| Visual Effect | Warmth, cool tones, shadows, and highlights. | Soft, realistic depth in corners and cracks. |
The UV2 Requirement in Three.js
A critical technical detail in Three.js is that both
lightMap and aoMap require a second set of UV
coordinates (the uv2 attribute) on your geometry to map
correctly.
By default, the standard uv attribute is used for the
main texture maps (like map, roughnessMap, and
normalMap), which often tile across the surface. Because
baked lighting and ambient occlusion maps must map uniquely to the
entire 3D object without tiling, they require a unique, non-overlapping
UV layout assigned to the uv2 channel.
You can copy the primary UV channel to the secondary UV channel in JavaScript like this:
const geometry = mesh.geometry;
geometry.setAttribute('uv2', new THREE.BufferAttribute(geometry.attributes.uv.array, 2));When to Use Which?
- Use a
lightMapwhen you want to target mobile devices or web browsers with strict performance budgets. By baking all your light, color, and shadows into alightMap, you can useMeshBasicMaterial(which requires no light calculations) and still achieve high-fidelity graphics. - Use an
aoMapwhen you are using real-time dynamic lights but want to add extra depth and realism to your models. TheaoMapensures that corners and cracks remain dark, preventing the flat look often associated with real-time web rendering.