Now that we know how to load external models and textures, the next crucial step is to bring them together by applying those textures to our 3D objects. This process involves creating a material and then assigning a texture to a specific property of that material. Textures are the visual 'skins' we wrap around our 3D geometry to give them color, detail, and realism.
In Three.js, the most common way to apply textures is by using a TextureLoader to load an image and then assigning that loaded texture to the map property of a material. Let's break down the typical workflow.
graph TD
A[Start] --> B{Load Texture Image};
B --> C[Create a Texture Object];
C --> D{Create a Material (e.g., MeshStandardMaterial)};
D --> E[Assign Texture to Material.map];
E --> F[Assign Material to Mesh];
F --> G[End];
First, you'll need an instance of TextureLoader. This object is responsible for loading image files and converting them into THREE.Texture objects that Three.js can understand and use.
const textureLoader = new THREE.TextureLoader();Next, you use the load() method of the TextureLoader to get your texture. This method takes the path to your image file as an argument. It's asynchronous, meaning it will load the image in the background without freezing your application. You provide a callback function that will be executed once the texture has loaded successfully. This callback receives the loaded THREE.Texture object as its argument.
let myTexture;
textureLoader.load(
'path/to/your/texture.jpg', // Specify the path to your texture image
(texture) => {
// This function is called when the texture is loaded successfully
myTexture = texture;
// You can now use myTexture
console.log('Texture loaded successfully!');
},
(xhr) => { // Optional: Progress callback
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
},
(error) => { // Optional: Error callback
console.error('An error happened:', error);
}
);Once you have your THREE.Texture object, you create a material. For most PBR (Physically Based Rendering) workflows, MeshStandardMaterial or MeshPhongMaterial are excellent choices. You then assign your loaded texture to the map property of this material. The map property is the primary diffuse texture, determining the base color and pattern of the surface.
const material = new THREE.MeshStandardMaterial({
map: myTexture // Assign the loaded texture here
});It's important to note that the material assignment should happen after the texture has loaded. If you try to assign myTexture before it's ready, it will be undefined, and your material won't have any texture applied. This is why the material creation is often placed inside the texture's load callback, or you might use flags and update the material later.
const textureLoader = new THREE.TextureLoader();
textureLoader.load(
'path/to/your/wood_texture.jpg',
(texture) => {
const material = new THREE.MeshStandardMaterial({
map: texture
});
// Assuming you have a loaded geometry (e.g., from a model loader)
// and a mesh variable created from it.
// mesh.material = material;
console.log('Material with texture applied!');
},
undefined, // No progress callback needed for this example
(error) => {
console.error('Error loading texture:', error);
}
);If you are loading a complete 3D model that already contains materials and textures (like a .gltf file), the textures are often applied automatically when the model is loaded. However, you can still access and modify these materials and their textures after loading if needed. This is common for swapping textures or adjusting material properties dynamically.