What Are Mipmaps and How Three.js Generates Them

This article explains the concept of mipmaps in 3D computer graphics and details how the Three.js library automatically generates and applies them to textures. You will learn what mipmaps are, why they are crucial for performance and visual quality, and how Three.js manages this process behind the scenes.

What Are Mipmaps?

Mipmaps are sequences of pre-calculated, optimized images that accompany a main texture. Each subsequent image in the mipmap sequence is exactly half the width and height of the previous one. For example, a 512x512 texture will have mipmaps at 256x256, 128x128, 64x64, 32x32, 16x16, 8x8, 4x4, 2x2, and 1x1.

Mipmaps serve two primary purposes in 3D rendering:

  1. Reducing Aliasing (Moiré Patterns): When a high-resolution texture is rendered on an object far away from the camera, the GPU has to map many texture pixels (texels) to a single screen pixel. This causes flickering and visual artifacts. Mipmaps prevent this by providing a pre-scaled, lower-resolution version of the texture that matches the screen size of the object.
  2. Improving Performance: Accessing smaller textures when objects are far away reduces GPU memory bandwidth usage and improves cache efficiency, leading to higher frame rates.

How Three.js Automatically Generates Mipmaps

By default, Three.js automatically generates mipmaps for every texture you load. This seamless behavior is managed through the library’s integration with WebGL.

The Automatic Generation Process

When you load a texture using a loader like THREE.TextureLoader, Three.js configures the texture object with default properties:

When the scene is rendered, Three.js uploads the texture to the GPU. During this upload process, if generateMipmaps is set to true, Three.js instructs the WebGL context to generate the mipmap chain automatically using the hardware-accelerated WebGL command:

gl.generateMipmap(gl.TEXTURE_2D);

This command allows the GPU to quickly generate the lower-resolution versions of the texture in graphics memory.

Texture Dimensions and WebGL 2

In modern WebGL 2 (which Three.js uses by default in current versions), the GPU can automatically generate mipmaps for textures of any size, including non-power-of-two (NPOT) dimensions (e.g., 500x300).

If you are targeting older WebGL 1 contexts, textures must have power-of-two (POT) dimensions (e.g., 256x256, 512x1024) to support automatic mipmap generation. If a texture is non-power-of-two in WebGL 1, Three.js will attempt to auto-resize the texture to the nearest power-of-two size so that mipmaps can still be generated.

How to Disable or Customize Mipmaps

While automatic mipmaps are beneficial for most 3D scenes, there are scenarios—such as 2D pixel art interfaces, UI overlays, or custom shaders—where you may want to disable them to save memory or maintain crisp edges.

To disable automatic mipmap generation in Three.js, set generateMipmaps to false and change the minification filter (minFilter) to a non-mipmap filter:

const texture = new THREE.TextureLoader().load('path/to/texture.jpg');

// Disable mipmap generation
texture.generateMipmaps = false;

// Set the minification filter to not use mipmaps
texture.minFilter = THREE.LinearFilter; // Or THREE.NearestFilter for pixel art

By disabling mipmaps and using THREE.LinearFilter or THREE.NearestFilter, the GPU will only load the base texture, saving roughly 33% of the texture’s video memory (VRAM) at the cost of potential aliasing when the texture is viewed from a distance.