Course outline
drei Helpers
In one line
drei is a shelf of ready-made R3F parts: controls, environments, shadows, HTML labels, loaders. Each one is plain three.js underneath. Know what each adds to the scene, because some quietly add work to every frame.
Think of it like this
A kitchen gadget shop. A garlic press saves you time, and a food processor saves more. But the food processor takes space on the counter, needs cleaning, and uses power when it runs. A drei helper is a gadget: you should know what it puts in your scene before you buy it.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- helper
- A ready-made component from drei that wraps common three.js work.
- makeDefault
- An OrbitControls prop that saves the controls as
state.controls, the default for the scene. - baked
- Computed once and kept, instead of recomputed every frame.
frames={1}bakes a contact shadow. - render pass
- One complete draw of a scene or part of it. Each helper pass costs draw calls like a full render.
- preset
- A named setting that stands for files or values. drei's environment presets stand for HDR files on a server you do not control.
Step by step
01Ask what the helpers added
Inspect runs after 10 frames and prints what is in the scene. The crate holds a Group (from <Html>). The scene holds the crate and a Group (from <ContactShadows>).
02Look inside
The contact-shadow group holds a Mesh (the shadow plane) and an OrthographicCamera (the point of view that makes the shadow). OrbitControls is state.controls, and scene.environment is a texture.
03Count the draws
The second example puts the same crate in three Canvases and counts gl.render calls by wrapping the method. The three results are 30, 180 and 35.
04Decide
A configurator does not move its floor shadow: frames={1} is the right choice. A moving object needs the live shadow, at its price.
Try it yourself
- 1
Bake the shadow
In the second example, change
frames={1}toframes={10}. The third count rises from 35 to 80: ten draws of the shadow cost 5 extra passes each, plus 30 for the scene. - 2
Take Html away
In the first example, delete the
<Html>line. The crate holds no children, and the last line says<Html> put a real div in the page: false.
Code & diagrams
Loading the HDR file takes a moment, so wait for the printout. The helpers are ordinary scene objects and DOM nodes.
Console
Run the scene to see its console.Expected console output
THREE.Clock: This module has been deprecated. Please use THREE.Timer instead.
scene children: Mesh "crate", Group
inside the crate: Group
inside <ContactShadows>: Mesh, OrthographicCamera
<OrbitControls makeDefault>: OrbitControls | moves the default camera: true
<Environment>: scene.environment is a DataTexture | background: null
<Html> put a real div in the page: trueThree Canvases, so three Clock warnings. Counts are over 30 animation frames.
Console
Run the scene to see its console.Expected console output
THREE.Clock: This module has been deprecated. Please use THREE.Timer instead.
THREE.Clock: This module has been deprecated. Please use THREE.Timer instead.
THREE.Clock: This module has been deprecated. Please use THREE.Timer instead.
plain scene: gl.render was called 30 times in 30 animation frames
with <ContactShadows>: gl.render was called 180 times in 30 animation frames
with <ContactShadows frames={1}>: gl.render was called 35 times in 30 animation framesBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Use a preset without a network
Replace <Environment files="/data/3d/hdr/studio_small_08_1k.hdr" /> with <Environment preset="city" />.
Myth vs fact
Myth
A helper from drei is free.
Fact
It is code you do not read. Some add render passes, DOM nodes or downloads. Check the scene tree and renderer.info after adding one.
Myth
<Stage> is a safe shortcut.
Fact
It uses an environment preset that is downloaded from the internet. Build the same from Environment files, lights and ContactShadows when you need to work offline.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
<ContactShadows>defaultframesisInfinity, so it renders every frame.<AccumulativeShadows>and<BakeShadows>are the one-time versions for scenes that do not move. - ▸
OrbitControls takes events from the
events.connectedelement (the Canvas wrapper), notdocument, so two Canvases on one page do not fight for the mouse. - ▸
In a
frameloop="demand"Canvas, drei controls callinvalidate()for you when they change something. Your ownuseFrameanimation does not.
Remember this
- 1
The problem this solves: the same scene parts are written again and again (orbit controls, an HDR environment, a soft shadow). drei has tested versions. The risk is treating them as magic: when the scene is slow or wrong, you need to know what they really are.
- 2
**
<OrbitControls />.** The OrbitControls from Phase 7 (drei uses the copy inthree-stdlib), attached to the camera and the canvas.makeDefaultstores it asstate.controls, so other code can find it. It callscontrols.update()inside auseFramewith priority -1, so damping works. The first example confirms:controls.constructor.nameisOrbitControlsand it moves the default camera. - 3
**
<Environment files="..." />.** Loads an HDR image and setsscene.environment(andbackgroundif you ask). Withfilesand a path on your own site it loads the equirectangular HDR from Phase 6 (drei uses an RGBE loader fromthree-stdliband converts it to an environment map). Withpreset="city"it downloads the image from the internet at run time: with no internet (as in the course checker) it fails withCould not load potsdamer_platz_1k.hdr: Failed to fetch, and on your site it is a third-party dependency. Usefilesand ship the file. - 4
**
<ContactShadows />.** A soft shadow on the floor. It adds a group with a plane and an orthographic camera, and each frame it renders the scene from below into a texture and blurs it. That is extra render passes, which the second example counts. - 5
**
<Html>.** A real HTML<div>that follows a 3D point. It adds one DOM element and moves it with CSS every frame. Good for labels with real text (clickable, selectable, readable by screen readers); expensive in large numbers. - 6
**
<Bounds>,<Stage>,<Center>,<Text>.**Boundsfits the camera to its children (<Bounds fit>).Stageis a ready studio (environment preset, lights, contact shadow): its preset downloads from the internet, as above.Centerre-centres children on the origin.Textbuilds a mesh from glyphs of a font: give it your ownfontfile. - 7
The second render loop. Some helpers draw the scene again themselves (
ContactShadows,RenderTexture,View,Hud, post-processing). In the second example, a plain scene callsgl.render30 times in 30 frames. With<ContactShadows>it is called 180 times: the scene once, plus 5 more passes (depth, then two blurs, each blur twice). Withframes={1}the shadow is drawn once and baked: 35 calls. A scene that is slow only after adding a helper needs this check.
Explain it without notes
A scene runs at 60 fps; after adding <ContactShadows> it drops to 40. What do you check and what do you change?
Why might <Environment preset="sunset"> be a bad idea for production?
Practice
Write the JSX to orbit around a crate with a floor shadow that is drawn once, using your own HDR file.
Predict the gl.render count after 30 frames for a scene with <ContactShadows frames={2} />, then check.
Trade-offs
- ↔
Helpers save time and are tested, but each hides cost and sometimes a network call. For a product showroom keep the few you need, and replace a helper with plain three.js when it costs more than it saves.
Done when you can
Say what OrbitControls, Environment, ContactShadows and Html add
Find a helper's objects in the scene and its draws in the count
Bake a shadow that does not move
Avoid presets that download at run time