Three.js Material Transparency and Opacity Guide
Achieving realistic transparency in Three.js requires more than just adjusting a single opacity value. This article provides a straightforward guide on how to correctly configure transparency and opacity on Three.js materials, covering the essential properties, handling depth sorting issues, and implementing best practices for flawless 3D rendering.
The Core Properties: Transparent and Opacity
To enable transparency on any Three.js material (such as
MeshBasicMaterial, MeshStandardMaterial, or
MeshPhongMaterial), you must configure two key properties:
transparent and opacity.
By default, materials are fully opaque to optimize rendering
performance. To make an object transparent, you must explicitly set
transparent to true. Once enabled, you can
control the level of transparency using the opacity
property, which accepts a float value between 0.0 (fully
invisible) and 1.0 (fully opaque).
Here is the standard implementation:
import * as THREE from 'three';
// Create a transparent material
const material = new THREE.MeshStandardMaterial({
color: 0x00ff00,
transparent: true, // Must be set to true
opacity: 0.5 // Value between 0.0 and 1.0
});
// Apply to a mesh
const geometry = new THREE.BoxGeometry(1, 1, 1);
const mesh = new THREE.Mesh(geometry, material);Resolving Depth and Sorting Issues
A common issue when working with transparent materials in WebGL is “depth fighting” or sorting artifacts, where objects behind a transparent surface are incorrectly hidden or clipped. Three.js renders transparent objects from back to front, but complex scenes can confuse the depth buffer.
To fix these visual artifacts, you can adjust how the material interacts with the depth buffer using the following properties:
1. Depth Write
(depthWrite)
Setting depthWrite to false prevents the
transparent material from writing to the depth buffer. This ensures that
objects rendered behind the transparent material are still drawn
correctly.
const glassMaterial = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
transparent: true,
opacity: 0.3,
depthWrite: false // Prevents clipping of objects behind this material
});2. Depth Test
(depthTest)
If you want an object to be visible regardless of what is in front of
it (for example, a UI overlay or helper gizmo), you can disable
depthTest.
material.depthTest = false;3. Render Order
(renderOrder)
For scenes with multiple overlapping transparent meshes, you can
manually define the rendering sequence using the
renderOrder property on the Mesh objects. Lower numbers
render first, and higher numbers render on top.
backgroundMesh.renderOrder = 0;
foregroundMesh.renderOrder = 1;Textured Transparency with Alpha Maps
If you want to apply transparency based on an image texture (like a
leaf or a chain-link fence), use an alphaMap combined with
alphaTest.
alphaMap: A grayscale texture where black represents fully transparent areas and white represents fully opaque areas.alphaTest: A threshold value. Pixels with an alpha value below this threshold will not be rendered at all, which eliminates depth sorting issues for cut-out textures.
const textureLoader = new THREE.TextureLoader();
const alphaTexture = textureLoader.load('path/to/alpha-map.png');
const cutoutMaterial = new THREE.MeshStandardMaterial({
color: 0xffffff,
alphaMap: alphaTexture,
transparent: true,
alphaTest: 0.5 // Discards pixels with opacity below 0.5
});By correctly combining transparent,
opacity, and depth buffer configurations, you can achieve
clean, artifact-free transparency in your Three.js projects.