Appearance
Loading Textures
FreshUsing TextureLoader and useLoader
To load textures, use TextureLoader from three.js in combination with useLoader. Pass the location of the texture to get the map back.
js
const colorMap = useLoader(TextureLoader, 'PavingStones092_1K_Color.jpg')A small scene with a texture-mapped sphere:
jsx
import { Suspense } from 'react'
import { Canvas, useLoader } from '@react-three/fiber'
import { TextureLoader } from 'three'
function Scene() {
const colorMap = useLoader(TextureLoader, 'PavingStones092_1K_Color.jpg')
return (
<>
<ambientLight intensity={0.2} />
<directionalLight />
<mesh>
<sphereGeometry args={[1, 32, 32]} />
<meshStandardMaterial map={colorMap} />
</mesh>
</>
)
}
export default function App() {
return (
<Canvas>
<Suspense fallback={null}>
<Scene />
</Suspense>
</Canvas>
)
}Loading Multiple Textures at Once
The second argument can be an array — all maps will be returned and ready to use:
js
const [colorMap, displacementMap, normalMap, roughnessMap, aoMap] = useLoader(TextureLoader, [
'PavingStones092_1K_Color.jpg',
'PavingStones092_1K_Displacement.jpg',
'PavingStones092_1K_Normal.jpg',
'PavingStones092_1K_Roughness.jpg',
'PavingStones092_1K_AmbientOcclusion.jpg',
])Apply all maps to the material:
jsx
<meshStandardMaterial
map={colorMap}
displacementMap={displacementMap}
normalMap={normalMap}
roughnessMap={roughnessMap}
aoMap={aoMap}
/>TIP
The displacement will probably be too much. Setting displacementScale={0.2} will make it look better.
Final code:
jsx
function Scene() {
const [colorMap, displacementMap, normalMap, roughnessMap, aoMap] = useLoader(TextureLoader, [
'PavingStones092_1K_Color.jpg',
'PavingStones092_1K_Displacement.jpg',
'PavingStones092_1K_Normal.jpg',
'PavingStones092_1K_Roughness.jpg',
'PavingStones092_1K_AmbientOcclusion.jpg',
])
return (
<mesh>
{/* Width and height segments for displacementMap */}
<sphereGeometry args={[1, 100, 100]} />
<meshStandardMaterial
displacementScale={0.2}
map={colorMap}
displacementMap={displacementMap}
normalMap={normalMap}
roughnessMap={roughnessMap}
aoMap={aoMap}
/>
</mesh>
)
}Using useTexture
@react-three/drei exports useTexture which makes loading slightly easier — no need to import TextureLoader:
js
import { useTexture } from "@react-three/drei"
const [colorMap, displacementMap, normalMap, roughnessMap, aoMap] = useTexture([
'PavingStones092_1K_Color.jpg',
'PavingStones092_1K_Displacement.jpg',
'PavingStones092_1K_Normal.jpg',
'PavingStones092_1K_Roughness.jpg',
'PavingStones092_1K_AmbientOcclusion.jpg',
])Object Notation (Most Convenient)
Use object notation for clearer code:
jsx
const props = useTexture({
map: 'PavingStones092_1K_Color.jpg',
displacementMap: 'PavingStones092_1K_Displacement.jpg',
normalMap: 'PavingStones092_1K_Normal.jpg',
roughnessMap: 'PavingStones092_1K_Roughness.jpg',
aoMap: 'PavingStones092_1K_AmbientOcclusion.jpg',
})
return (
<mesh>
<sphereGeometry args={[1, 32, 32]} />
<meshStandardMaterial {...props} />
</mesh>
)Spreading the props object directly onto the material is the cleanest pattern. The keys match the material property names exactly.