How to Use AlphaTest in Three.js for Leaf Textures

This article explains how to resolve depth sorting and transparency glitches on leaf and foliage textures in Three.js using the alphaTest property. You will learn why these rendering issues occur, how to apply alphaTest to your materials, and how to fine-tune the threshold to ensure clean, high-performance cutouts of complex plant geometry.

When rendering semi-transparent textures like leaves on a tree, Three.js often struggles with depth sorting. By default, transparent objects do not write to the depth buffer in the same way opaque objects do, which can cause background objects to render in front of foreground leaves. The alphaTest property solves this by acting as a cutoff threshold: any fragment with an alpha value lower than the specified alphaTest value is discarded entirely, preventing it from writing to the depth buffer and eliminating sorting artifacts.

Implementing alphaTest in Your Material

To apply this solution, define the alphaTest property when instantiating your material. Below is a practical example using MeshStandardMaterial:

import * as THREE from 'three';

// Load your leaf texture with an alpha channel
const textureLoader = new THREE.TextureLoader();
const leafTexture = textureLoader.load('path/to/leaf-texture.png');

// Create the material with alphaTest
const leafMaterial = new THREE.MeshStandardMaterial({
    map: leafTexture,
    alphaTest: 0.5, // Discards pixels with alpha less than 0.5
    side: THREE.DoubleSide, // Ensures leaves are visible from both sides
    transparent: false // Often set to false when using alphaTest for binary cutouts
});

// Apply to a mesh
const leafMesh = new THREE.Mesh(geometry, leafMaterial);

Choosing the Right alphaTest Value

The alphaTest property accepts a value between 0.0 and 1.0.

Performance and Transparency Considerations

Using alphaTest allows you to set transparent: false. When transparent is set to true, Three.js must sort objects from back to front before rendering, which is computationally expensive for scenes with thousands of leaves. By setting transparent: false and relying solely on alphaTest for binary “cutout” transparency, Three.js can render the leaves as opaque objects, drastically improving rendering performance and completely bypassing depth sorting issues.

If you modify the alphaTest value dynamically after the material has already been rendered in the scene, you must notify the renderer by setting the update flag:

leafMaterial.alphaTest = 0.6;
leafMaterial.needsUpdate = true;