Navigate

Search topics across all sections

GitHub
Lights

Environment Maps

Environment maps are panoramic images that wrap around your entire scene. They provide realistic reflections and ambient lighting that make PBR materials look stunning — especially metals and glossy surfaces.

You spend an hour crafting a perfect chrome sphere with metalness=1 and roughness=0, but it renders as a solid black ball. You try different colors, different positions, different cameras — still black. The chrome has nothing to reflect. Without an environment map, metallic surfaces are blind mirrors in a pitch-black void.

terminal
Metallic PBR material renders as pure black with no visible reflections.

Real-world

Have you ever seen a photographer place a shiny chrome ball in the middle of a room? They photograph the ball, and in its reflection you can see a complete 360-degree view of the entire room — walls, ceiling, windows, everything.

Environment maps do the exact same thing, but in reverse. Instead of capturing the world into a ball, you take a panoramic photo of the world and project it onto your objects.

Every shiny surface in your scene uses that panoramic image to figure out what it should be reflecting. A chrome faucet shows a blurry version of the room. A polished marble floor shows the ceiling. A car's paint reflects the sky. All from one single image wrapped around the scene.

What an Environment Map Does

An environment map serves two separate purposes. You can use it for one, the other, or both.

HDR Image

Panoramic photo of a scene

scene.environment

Lighting + reflections for PBR materials

scene.background

Visible backdrop behind all objects

Guided Walkthrough

Let us go from a black chrome sphere to a stunning reflective scene in three steps.

Step 1 — Add an environment map with a drei preset

step-1-preset.tsxTSX
import { Environment } from '@react-three/drei'

{/* One line — provides IBL to all PBR materials */}
<Environment preset="studio" />

The Environment component from drei handles all the HDR loading and processing for you. The "studio" preset gives you clean, neutral lighting perfect for product shots. Every PBR material in the scene automatically picks up the reflections.

Step 2 — Show it as a visible background too

step-2-background.tsxTSX
{/* background makes the HDR panorama visible */}
{/* backgroundBlurriness softens it so it does not compete */}
<Environment
  preset="sunset"
  background
  backgroundBlurriness={0.5}
/>

Adding the background prop makes the panoramic image visible behind your objects. The backgroundBlurriness prop softens it so your objects remain the focal point rather than the backdrop.

Step 3 — Control reflection strength per material

step-3-intensity.tsxTSX
{/* Strong reflections on chrome */}
<meshStandardMaterial
  metalness={1} roughness={0}
  envMapIntensity={1.5}
/>

{/* Subtle reflections on plastic */}
<meshStandardMaterial
  metalness={0} roughness={0.3}
  envMapIntensity={0.3}
/>

The envMapIntensity prop lets you control how much each material reflects the environment. Crank it up for chrome and mirrors, dial it down for matte surfaces that should not look too shiny.

What you just learned

Environment maps provide both ambient lighting (IBL) and reflections for PBR materials

scene.environment controls lighting; scene.background controls the visible backdrop — they are independent

HDR images are critical because they store brightness values beyond 1.0 for realistic specular highlights

envMapIntensity lets you fine-tune reflection strength per material

Question

If you use a studio HDR for scene.environment (lighting) but a sunset HDR for scene.background (backdrop), the reflections on your objects will show the studio, not the sunset. When would this mismatch actually be desirable? Think about product visualization.

Think about it...

You have a scene with an Environment preset providing lighting. You add a separate directional light for shadows. The objects look overly bright. What is the best way to balance them?

Try These Challenges

Put what you learned into practice. Try each challenge in the demo above using the Leva controls, then check the solution.

Try This!

Beginner

Set roughness to 1 — where did the reflections go?

Try This!

Beginner

Set metalness to 0 — it's plastic now

Try This!

Intermediate

Try 'night' preset — dark reflections

These are the patterns that trip up developers most often. Switch between Wrong and Fixed to compare the code side by side.

1
HDR panorama shows as the scene background when you only wanted lighting
Setting both environment and background to the same texture
Don't do this
env-vs-bg.tsxTSX
// This sets BOTH lighting AND visible background
<Environment preset="sunset" background />

// The HDR panorama is now the scene backdrop
// which may not match your design
scene.environment provides image-based lighting for PBR materials. scene.background is what appears behind all objects. You can use the same HDR for both, or use completely different images. Setting background when you only wanted lighting puts an unwanted panoramic backdrop in your scene.
2
Metallic surfaces appear completely black
No environment map for the metal to reflect
Don't do this
black-metal.tsxTSX
<meshStandardMaterial
  color="#ffffff"
  roughness={0}
  metalness={1}
/>
// No environment map = nothing to reflect = black
Metals get their visible color entirely from reflections. Unlike wood or plastic, metals have no diffuse scattering. If there is nothing to reflect — no environment map, no lights — the surface is pure black. Always provide an environment map when using metallic PBR materials.
3
GPU memory leak from unused source texture
Not disposing the original HDR after PMREM processing
Don't do this
pmrem-dispose.tsxTSX
rgbeLoader.load('/hdri/studio.hdr', (texture) => {
  const envMap = pmrem.fromEquirectangular(texture).texture;
  scene.environment = envMap;
  // Original HDR still in GPU memory — wasted!
});
PMREMGenerator creates a new prefiltered texture from the source HDR. After processing, the original HDR is no longer needed. Failing to dispose it leaves a large texture in GPU memory permanently. Always call dispose() on both the source and the generator.

Best Practices

Always use HDR over JPG for PBR

HDR environment maps store brightness values above 1.0, which create the specular highlights that make metallic and glossy surfaces look real. JPG panoramas look flat in comparison.

Separate environment from background

Use a studio HDR for clean lighting and a different texture or solid color for the backdrop. This gives you artistic control over both independently.

Dispose source textures after PMREM

If you manually load HDR files, always dispose the original texture and PMREM generator after processing. The processed output is all you need — keeping the source wastes GPU memory.

Use envMapIntensity for fine control

Adjust envMapIntensity per material to balance environment reflections against direct lights. Reduce it on matte surfaces to prevent them from looking overly reflective.