@react-three/drei 7.25.4 → 7.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +1661 -0
  2. package/core/ArcballControls.d.ts +1 -1
  3. package/core/Backdrop.js +3 -1
  4. package/core/BakeShadows.cjs.js +1 -1
  5. package/core/BakeShadows.js +3 -3
  6. package/core/Bounds.cjs.js +1 -1
  7. package/core/Bounds.js +2 -2
  8. package/core/DeviceOrientationControls.d.ts +1 -1
  9. package/core/Instances.cjs.js +1 -1
  10. package/core/Instances.js +1 -1
  11. package/core/Line.d.ts +1 -1
  12. package/core/MapControls.d.ts +1 -1
  13. package/core/MeshDistortMaterial.d.ts +1 -1
  14. package/core/MeshReflectorMaterial.cjs.js +1 -0
  15. package/core/MeshReflectorMaterial.d.ts +25 -0
  16. package/core/MeshReflectorMaterial.js +180 -0
  17. package/core/MeshWobbleMaterial.d.ts +1 -1
  18. package/core/OrbitControls.d.ts +1 -1
  19. package/core/PositionalAudio.d.ts +1 -1
  20. package/core/QuadraticBezierLine.js +5 -1
  21. package/core/Reflector.cjs.js +1 -1
  22. package/core/Reflector.d.ts +4 -5
  23. package/core/Reflector.js +34 -49
  24. package/core/SpotLight.d.ts +1 -1
  25. package/core/Text.d.ts +1 -1
  26. package/core/TrackballControls.d.ts +1 -1
  27. package/core/TransformControls.d.ts +1 -1
  28. package/core/index.cjs.js +1 -1
  29. package/core/index.d.ts +1 -0
  30. package/core/index.js +4 -1
  31. package/core/useDetectGPU.cjs.js +1 -1
  32. package/core/useDetectGPU.d.ts +1 -1
  33. package/core/useDetectGPU.js +1 -5
  34. package/index.cjs.js +1 -1
  35. package/index.js +2 -1
  36. package/materials/BlurPass.cjs.js +1 -0
  37. package/materials/BlurPass.d.ts +23 -0
  38. package/materials/BlurPass.js +75 -0
  39. package/materials/ConvolutionMaterial.cjs.js +1 -0
  40. package/materials/ConvolutionMaterial.d.ts +7 -0
  41. package/materials/ConvolutionMaterial.js +97 -0
  42. package/materials/MeshReflectorMaterial.cjs.js +1 -1
  43. package/materials/MeshReflectorMaterial.d.ts +10 -66
  44. package/materials/MeshReflectorMaterial.js +65 -313
  45. package/native/index.cjs.js +1 -1
  46. package/native/index.d.ts +0 -1
  47. package/native/index.js +4 -1
  48. package/package.json +3 -1
  49. package/web/PresentationControls.cjs.js +1 -0
  50. package/web/PresentationControls.d.ts +14 -0
  51. package/web/PresentationControls.js +73 -0
  52. package/web/ScrollControls.cjs.js +1 -1
  53. package/web/ScrollControls.js +1 -1
  54. package/web/index.cjs.js +1 -1
  55. package/web/index.d.ts +1 -1
  56. package/web/index.js +7 -1
  57. package/materials/index.cjs.js +0 -1
  58. package/materials/index.d.ts +0 -1
  59. package/materials/index.js +0 -2
package/README.md ADDED
@@ -0,0 +1,1661 @@
1
+ ![logo](logo.jpg)
2
+
3
+ [![Version](https://img.shields.io/npm/v/@react-three/drei?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/@react-three/drei)
4
+ [![Downloads](https://img.shields.io/npm/dt/@react-three/drei.svg?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/@react-three/drei)
5
+ [![Discord Shield](https://img.shields.io/discord/740090768164651008?style=flat&colorA=000000&colorB=000000&label=discord&logo=discord&logoColor=ffffff)](https://discord.gg/poimandres)
6
+
7
+ A growing collection of useful helpers and fully functional, ready-made abstractions for [react-three-fiber](https://github.com/pmndrs/react-three-fiber). If you make a component that is generic enough to be useful to others, think about making it available here through a PR!
8
+
9
+ ```bash
10
+ npm install @react-three/drei
11
+ ```
12
+
13
+ :point_right: this package is using the stand-alone [`three-stdlib`](https://github.com/pmndrs/three-stdlib) instead of [`three/examples/jsm`](https://github.com/mrdoob/three.js/tree/dev/examples/jsm). :point_left:
14
+
15
+ ### Basic usage:
16
+
17
+ ```jsx
18
+ import { PerspectiveCamera, PositionalAudio, ... } from '@react-three/drei'
19
+ ```
20
+
21
+ ### React-native:
22
+
23
+ ```jsx
24
+ import { PerspectiveCamera, PositionalAudio, ... } from '@react-three/drei/native'
25
+ ```
26
+
27
+ The `native` route of the library **does not** export `Html` or `Loader`. The default export of the library is `web` which **does** export `Html` and `Loader`.
28
+
29
+ ### Index
30
+
31
+ <table>
32
+ <tr>
33
+ <td valign="top">
34
+ <ul>
35
+ <li><a href="#cameras">Cameras</a></li>
36
+ <ul>
37
+ <li><a href="#perspectivecamera">PerspectiveCamera</a></li>
38
+ <li><a href="#orthographiccamera">OrthographicCamera</a></li>
39
+ <li><a href="#cubecamera">CubeCamera</a></li>
40
+ </ul>
41
+ <li><a href="#controls">Controls</a></li>
42
+ <ul>
43
+ <li><a href="#controls">Controls</a></li>
44
+ <li><a href="#controls">FlyControls</a></li>
45
+ <li><a href="#controls">MapControls</a></li>
46
+ <li><a href="#controls">DeviceOrientationControls</a></li>
47
+ <li><a href="#controls">TrackballControls</a></li>
48
+ <li><a href="#controls">ArcballControls</a></li>
49
+ <li><a href="#controls">PointerLockControls</a></li>
50
+ <li><a href="#controls">FirstPersonControls</a></li>
51
+ <li><a href="#transformcontrols">TransformControls</a></li>
52
+ <li><a href="#scrollcontrols">ScrollControls</a></li>
53
+ <li><a href="#presentationcontrols">PresentationControls</a></li>
54
+ </ul>
55
+ <li><a href="#abstractions">Abstractions</a></li>
56
+ <ul>
57
+ <li><a href="#image">Image</a></li>
58
+ <li><a href="#text">Text</a></li>
59
+ <li><a href="#line">Line</a></li>
60
+ <li><a href="#quadraticbezierline">QuadraticBezierLine</a></li>
61
+ <li><a href="#cubicbezierline">CubicBezierLine</a></li>
62
+ <li><a href="#positionalaudio">PositionalAudio</a></li>
63
+ <li><a href="#billboard">Billboard</a></li>
64
+ <li><a href="#gizmohelper">GizmoHelper</a></li>
65
+ <li><a href="#effects">Effects</a></li>
66
+ <li><a href="#gradienttexture">GradientTexture</a></li>
67
+ <li><a href="#useanimations">useAnimations</a></li>
68
+ </ul>
69
+ <li><a href="#shaders">Shaders</a></li>
70
+ <ul>
71
+ <li><a href="#meshreflectormaterial">MeshReflectorMaterial</a></li>
72
+ <li><a href="#meshwobblematerial">MeshWobbleMaterial</a></li>
73
+ <li><a href="#meshdistortmaterial">MeshDistortMaterial</a></li>
74
+ <li><a href="#pointmaterial">PointMaterial</a></li>
75
+ <li><a href="#softshadows">softShadows</a></li>
76
+ <li><a href="#shadermaterial">shaderMaterial</a></li>
77
+ </ul>
78
+ <li><a href="#modifiers">Modifiers</a></li>
79
+ <ul>
80
+ <li><a href="#curvemodifier">CurveModifier</a></li>
81
+ <li><a href="#useedgesplit">useEdgeSplit</a></li>
82
+ <li><a href="#usetessellation">useTessellation</a></li>
83
+ <li><a href="#usesimplification">useSimplification</a></li>
84
+ </ul>
85
+ </ul>
86
+ </td>
87
+ <td valign="top">
88
+ <ul>
89
+ <li><a href="#misc">Misc</a></li>
90
+ <ul>
91
+ <li><a href="#html">Html</a></li>
92
+ <li><a href="#cycleraycast">CycleRaycast</a></li>
93
+ <li><a href="#stats">Stats</a></li>
94
+ <li><a href="#usedepthbuffer">useDepthBuffer</a></li>
95
+ <li><a href="#usecontextbridge">useContextBridge</a></li>
96
+ <li><a href="#usefbo">useFBO</a></li>
97
+ <li><a href="#usecamera">useCamera</a></li>
98
+ <li><a href="#usedetectgpu">useDetectGPU</a></li>
99
+ <li><a href="#usehelper">useHelper</a></li>
100
+ <li><a href="#useaspect">useAspect</a></li>
101
+ <li><a href="#usecursor">useCursor</a></li>
102
+ <li><a href="#useintersect">useIntersect</a></li>
103
+ </ul>
104
+ <li><a href="#loading">Loaders</a></li>
105
+ <ul>
106
+ <li><a href="#loader">Loader</a></li>
107
+ <li><a href="#useprogress">useProgress</a></li>
108
+ <li><a href="#usegltf">useGLTF</a></li>
109
+ <li><a href="#usefbx">useFBX</a></li>
110
+ <li><a href="#usetexture">useTexture</a></li>
111
+ <li><a href="#usecubetexture">useCubeTexture</a></li>
112
+ </ul>
113
+ <li><a href="#performance">Performance</a></li>
114
+ <ul>
115
+ <li><a href="#instances">Instances</a></li>
116
+ <li><a href="#merged">Merged</a></li>
117
+ <li><a href="#points">Points</a></li>
118
+ <li><a href="#segments">Segments</a></li>
119
+ <li><a href="#detailed">Detailed</a></li>
120
+ <li><a href="#preload">Preload</a></li>
121
+ <li><a href="#bakeshadows">BakeShadows</a></li>
122
+ <li><a href="#meshbounds">meshBounds</a></li>
123
+ <li><a href="#adaptivedpr">AdaptiveDpr</a></li>
124
+ <li><a href="#adaptiveevents">AdaptiveEvents</a></li>
125
+ <li><a href="#usebvh">useBVH</a></li>
126
+ </ul>
127
+ </ul>
128
+ </td>
129
+ <td valign="top">
130
+ <ul>
131
+ <li><a href="#shapes">Shapes</a></li>
132
+ <ul>
133
+ <li><a href="#shapes">Plane</a></li>
134
+ <li><a href="#shapes">Box</a></li>
135
+ <li><a href="#shapes">Sphere</a></li>
136
+ <li><a href="#shapes">Circle</a></li>
137
+ <li><a href="#shapes">Cone</a></li>
138
+ <li><a href="#shapes">Cylinder</a></li>
139
+ <li><a href="#shapes">Tube</a></li>
140
+ <li><a href="#shapes">Torus</a></li>
141
+ <li><a href="#shapes">TorusKnot</a></li>
142
+ <li><a href="#shapes">Ring</a></li>
143
+ <li><a href="#shapes">Tetrahedron</a></li>
144
+ <li><a href="#shapes">Polyhedron</a></li>
145
+ <li><a href="#shapes">Icosahedron</a></li>
146
+ <li><a href="#shapes">Octahedron</a></li>
147
+ <li><a href="#shapes">Dodecahedron</a></li>
148
+ <li><a href="#shapes">Extrude</a></li>
149
+ <li><a href="#shapes">Lathe</a></li>
150
+ <li><a href="#shapes">Parametric</a></li>
151
+ <li><a href="#roundedbox">RoundedBox</a></li>
152
+ <li><a href="#screenquad">Screenquad</a></li>
153
+ </ul>
154
+ <li><a href="#staging">Staging</a></li>
155
+ <ul>
156
+ <li><a href="#center">Center</a></li>
157
+ <li><a href="#bounds">Bounds</a></li>
158
+ <li><a href="#camerashake">CameraShake</a></li>
159
+ <li><a href="#float">Float</a></li>
160
+ <li><a href="#stage">Stage</a></li>
161
+ <li><a href="#backdrop">Backdrop</a></li>
162
+ <li><a href="#environment">Environment</a></li>
163
+ <li><a href="#spotlight">SpotLight</a></li>
164
+ <li><a href="#shadow">Shadow</a></li>
165
+ <li><a href="#contactshadows">ContactShadows</a></li>
166
+ <li><a href="#sky">Sky</a></li>
167
+ <li><a href="#stars">Stars</a></li>
168
+ <li><a href="#cloud">Cloud</a></li>
169
+ <li><a href="#usematcaptexture">useMatcapTexture</a></li>
170
+ <li><a href="#usenormaltexture">useNormalTexture</a></li>
171
+ </ul>
172
+ </ul>
173
+ </td>
174
+ </tr>
175
+ </table>
176
+
177
+ # Cameras
178
+
179
+ #### PerspectiveCamera
180
+
181
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/camera-perspectivecamera--perspective-camera-scene-st)
182
+
183
+ A responsive [THREE.PerspectiveCamera](https://threejs.org/docs/index.html#api/en/cameras/PerspectiveCamera) that can set itself as the default.
184
+
185
+ ```jsx
186
+ <PerspectiveCamera makeDefault {...props} />
187
+ <mesh />
188
+ ```
189
+
190
+ You can also give it children, which will now occupy the same position as the camera and follow along as it moves.
191
+
192
+ ```jsx
193
+ <PerspectiveCamera makeDefault {...props}>
194
+ <mesh />
195
+ </PerspectiveCamera>
196
+ ```
197
+
198
+ You can also drive it manually, it won't be responsive and you have to calculate aspect ration yourself.
199
+
200
+ ```jsx
201
+ <PerspectiveCamera manual aspect={...} onUpdate={(c) => c.updateProjectionMatrix()}>
202
+ ```
203
+
204
+ #### OrthographicCamera
205
+
206
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/camera-orthographiccamera--orthographic-camera-scene-st)
207
+
208
+ A responsive [THREE.OrthographicCamera](https://threejs.org/docs/index.html#api/en/cameras/OrthographicCamera) that can set itself as the default.
209
+
210
+ ```jsx
211
+ <OrthographicCamera makeDefault {...props}>
212
+ <mesh />
213
+ </OrthographicCamera>
214
+ ```
215
+
216
+ #### CubeCamera
217
+
218
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/camera-cubecamera--default-story)
219
+
220
+ A [THREE.CubeCamera](https://threejs.org/docs/index.html#api/en/cameras/CubeCamera) that returns its texture as a render-prop. It makes children invisible while rendering to the internal buffer so that they are not included in the reflection.
221
+
222
+ Using the `frames` prop you can control if this camera renders indefinitively or statically (a given number of times).
223
+ If you have two static objects in the scene, make it `frames={2}` for instance, so that both objects get to "see" one another in the reflections, which takes multiple renders.
224
+ If you have moving objects, unset the prop and use a smaller `resolution` instead.
225
+
226
+ ```jsx
227
+ <CubeCamera resolution={256} frames={Infinity} fog={customFog} near={1} far={1000}>
228
+ {(texture) => (
229
+ <mesh>
230
+ <sphereGeometry />
231
+ <meshStandardMaterial envMap={texture} />
232
+ </mesh>
233
+ )}
234
+ </CubeCamera>
235
+ ```
236
+
237
+ # Controls
238
+
239
+ If available controls have damping enabled by default, they manage their own updates, remove themselves on unmount, are compatible with the `invalidateFrameloop` canvas-flag. They inherit all props from their underlying [THREE controls](https://github.com/mrdoob/three.js/tree/dev/examples/jsm/controls).
240
+
241
+ Some controls allow you to set `makeDefault`, similar to, for instance, PerspectiveCamera. This will set react-three-fiber's `controls` field in the root store. This can make it easier in situations where you want controls to be known and other parts of the app could respond to it. Some drei controls already take it into account, like CameraShake, Gizmo and TransformControls.
242
+
243
+ Drei currently exports OrbitControls [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/controls-orbitcontrols--orbit-controls-story), MapControls [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/controls-mapcontrols--map-controls-scene-st), TrackballControls, ArcballControls, FlyControls, DeviceOrientationControls, PointerLockControls [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/controls-pointerlockcontrols--pointer-lock-controls-scene-st), FirstPersonControls [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/controls-firstpersoncontrols--first-person-controls-story)
244
+
245
+ All controls react to the default camera. If you have a `<PerspectiveCamera makeDefault />` in your scene, they will control it. If you need to inject an imperative camera or one that isn't the default, use the `camera` prop: `<OrbitControls camera={MyCamera} />`.
246
+
247
+ PointerLockControls additionally supports a `selector` prop, which enables the binding of `click` event handlers for control activation to other elements than `document` (e.g. a 'Click here to play' button). All elements matching the `selector` prop will activate the controls.
248
+
249
+ # TransformControls
250
+
251
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/controls-transformcontrols--transform-controls-story)
252
+
253
+ An abstraction around [THREE.TransformControls](https://threejs.org/docs/index.html?q=transfor#examples/en/controls/TransformControls).
254
+
255
+ You can wrap objects which then receive a transform gizmo.
256
+
257
+ ```jsx
258
+ <TransformControls mode="translate">
259
+ <mesh />
260
+ </TransformControls>
261
+ ```
262
+
263
+ You could also reference the object which might make it easier to exchange the target. Now the object does not have to be part of the same sub-graph. References can be plain objects or React.MutableRefObjects.
264
+
265
+ ```jsx
266
+ <TransformControls object={mesh} mode="translate">
267
+ <mesh ref={mesh} />
268
+ ```
269
+
270
+ If you are using other controls (Orbit, Trackball, etc), you will notice how they interfere, dragging one will affect the other. Default-controls will temporarily be disabled automatically when the user is pulling on the transform gizmo.
271
+
272
+ ```jsx
273
+ <TransformControls mode="translate" />
274
+ <OrbitControls makeDefault />
275
+ ```
276
+
277
+ # ScrollControls
278
+
279
+ ![](https://img.shields.io/badge/-Dom only-red)
280
+
281
+ <p align="center">
282
+ <a href="https://codesandbox.io/s/l4klb"><img width="16%" src="https://codesandbox.io/api/v1/sandboxes/l4klb/screenshot.png" alt="Horizintal tiles"/></a>
283
+ <a href="https://codesandbox.io/s/4m0d0"><img width="16%" src="https://codesandbox.io/api/v1/sandboxes/4m0d0/screenshot.png" alt="M1 scroll"/></a>
284
+ <a href="https://codesandbox.io/s/gsm1y"><img width="16%" src="https://codesandbox.io/api/v1/sandboxes/gsm1y/screenshot.png" alt="useIntersect"/></a>
285
+ <a href="https://codesandbox.io/s/x8gvs"><img width="16%" src="https://codesandbox.io/api/v1/sandboxes/x8gvs/screenshot.png" alt="Infinite scroll"/></a>
286
+ <a href="https://codesandbox.io/s/yjhzv"><img width="16%" src="https://codesandbox.io/api/v1/sandboxes/yjhzv/screenshot.png" alt="Vertical scroll"/></a>
287
+ <a href="https://codesandbox.io/s/4jr4p"><img width="16%" src="https://codesandbox.io/api/v1/sandboxes/4jr4p/screenshot.png" alt="GLTF and useScroll"/></a>
288
+ </p>
289
+
290
+ Scroll controls create a HTML scroll container in front of the canvas. Everything you drop into the `<Scroll>` component will be affected.
291
+
292
+ You can listen and react to scroll with the `useScroll` hook which gives you useful data like the current scroll `offset`, `delta` and functions for range finding: `range`, `curve` and `visible`. The latter functions are especially useful if you want to react to the scroll offset, for instance if you wanted to fade things in and out if they are in or out of view.
293
+
294
+ ```jsx
295
+ <ScrollControls
296
+ pages={3} // Each page takes 100% of the height of the canvas
297
+ distance={1} // A factor that increases scroll bar travel (default: 1)
298
+ damping={4} // Friction, higher is faster (default: 4)
299
+ horizontal={false} // Can also scroll horizontally (default: false)
300
+ infinite={false} // Can also scroll infinitely (default: false)
301
+ >
302
+ {/* You can have components in here, they are not scrolled, but they can still
303
+ react to scroll by using useScroll! */}
304
+ <Scroll>
305
+ <Foo position={[0, 0, 0]} />
306
+ <Foo position={[0, viewport.height, 0]} />
307
+ <Foo position={[0, viewport.height * 1, 0]} />
308
+ </Scroll>
309
+ <Scroll html>
310
+ <h1>html in here (optional)</h1>
311
+ <h1 style={{ top: '100vh' }}>second page</h1>
312
+ <h1 style={{ top: '200vh' }}>third page</h1>
313
+ </Scroll>
314
+ </ScrollControls>
315
+
316
+ function Foo() {
317
+ const ref = useRef()
318
+ const data = useScroll()
319
+ useFrame(() => {
320
+ // data.offset = current scroll position, between 0 and 1, dampened
321
+ // data.delta = current delta, between 0 and 1, dampened
322
+
323
+ // Will be 0 when the scrollbar is at the starting position,
324
+ // then increase to 1 until 1 / 3 of the scroll distance is reached
325
+ const a = data.range(0, 1 / 3)
326
+ // Will start increasing when 1 / 3 of the scroll distance is reached,
327
+ // and reach 1 when it reaches 2 / 3rds.
328
+ const b = data.range(1 / 3, 1 / 3)
329
+ // Same as above but with a margin of 0.1 on both ends
330
+ const c = data.range(1 / 3, 1 / 3, 0.1)
331
+ // Will move between 0-1-0 for the selected range
332
+ const d = data.curve(1 / 3, 1 / 3)
333
+ // Same as above, but with a margin of 0.1 on both ends
334
+ const d = data.curve(1 / 3, 1 / 3, 0.1)
335
+ // Returns true if the offset is in range and false if it isn't
336
+ const e = data.visible(2 / 3, 1 / 3)
337
+ // The visible function can also receive a margin
338
+ const f = data.visible(2 / 3, 1 / 3, 0.1)
339
+ })
340
+ return <mesh ref={ref} {...props} />
341
+ ```
342
+
343
+ # PresentationControls
344
+
345
+ ![](https://img.shields.io/badge/-Dom only-red)
346
+
347
+ Semi-OrbitControls with spring-physics, polar zoom and snap-back, for presentational purposes. These controls do not turn the camera but will spin their contents. They will not suddenly come to rest when they reach limits like OrbitControls do, but rather smoothly anticipate stopping position.
348
+
349
+ ```jsx
350
+ <PresentationControls
351
+ global={false} // Spin globally or by dragging the model
352
+ snap={false} // Snap-back to center (can also be a spring config)
353
+ speed={1} // Speed factor
354
+ zoom={1} // Zoom factor when half the polar-max is reached
355
+ rotation={[0, 0, 0]} // Default rotation
356
+ polar={[0, Math.PI / 2]} // Vertical limits
357
+ azimuth={[-Infinity, Infinity]} // Horizontal limits
358
+ config = { mass: 1, tension: 170, friction: 26 } // Spring config
359
+ >
360
+ <mesh />
361
+ </PresentationControls>
362
+ ```
363
+
364
+ # Shapes
365
+
366
+ [Buffer-geometry](https://threejs.org/docs/index.html#api/en/core/BufferGeometry) short-cuts for Plane, Box, Sphere, Circle, Cone, Cylinder, Tube, Torus, TorusKnot, Ring, Tetrahedron, Polyhedron, Icosahedron, Octahedron, Dodecahedron, Extrude, Lathe, Parametric.
367
+
368
+ ```jsx
369
+ <Plane args={[2, 2]} />
370
+ <Sphere>
371
+ <meshBasicMaterial attach="material" color="hotpink" />
372
+ </Sphere>
373
+ ```
374
+
375
+ #### RoundedBox
376
+
377
+ A box buffer geometry with rounded corners, done with extrusion.
378
+
379
+ ```jsx
380
+ <RoundedBox args={[1, 1, 1]} radius={0.05} smoothness={4} {...meshProps}>
381
+ <meshPhongMaterial attach="material" color="#f3f3f3" wireframe />
382
+ </RoundedBox>
383
+ ```
384
+
385
+ #### ScreenQuad
386
+
387
+ ```jsx
388
+ <ScreenQuad>
389
+ <myMaterial />
390
+ </ScreenQuad>
391
+ ```
392
+
393
+ A triangle that fills the screen, ideal for full-screen fragment shader work (raymarching, postprocessing).
394
+ 👉 [Why a triangle?](https://www.cginternals.com/en/blog/2018-01-10-screen-aligned-quads-and-triangles.html)
395
+ 👉 [Use as a post processing mesh](https://medium.com/@luruke/simple-postprocessing-in-three-js-91936ecadfb7)
396
+
397
+ # Abstractions
398
+
399
+ #### Image
400
+
401
+ A shader-based image component with auto-cover (similar to css/background: cover).
402
+
403
+ ```jsx
404
+ function Foo() {
405
+ const ref = useRef()
406
+ useFrame(() => {
407
+ ref.current.material.zoom = ... // 1 and higher
408
+ ref.current.material.grayscale = ... // between 0 and 1
409
+ ref.current.material.color.set(...) // mix-in color
410
+ })
411
+ return <Image ref={ref} url="/file.jpg" />
412
+ ```
413
+
414
+ #### Text
415
+
416
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/abstractions-text--text-st)
417
+
418
+ Hi-quality text rendering w/ signed distance fields (SDF) and antialiasing, using [troika-3d-text](https://github.com/protectwise/troika/tree/master/packages/troika-3d-text). All of troikas props are valid!
419
+
420
+ ```jsx
421
+ <Text color="black" anchorX="center" anchorY="middle">
422
+ hello world!
423
+ </Text>
424
+ ```
425
+
426
+ #### Line
427
+
428
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/abstractions-line--basic-line)
429
+
430
+ Renders a THREE.Line2.
431
+
432
+ ```jsx
433
+ <Line
434
+ points={[[0, 0, 0], ...]} // Array of points
435
+ color="black" // Default
436
+ lineWidth={1} // In pixels (default)
437
+ dashed={false} // Default
438
+ vertexColors={[[0, 0, 0], ...]} // Optional array of RGB values for each point
439
+ {...lineProps} // All THREE.Line2 props are valid
440
+ {...materialProps} // All THREE.LineMaterial props are valid
441
+ />
442
+ ```
443
+
444
+ #### QuadraticBezierLine
445
+
446
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/abstractions-line--quadratic-bezier)
447
+
448
+ Renders a THREE.Line2 using THREE.QuadraticBezierCurve3 for interpolation.
449
+
450
+ ```jsx
451
+ <QuadraticBezierLine
452
+ start={[0, 0, 0]} // Starting point, can be an array or a vec3
453
+ end={[10, 0, 10]} // Ending point, can be an array or a vec3
454
+ mid={[5, 0, 5]} // Optional control point, can be an array or a vec3
455
+ color="black" // Default
456
+ lineWidth={1} // In pixels (default)
457
+ dashed={false} // Default
458
+ vertexColors={[[0, 0, 0], ...]} // Optional array of RGB values for each point
459
+ {...lineProps} // All THREE.Line2 props are valid
460
+ {...materialProps} // All THREE.LineMaterial props are valid
461
+ />
462
+ ```
463
+
464
+ You can also update the line runtime.
465
+
466
+ ```jsx
467
+ const ref = useRef()
468
+ useFrame((state) => {
469
+ ref.current.setPoints(
470
+ [0, 0, 0],
471
+ [10, 0, 0],
472
+ // [5, 0, 0] // Optional: mid-point
473
+ )
474
+ }, [])
475
+ return <QuadraticBezierLine ref={ref} />
476
+ }
477
+ ```
478
+
479
+ #### CubicBezierLine
480
+
481
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/abstractions-line--cubic-bezier)
482
+
483
+ Renders a THREE.Line2 using THREE.CubicBezierCurve3 for interpolation.
484
+
485
+ ```jsx
486
+ <CubicBezierLine
487
+ start={[0, 0, 0]} // Starting point
488
+ end={[10, 0, 10]} // Ending point
489
+ midA={[5, 0, 0]} // First control point
490
+ midB={[0, 0, 5]} // Second control point
491
+ color="black" // Default
492
+ lineWidth={1} // In pixels (default)
493
+ dashed={false} // Default
494
+ vertexColors={[[0, 0, 0], ...]} // Optional array of RGB values for each point
495
+ {...lineProps} // All THREE.Line2 props are valid
496
+ {...materialProps} // All THREE.LineMaterial props are valid
497
+ />
498
+ ```
499
+
500
+ #### PositionalAudio
501
+
502
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/abstractions-positionalaudio--positional-audio-scene-st) ![](https://img.shields.io/badge/-suspense-brightgreen)
503
+
504
+ A wrapper around [THREE.PositionalAudio](https://threejs.org/docs/index.html#api/en/audio/PositionalAudio). Add this to groups or meshes to tie them to a sound that plays when the camera comes near.
505
+
506
+ ```jsx
507
+ <PositionalAudio
508
+ url="/sound.mp3"
509
+ distance={1}
510
+ loop
511
+ {...props} // All THREE.PositionalAudio props are valid
512
+ />
513
+ ```
514
+
515
+ #### Billboard
516
+
517
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/abstractions-billboard--billboard-st)
518
+
519
+ Adds a `<group />` that always faces the camera.
520
+
521
+ ```jsx
522
+ <Billboard
523
+ follow={true}
524
+ lockX={false}
525
+ lockY={false}
526
+ lockZ={false} // Lock the rotation on the z axis (default=false)
527
+ >
528
+ <Text fontSize={1}>I'm a billboard</Text>
529
+ </Billboard>
530
+ ```
531
+
532
+ #### GizmoHelper
533
+
534
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/gizmos-gizmohelper--default-story)
535
+
536
+ Used by widgets that visualize and control camera position.
537
+
538
+ Two example gizmos are included: GizmoViewport and GizmoViewcube, and `useGizmoContext` makes it easy to create your own.
539
+
540
+ Make sure to set the `makeDefault` prop on your controls, in that case you do not have to define the onTarget and onUpdate props.
541
+
542
+ ```jsx
543
+ <GizmoHelper
544
+ alignment="bottom-right" // widget alignment within scene
545
+ margin={[80, 80]} // widget margins (X, Y)
546
+ onUpdate={/* called during camera animation */}
547
+ onTarget={/* return current camera target (e.g. from orbit controls) to center animation */}
548
+ renderPriority={/* use renderPriority to prevent the helper from disappearing if there is another useFrame(..., 1)*/}
549
+ >
550
+ <GizmoViewport axisColors={['red', 'green', 'blue']} labelColor="black" />
551
+ {/* alternative: <GizmoViewcube /> */}
552
+ </GizmoHelper>
553
+ ```
554
+
555
+ #### Effects
556
+
557
+ Abstraction around threes own [EffectComposer](https://threejs.org/docs/index.html#examples/en/postprocessing/EffectComposer).
558
+
559
+ ```jsx
560
+ <Effects multisamping={8} renderIndex={1} disableGamma={false} disableRenderPass={false}>
561
+ <lUTPass attachArray="passes" lut={texture3D} />
562
+ </Effects>
563
+ ```
564
+
565
+ #### GradientTexture
566
+
567
+ A declarative THREE.Texture which attaches to "map" by default. You can use this to create gradient backgrounds.
568
+
569
+ ```jsx
570
+ <mesh>
571
+ <planeGeometry />
572
+ <meshBasicMaterial depthWrite={false}>
573
+ <GradientTexture
574
+ stops={[0, 1]} // As many stops as you want
575
+ colors={['aquamarine', 'hotpink']} // Colors need to match the number of stops
576
+ size={1024} // Size is optional, default = 1024
577
+ />
578
+ </meshBasicMaterial>
579
+ </mesh>
580
+ ```
581
+
582
+ #### useAnimations
583
+
584
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/abstractions-useanimations--use-animations-st)
585
+
586
+ A hook that abstracts [AnimationMixer](https://threejs.org/docs/index.html#api/en/animation/AnimationMixer).
587
+
588
+ ```jsx
589
+ const { nodes, materials, animations } = useGLTF(url)
590
+ const { ref, mixer, names, actions, clips } = useAnimations(animations)
591
+ useEffect(() => {
592
+ actions?.jump.play()
593
+ })
594
+ return (
595
+ <mesh ref={ref} />
596
+ ```
597
+
598
+ The hook can also take a pre-existing root (which can be a plain object3d or a reference to one):
599
+
600
+ ```jsx
601
+ const { scene, animations } = useGLTF(url)
602
+ const { actions } = useAnimations(animations, scene)
603
+ return <primitive object={scene} />
604
+ ```
605
+
606
+ # Shaders
607
+
608
+ #### MeshReflectorMaterial
609
+
610
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/shaders-meshreflectormaterial--reflector-st)
611
+
612
+ Easily add reflections and/or blur to any mesh. It takes surface roughness into account for a more realistic effect. This material extends from [THREE.MeshStandardMaterial](https://threejs.org/docs/index.html?q=meshsta#api/en/materials/MeshStandardMaterial) and accepts all its props.
613
+
614
+ ```jsx
615
+ <mesh>
616
+ <planeGeometry />
617
+ <MeshReflectorMaterial
618
+ blur={[0, 0]} // Blur ground reflections (width, heigt), 0 skips blur
619
+ mixBlur={1.0} // How much blur mixes with surface roughness (default = 0), note that this can affect performance
620
+ mixStrength={0.5} // Strength of the reflections
621
+ resolution={256} // Off-buffer resolution, lower=faster, higher=better quality, slower
622
+ mirror={0.5} // Mirror environment, 0 = texture colors, 1 = pick up env colors
623
+ depthScale={1} // Scale the depth factor (0 = no depth, default = 0)
624
+ minDepthThreshold={0.9} // Lower edge for the depthTexture interpolation (default = 0)
625
+ maxDepthThreshold={1} // Upper edge for the depthTexture interpolation (default = 0)
626
+ depthToBlurRatioBias={0.25} // Adds a bias factor to the depthTexture before calculating the blur amount [blurFactor = blurTexture * (depthTexture + bias)]. It accepts values between 0 and 1, default is 0.25. An amount > 0 of bias makes sure that the blurTexture is not too sharp because of the multiplication with the depthTexture
627
+ distortion={0} // Amount of distortion based on the distortionMap texture
628
+ distortionMap={distortionTexture} // The red channel of this texture is used as the distortion map. Default is null
629
+ debug={0} /* Depending on the assigned value, one of the following channels is shown:
630
+ 0 = no debug
631
+ 1 = depth channel
632
+ 2 = base channel
633
+ 3 = distortion channel
634
+ 4 = lod channel (based on the roughness)
635
+ */
636
+ >
637
+ </mesh>
638
+ ```
639
+
640
+ #### MeshWobbleMaterial
641
+
642
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/shaders-meshwobblematerial--mesh-wobble-material-st)
643
+
644
+ This material makes your geometry wobble and wave around. It was taken from the [threejs-examples](https://threejs.org/examples/#webgl_materials_modified) and adapted into a self-contained material.
645
+
646
+ ```jsx
647
+ <mesh>
648
+ <boxBufferGeometry attach="geometry" />
649
+ <MeshWobbleMaterial attach="material" factor={1} speed={10} />
650
+ </mesh>
651
+ ```
652
+
653
+ #### MeshDistortMaterial
654
+
655
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/shaders-meshdistortmaterial--mesh-distort-material-st)
656
+
657
+ This material makes your geometry distort following simplex noise.
658
+
659
+ ```jsx
660
+ <mesh>
661
+ <boxBufferGeometry attach="geometry" />
662
+ <MeshDistortMaterial attach="material" distort={1} speed={10} />
663
+ </mesh>
664
+ ```
665
+
666
+ #### PointMaterial
667
+
668
+ An antialiased round dot that always keeps the same size.
669
+
670
+ ```jsx
671
+ <points>
672
+ <PointMaterial scale={20} />
673
+ </points>
674
+ ```
675
+
676
+ #### softShadows
677
+
678
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/shaders-softshadows--soft-shadows-st)
679
+
680
+ Injects [percent closer soft shadows (pcss)](https://threejs.org/examples/?q=pcss#webgl_shadowmap_pcss) into threes shader chunk.
681
+
682
+ ```jsx
683
+ softShadows({
684
+ frustum: 3.75,
685
+ size: 0.005,
686
+ near: 9.5,
687
+ samples: 17,
688
+ rings: 11, // Rings (default: 11) must be a int
689
+ })
690
+ ```
691
+
692
+ #### shaderMaterial
693
+
694
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/shaders-shadermaterial--shader-material-story)
695
+
696
+ Creates a THREE.ShaderMaterial for you with easier handling of uniforms, which are also automatically declared as setter/getters on the object.
697
+
698
+ ```jsx
699
+ import { extend } from 'react-three-fiber'
700
+ import glsl from 'babel-plugin-glsl/macro'
701
+
702
+ const ColorShiftMaterial = shaderMaterial(
703
+ { time: 0, color: new THREE.Color(0.2, 0.0, 0.1) },
704
+ // vertex shader
705
+ glsl`
706
+ varying vec2 vUv;
707
+ void main() {
708
+ vUv = uv;
709
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
710
+ }
711
+ `,
712
+ // fragment shader
713
+ glsl`
714
+ uniform float time;
715
+ uniform vec3 color;
716
+ varying vec2 vUv;
717
+ void main() {
718
+ gl_FragColor.rgba = vec4(0.5 + 0.3 * sin(vUv.yxx + time) + color, 1.0);
719
+ }
720
+ `
721
+ )
722
+
723
+ extend({ ColorShiftMaterial })
724
+
725
+ // in your component
726
+ <mesh>
727
+ <colorShiftMaterial attach="material" color="hotpink" time={1} />
728
+ </mesh>
729
+ ```
730
+
731
+ # Modifiers
732
+
733
+ #### CurveModifier
734
+
735
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/modifiers-curvemodifier)
736
+
737
+ Given a curve will replace the children of this component with a mesh that move along said curve calling the property `moveAlongCurve` on the passed ref. Uses [three's Curve Modifier](https://threejs.org/examples/?q=curve#webgl_modifier_curve)
738
+
739
+ ```jsx
740
+ const curveRef = useRef()
741
+
742
+ const curve = React.useMemo(() => new THREE.CatmullRomCurve3([...handlePos], true, 'centripetal'), [handlePos])
743
+
744
+ return (
745
+ <CurveModifier ref={curveRef} curve={curve}>
746
+ <mesh>
747
+ <boxBufferGeometry args={[10, 10]} />
748
+ </mesh>
749
+ </CurveModifier>
750
+ )
751
+ ```
752
+
753
+ #### useEdgeSplit
754
+
755
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/modifiers-useedgesplit)
756
+
757
+ This hook mutates a mesh geometry using [three's Edge Split modifier](https://threejs.org/examples/?q=modifier#webgl_modifier_edgesplit). The first parameter is the cut-off angle, and the second parameter is a `tryKeepNormals` flag (default `true`).
758
+
759
+ ```jsx
760
+ const meshRef = useEdgeSplit(Math.PI / 2)
761
+
762
+ return (
763
+ <mesh ref={meshRef}>
764
+ <boxBufferGeometry args={[10, 10]} />
765
+ </mesh>
766
+ )
767
+ ```
768
+
769
+ #### useSimplification
770
+
771
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/modifiers-usesimplification)
772
+
773
+ This hook mutates a mesh geometry using [three's Simplification modifier](https://threejs.org/examples/webgl_modifier_simplifier.html).
774
+
775
+ 👉 The simplification code is based on [this algorithm](http://www.melax.com/polychop/).
776
+
777
+ ```jsx
778
+ const meshRef = useSimplification(0.5)
779
+
780
+ return (
781
+ <mesh ref={meshRef}>
782
+ <octahedronBufferGeometry args={[2, 5]} />
783
+ </mesh>
784
+ )
785
+ ```
786
+
787
+ #### useTessellation
788
+
789
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/modifiers-usetessellation)
790
+
791
+ This hook mutates a mesh geometry using [three's Tessellation modifier](https://threejs.org/examples/?q=tess#webgl_modifier_tessellation). It will break-up faces withe edge longer than the maxEdgeLength parameter.
792
+
793
+ ```jsx
794
+ const meshRef = useTessellation(2, 8)
795
+
796
+ return (
797
+ <mesh ref={meshRef}>
798
+ <octahedronBufferGeometry args={[2, 2]} />
799
+ </mesh>
800
+ )
801
+ ```
802
+
803
+ # Misc
804
+
805
+ #### useContextBridge
806
+
807
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/misc-usecontextbridge--use-context-bridge-st)
808
+
809
+ Allows you to forward contexts provided above the `<Canvas />` to be consumed from within the `<Canvas />` normally
810
+
811
+ ```jsx
812
+ function SceneWrapper() {
813
+ // bridge any number of contexts
814
+ // Note: These contexts must be provided by something above this SceneWrapper component
815
+ // You cannot render the providers for these contexts inside this component
816
+ const ContextBridge = useContextBridge(ThemeContext, GreetingContext)
817
+ return (
818
+ <Canvas>
819
+ <ContextBridge>
820
+ <Scene />
821
+ </ContextBridge>
822
+ </Canvas>
823
+ )
824
+ }
825
+
826
+ function Scene() {
827
+ // we can now consume a context within the Canvas
828
+ const theme = React.useContext(ThemeContext)
829
+ const greeting = React.useContext(GreetingContext)
830
+ return (
831
+ //...
832
+ )
833
+ }
834
+ ```
835
+
836
+ #### Html
837
+
838
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-html--html-st) ![](https://img.shields.io/badge/-Dom only-red)
839
+
840
+ Allows you to tie HTML content to any object of your scene. It will be projected to the objects whereabouts automatically.
841
+
842
+ ```jsx
843
+ <Html
844
+ as='div' // Wrapping element (default: 'div')
845
+ prepend // Project content behind the canvas (default: false)
846
+ center // Adds a -50%/-50% css transform (default: false) [ignored in transform mode]
847
+ fullscreen // Aligns to the upper-left corner, fills the screen (default:false) [ignored in transform mode]
848
+ distanceFactor={10} // If set (default: undefined), children will be scaled by this factor, and also by distance to a PerspectiveCamera / zoom by a OrthographicCamera.
849
+ zIndexRange={[100, 0]} // Z-order range (default=[16777271, 0])
850
+ portal={domnodeRef} // Reference to target container (default=undefined)
851
+ transform // If true, applies matrix3d transformations (default=false)
852
+ sprite // Renders as sprite, but only in transform mode (default=false)
853
+ calculatePosition={(el: Object3D, camera: Camera, size: { width: number; height: number }) => number[]} // Override default positioning function. (default=undefined) [ignored in transform mode]
854
+ occlude={[ref]} // Can be true or a Ref<Object3D>[], true occludes the entire scene (default: undefined)
855
+ onOcclude={(visible) => null} // Callback when the visibility changes (default: undefined)
856
+ {...groupProps} // All THREE.Group props are valid
857
+ {...divProps} // All HTMLDivElement props are valid
858
+ >
859
+ <h1>hello</h1>
860
+ <p>world</p>
861
+ </Html>
862
+ ```
863
+
864
+ Html can hide behind geometry using the `occlude` prop.
865
+
866
+ ```jsx
867
+ // Raytrace the entire scene
868
+ <Html occlude />
869
+ // Raytrace only specific elements
870
+ <Html occlude={[ref1, ref2]} />
871
+ ```
872
+
873
+ When the Html object hides it sets the opacity prop on the innermost div. If you want to animate or control the transition yourself then you can use `onOcclude`.
874
+
875
+ ```jsx
876
+ const [hidden, set] = useState()
877
+
878
+ <Html
879
+ occlude
880
+ onOcclude={set}
881
+ style={{
882
+ transition: 'all 0.5s',
883
+ opacity: hidden ? 0 : 1,
884
+ transform: `scale(${hidden ? 0.5 : 1})`
885
+ }} />
886
+ ```
887
+
888
+ #### CycleRaycast
889
+
890
+ ![](https://img.shields.io/badge/-Dom only-red)
891
+
892
+ This component allows you to cycle through all objects underneath the cursor with optional visual feedback. This can be useful for non-trivial selection, CAD data, housing, everything that has layers. It does this by changing the raycasters filter function and then refreshing the raycaster.
893
+
894
+ For this to work properly your event handler have to call `event.stopPropagation()`, for instance in `onPointerOver` or `onClick`, only one element can be selective for cycling to make sense.
895
+
896
+ ```jsx
897
+ <CycleRaycast
898
+ preventDefault={true} // Call event.preventDefault() (default: true)
899
+ scroll={true} // Wheel events (default: true)
900
+ keyCode={9} // Keyboard events (default: 9 [Tab])
901
+ onChanged={(objects, cycle) => console.log(objects, cycle)} // Optional onChanged event
902
+ />
903
+ ```
904
+
905
+ #### Stats
906
+
907
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-stats--default-story)
908
+
909
+ Adds [stats](https://github.com/mrdoob/stats.js/) to document.body. It takes over the render-loop!
910
+
911
+ ```jsx
912
+ <Stats showPanel={0} className="stats" {...props} />
913
+ ```
914
+
915
+ You can choose to mount Stats to a different DOM Element - for example, for custom styling:
916
+
917
+ ```jsx
918
+ const node = useRef(document.createElement('div'))
919
+
920
+ useEffect(() => {
921
+ node.current.id = 'test'
922
+ document.body.appendChild(node.current)
923
+
924
+ return () => document.body.removeChild(node.current)
925
+ }, [])
926
+
927
+ return <Stats parent={parent} />
928
+ ```
929
+
930
+ #### useDepthBuffer
931
+
932
+ Renders the scene into a depth-buffer. Often effects depend on it and this allows you to render a single buffer and share it, which minimizes the performance impact. It returns the buffer's `depthTexture`.
933
+
934
+ Since this is a rather expensive effect you can limit the amount of frames it renders when your objects are static. For instance making it render only once by setting `frames: 1`.
935
+
936
+ ```jsx
937
+ const depthBuffer = useDepthBuffer({
938
+ size: 256, // Size of the FBO, 256 by default
939
+ frames: Infinity, // How many frames it renders, Infinity by default
940
+ })
941
+ return <SomethingThatNeedsADepthBuffer depthBuffer={depthBuffer} />
942
+ ```
943
+
944
+ #### useFBO
945
+
946
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-usefbo--use-fbo-st)
947
+
948
+ Creates a `THREE.WebGLRenderTarget` or `THREE.WebGLMultisampleRenderTarget`.
949
+
950
+ ```jsx
951
+ const target = useFBO({
952
+ multisample: true,
953
+ stencilBuffer: false,
954
+ })
955
+ ```
956
+
957
+ The rendertarget is automatically disposed when unmounted.
958
+
959
+ #### useCamera
960
+
961
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-usecamera--use-camera-st)
962
+
963
+ A hook for the rare case when you are using non-default cameras for heads-up-displays or portals, and you need events/raytracing to function properly (raycasting uses the default camera otherwise).
964
+
965
+ ```jsx
966
+ <mesh raycast={useCamera(customCamera)} />
967
+ ```
968
+
969
+ #### useHelper
970
+
971
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-usehelper--default-story)
972
+
973
+ A hook for a quick way to add helpers to existing nodes in the scene. It handles removal of the helper on unmount and auto-updates it by default.
974
+
975
+ ```jsx
976
+ const mesh = useRef()
977
+ useHelper(mesh, BoxHelper, 'cyan')
978
+
979
+ <mesh ref={mesh} ... />
980
+ ```
981
+
982
+ #### useDetectGPU
983
+
984
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/misc-usedetectgpu)
985
+
986
+ This hook uses [DetectGPU by @TimvanScherpenzeel](https://github.com/TimvanScherpenzeel/detect-gpu), wrapped into suspense, to determine what tier should be assigned to the user's GPU.
987
+
988
+ 👉 This hook CAN be used outside the react-three-fiber `Canvas`.
989
+
990
+ ```jsx
991
+ function App() {
992
+ const GPUTier = useDetectGPU()
993
+ // show a fallback for mobile or lowest tier GPUs
994
+ return (
995
+ {(GPUTier.tier === "0" || GPUTier.isMobile) ? <Fallback /> : <Canvas>...</Canvas>
996
+
997
+ <Suspense fallback={null}>
998
+ <App />
999
+ ```
1000
+
1001
+ #### useAspect
1002
+
1003
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-useaspect--default-story)
1004
+
1005
+ This hook calculates aspect ratios (for now only what in css would be `image-size: cover` is supported). You can use it to make an image fill the screen. It is responsive and adapts to viewport resize. Just give the hook the image bounds in pixels. It returns an array: `[width, height, 1]`.
1006
+
1007
+ ```jsx
1008
+ const scale = useAspect(
1009
+ 1024, // Pixel-width
1010
+ 512, // Pixel-height
1011
+ 1 // Optional scaling factor
1012
+ )
1013
+ return (
1014
+ <mesh scale={scale}>
1015
+ <planeBufferGeometry />
1016
+ <meshBasicMaterial map={imageTexture} />
1017
+ ```
1018
+
1019
+ #### useCursor
1020
+
1021
+ ![](https://img.shields.io/badge/-Dom only-red)
1022
+
1023
+ A small hook that sets the css body cursor according to the hover state of a mesh, so that you can give the use visual feedback when the mouse enters a shape. Arguments 1 and 2 determine the style, the defaults are: onPointerOver = 'pointer', onPointerOut = 'auto'.
1024
+
1025
+ ```jsx
1026
+ const [hovered, set] = useState()
1027
+ useCursor(hovered, /*'pointer', 'auto'*/)
1028
+ return (
1029
+ <mesh onPointerOver={() => set(true)} onPointerOut={() => set(false)}>
1030
+ ```
1031
+
1032
+ #### useIntersect
1033
+
1034
+ A very cheap frustum check that gives you a reference you can observe in order to know if the object has entered the view or is outside of it. This relies on [THREE.Object3D.onBeforeRender](https://threejs.org/docs/index.html?q=obj#api/en/core/Object3D.onBeforeRender) so it only works on objects that are effectively rendered, like meshes, lines, sprites. It won't work on groups, object3d's, bones, etc.
1035
+
1036
+ ```jsx
1037
+ const ref = useIntersect((visible) => console.log('object is visible', visible))
1038
+ return <mesh ref={ref} />
1039
+ ```
1040
+
1041
+ # Loading
1042
+
1043
+ #### Loader
1044
+
1045
+ ![](https://img.shields.io/badge/-Dom only-red)
1046
+
1047
+ A quick and easy loading overlay component that you can drop on top of your canvas. It's intended to "hide" the whole app, so if you have multiple suspense wrappers in your application, you should use multiple loaders. It will show an animated loadingbar and a percentage.
1048
+
1049
+ ```jsx
1050
+ <Canvas>
1051
+ <Suspense fallback={null}>
1052
+ <AsyncModels />
1053
+ </Suspense>
1054
+ </Canvas>
1055
+ <Loader />
1056
+ ```
1057
+
1058
+ You can override styles, too.
1059
+
1060
+ ```jsx
1061
+ <Loader
1062
+ containerStyles={...container} // Flex layout styles
1063
+ innerStyles={...inner} // Inner container styles
1064
+ barStyles={...bar} // Loading-bar styles
1065
+ dataStyles={...data} // Text styles
1066
+ dataInterpolation={(p) => `Loading ${p.toFixed(2)}%`} // Text
1067
+ initialState={(active) => active} // Initial black out state
1068
+ >
1069
+ ```
1070
+
1071
+ #### useProgress
1072
+
1073
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-useprogress--use-progress-scene-st)
1074
+
1075
+ A convenience hook that wraps `THREE.DefaultLoadingManager`'s progress status.
1076
+
1077
+ ```jsx
1078
+ function Loader() {
1079
+ const { active, progress, errors, item, loaded, total } = useProgress()
1080
+ return <Html center>{progress} % loaded</Html>
1081
+ }
1082
+
1083
+ return (
1084
+ <Suspense fallback={<Loader />}>
1085
+ <AsyncModels />
1086
+ </Suspense>
1087
+ )
1088
+ ```
1089
+
1090
+ If you don't want your progress component to re-render on all changes you can be specific as to what you need, for instance if the component is supposed to collect errors only. Look into [zustand](https://github.com/react-spring/zustand) for more info about selectors.
1091
+
1092
+ ```jsx
1093
+ const errors = useProgress((state) => state.errors)
1094
+ ```
1095
+
1096
+ 👉 Note that your loading component does not have to be a suspense fallback. You can use it anywhere, even in your dom tree, for instance for overlays.
1097
+
1098
+ #### useGLTF
1099
+
1100
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/loaders-gltf)
1101
+
1102
+ A convenience hook that uses `useLoader` and `GLTFLoader`, it defaults to CDN loaded draco binaries (`https://www.gstatic.com/draco/v1/decoders/`) which are only loaded for compressed models.
1103
+
1104
+ ```jsx
1105
+ useGLTF(url)
1106
+
1107
+ useGLTF(url, '/draco-gltf')
1108
+
1109
+ useGLTF.preload(url)
1110
+ ```
1111
+
1112
+ #### useFBX
1113
+
1114
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/loaders-fbx)
1115
+
1116
+ A convenience hook that uses `useLoader` and `FBXLoader`:
1117
+
1118
+ ```jsx
1119
+ useFBX(url)
1120
+
1121
+ function SuzanneFBX() {
1122
+ let fbx = useFBX('suzanne/suzanne.fbx')
1123
+ return <primitive object={fbx} dispose={null} />
1124
+ }
1125
+ ```
1126
+
1127
+ #### useTexture
1128
+
1129
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/loaders-texture)
1130
+
1131
+ A convenience hook that uses `useLoader` and `TextureLoader`
1132
+
1133
+ ```jsx
1134
+ const texture = useTexture(url)
1135
+ const [texture1, texture2] = useTexture([texture1, texture2])
1136
+ ```
1137
+
1138
+ You can also use key: url objects:
1139
+
1140
+ ```jsx
1141
+ const props = useTexture({
1142
+ metalnessMap: url1,
1143
+ map: url2,
1144
+ })
1145
+ return <meshStandardMaterial {...props} />
1146
+ ```
1147
+
1148
+ #### useCubeTexture
1149
+
1150
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/loaders-cubetexture)
1151
+
1152
+ A convenience hook that uses `useLoader` and `CubeTextureLoader`
1153
+
1154
+ ```jsx
1155
+ const envMap = useCubeTexture(['px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png'], { path: 'cube/' })
1156
+ ```
1157
+
1158
+ # Performance
1159
+
1160
+ #### Instances
1161
+
1162
+ A wrapper around [THREE.InstancedMesh](https://threejs.org/docs/index.html?q=instan#api/en/objects/InstancedMesh). This allows you to define hundreds of thousands of objects in a single draw call, but declaratively!
1163
+
1164
+ ```jsx
1165
+ <Instances
1166
+ limit={1000} // Optional: max amount of items (for calculating buffer size)
1167
+ range={1000} // Optional: draw-range
1168
+ >
1169
+ <boxGeometry />
1170
+ <meshStandardMaterial />
1171
+ <Instance
1172
+ color="red"
1173
+ scale={2}
1174
+ position={[1, 2, 3]}
1175
+ rotation={[Math.PI / 3, 0, 0]}
1176
+ onClick={onClick} ... />
1177
+ // As many as you want, make them conditional, mount/unmount them, lazy load them, etc ...
1178
+ </Instances>
1179
+ ```
1180
+
1181
+ You can nest Instances and use relative coordinates!
1182
+
1183
+ ```jsx
1184
+ <group position={[1, 2, 3]} rotation={[Math.PI / 2, 0, 0]}>
1185
+ <Instance />
1186
+ </group>
1187
+ ```
1188
+
1189
+ Instances can also receive non-instanced objects, for instance annotations!
1190
+
1191
+ ```jsx
1192
+ <Instance>
1193
+ <Html>hello from the dom</Html>
1194
+ </Instance>
1195
+ ```
1196
+
1197
+ You can define events on them!
1198
+
1199
+ ```jsx
1200
+ <Instance onClick={...} onPointerOver={...} />
1201
+ ```
1202
+
1203
+ #### Merged
1204
+
1205
+ This creates instances for existing meshes and allows you to use them cheaply in the same scene graph. Each type will cost you exactly one draw call, no matter how many you use. `meshes` has to be a collection of pre-existing THREE.Mesh objects.
1206
+
1207
+ ```jsx
1208
+ <Merged meshes={[box, sphere]}>
1209
+ {(Box, Sphere) => (
1210
+ <>
1211
+ <Box position={[-2, -2, 0]} color="red" />
1212
+ <Box position={[-3, -3, 0]} color="tomato" />
1213
+ <Sphere scale={0.7} position={[2, 1, 0]} color="green" />
1214
+ <Sphere scale={0.7} position={[3, 2, 0]} color="teal" />
1215
+ </>
1216
+ )}
1217
+ </Merged>
1218
+ ```
1219
+
1220
+ You may also use object notation, which is good for loaded models.
1221
+
1222
+ ```jsx
1223
+ function Model({ url }) {
1224
+ const { nodes } = useGLTF(url)
1225
+ return (
1226
+ <Merged meshes={nodes}>
1227
+ {({ Screw, Filter, Pipe }) => (
1228
+ <>
1229
+ <Screw />
1230
+ <Filter position={[1, 2, 3]} />
1231
+ <Pipe position={[4, 5, 6]} />
1232
+ </>
1233
+ )}
1234
+ </Merged>
1235
+ )
1236
+ }
1237
+ ```
1238
+
1239
+ #### Points
1240
+
1241
+ A wrapper around [THREE.Points](https://threejs.org/docs/index.html?q=points#api/en/objects/Points). It has the same api and properties as Instances.
1242
+
1243
+ ```jsx
1244
+ <Points
1245
+ limit={1000} // Optional: max amount of items (for calculating buffer size)
1246
+ range={1000} // Optional: draw-range
1247
+ >
1248
+ <pointsMaterial />
1249
+ <Point position={[1, 2, 3]} color="red" onClick={onClick} onPointerOver={onPointerOver} ... />
1250
+ // As many as you want, make them conditional, mount/unmount them, lazy load them, etc ...
1251
+ </Points>
1252
+ ```
1253
+
1254
+ If you have a material that supports vertex colors (like drei/PointMaterial) you can have individual colors!
1255
+
1256
+ ```jsx
1257
+ <Points>
1258
+ <PointMaterial />
1259
+ <Point color="hotpink" />
1260
+ ```
1261
+
1262
+ Otherwise use any material you like:
1263
+
1264
+ ```jsx
1265
+ <Points>
1266
+ <pointsMaterial vertexColors size={10} />
1267
+ ```
1268
+
1269
+ If you just want to use buffers for position, color and size, you can use the alternative API:
1270
+
1271
+ ```jsx
1272
+ <Points positions={positionsBuffer} colors={colorsBuffer} sizes={sizesBuffer}>
1273
+ <pointsMaterial />
1274
+ </Points>
1275
+ ```
1276
+
1277
+ #### Segments
1278
+
1279
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/performance-segments--many-segments)
1280
+
1281
+ A wrapper around [THREE.LineSegments](https://threejs.org/docs/#api/en/objects/LineSegments). This allows you to use thousands of segments under the same geometry.
1282
+
1283
+ ##### Prop based:
1284
+
1285
+ ```jsx
1286
+ <Segments limit={1000} lineWidth={1.0}>
1287
+ <Segment start={[0, 0, 0]} end={[0, 10, 0]} color="red" />
1288
+ <Segment start={[0, 0, 0]} end={[0, 10, 10]} color={[1, 0, 1]} />
1289
+ </Segments>
1290
+ ```
1291
+
1292
+ ##### Ref based (for fast updates):
1293
+
1294
+ ```jsx
1295
+ const ref = useRef()
1296
+
1297
+ // E.g. to change segment position each frame.
1298
+ useFrame(() => {
1299
+ ref.current.start.set(0,0,0)
1300
+ ref.current.end.set(10,10,0)
1301
+ ref.current.color.setRGB(0,0,0)
1302
+ })
1303
+ // ...
1304
+ <Segments
1305
+ limit={1000}
1306
+ lineWidth={1.0}
1307
+ >
1308
+ <Segment ref={ref} />
1309
+ </Segments>
1310
+ ```
1311
+
1312
+ #### Detailed
1313
+
1314
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/abstractions-detailed--detailed-st)
1315
+
1316
+ A wrapper around [THREE.LOD](https://threejs.org/docs/index.html#api/en/objects/LOD) (Level of detail).
1317
+
1318
+ ```jsx
1319
+ <Detailed distances={[0, 10, 20]} {...props}>
1320
+ <mesh geometry={highDetail} />
1321
+ <mesh geometry={mediumDetail} />
1322
+ <mesh geometry={lowDetail} />
1323
+ </Detailed>
1324
+ ```
1325
+
1326
+ #### Preload
1327
+
1328
+ The WebGLRenderer will compile materials only when they hit the frustrum, which can cause jank. This component precompiles the scene using [gl.compile](https://threejs.org/docs/index.html#api/en/renderers/WebGLRenderer.compile) which makes sure that your app is responsive from the get go.
1329
+
1330
+ By default gl.compile will only preload visible objects, if you supply the `all` prop, it will circumvent that. With the `scene` and `camera` props you could also use it in portals.
1331
+
1332
+ ```jsx
1333
+ <Canvas>
1334
+ <Suspense fallback={null}>
1335
+ <Model />
1336
+ <Preload all />
1337
+ ```
1338
+
1339
+ #### BakeShadows
1340
+
1341
+ Sets `gl.shadowMap.autoUpdate` to `false` while mounted and requests a single `gl.shadowMap.needsUpdate = true` afterwards. This freezes all shadow maps the moment this component comes in, which makes shadows performant again (with the downside that they are now static). Mount this component in lock-step with your models, for instance by dropping it into the same suspense boundary of a model that loads.
1342
+
1343
+ ```jsx
1344
+ <Canvas>
1345
+ <Suspense fallback={null}>
1346
+ <Model />
1347
+ <BakeShadows />
1348
+ ```
1349
+
1350
+ #### meshBounds
1351
+
1352
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-meshbounds--mesh-bounds-st)
1353
+
1354
+ A very fast, but often good-enough bounds-only raycast for meshes. You can use this if performance has precedence over pointer precision.
1355
+
1356
+ ```jsx
1357
+ <mesh raycast={meshBounds} />
1358
+ ```
1359
+
1360
+ #### AdaptiveDpr
1361
+
1362
+ Drop this component into your scene and it will cut the pixel-ratio on [regress](#) according to the canvases perrformance min/max settings. This allows you to temporarily reduce visuals for more performance, for instance when the camera moves (look into drei's controls `regress` flag). Optionally you can set the canvas to a pixelated filter, which would be even faster.
1363
+
1364
+ ```jsx
1365
+ <AdaptiveDpr pixelated />
1366
+ ```
1367
+
1368
+ #### AdaptiveEvents
1369
+
1370
+ Drop this component into your scene and it will switch off the raycaster while the system is in regress.
1371
+
1372
+ ```jsx
1373
+ <AdaptiveEvents />
1374
+ ```
1375
+
1376
+ #### useBVH
1377
+
1378
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/performance-usebvh--default-story)
1379
+
1380
+ A hook to speed up the default raycasting by using the [BVH Implementation by @gkjohnnson](https://github.com/gkjohnson/three-mesh-bvh).
1381
+
1382
+ ```jsx
1383
+ const mesh = useRef()
1384
+ useBVH(mesh)
1385
+
1386
+ <mesh ref={mesh} ... />
1387
+ ```
1388
+
1389
+ # Staging
1390
+
1391
+ #### Center
1392
+
1393
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-center--default-story)
1394
+
1395
+ Calculates a boundary box and centers its children accordingly. `alignTop` makes adjusts it so that it's sits flush on y=0.
1396
+
1397
+ ```jsx
1398
+ <Center alignTop>
1399
+ <mesh />
1400
+ </Center>
1401
+ ```
1402
+
1403
+ #### Bounds
1404
+
1405
+ Calculates a boundary box and centers the camera accordingly. If you are using controls, make sure to pass them the `makeDefault` prop. `fit` fits the current view on first render. `clip` sets the cameras near/far planes.
1406
+
1407
+ ```jsx
1408
+ <Bounds fit clip damping={6} margin={1.2}>
1409
+ <mesh />
1410
+ </Bounds>
1411
+ ```
1412
+
1413
+ The Bounds component also acts as a context provider, use the `useBounds` hook to refresh the bounds, fit the camera, clip near/far planes or focus objects. `refresh(object?: THREE.Object3D | THREE.Box3)` will recalculate bounds, since this can be expensive only call it when you know the view has changed. `clip` sets the cameras near/far planes. `fit` zooms and centers the view.
1414
+
1415
+ ```jsx
1416
+ function Foo() {
1417
+ const bounds = useBounds()
1418
+ useEffect(() => {
1419
+ // Calculate scene bounds
1420
+ bounds.refresh().clip().fit()
1421
+ // Or, focus a specific object or box3
1422
+ // bounds.refresh(ref.current).clip().fit()
1423
+ // bounds.refresh(new THREE.Box3()).clip().fit()
1424
+
1425
+ <Bounds>
1426
+ <Foo />
1427
+ ```
1428
+
1429
+ #### CameraShake
1430
+
1431
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/camera-camerashake--camera-shake-st)
1432
+
1433
+ A component for applying a configurable camera shake effect. Currently only supports rotational camera shake. Pass a ref to recieve the `ShakeController` API.
1434
+
1435
+ If you use shake in combination with controls make sure to set the `makeDefault` prop on your controls, in that case you do not have to pass them via the `controls` prop.
1436
+
1437
+ ```js
1438
+ const config = {
1439
+ maxYaw: 0.1, // Max amount camera can yaw in either direction
1440
+ maxPitch: 0.1, // Max amount camera can pitch in either direction
1441
+ maxRoll: 0.1, // Max amount camera can roll in either direction
1442
+ yawFrequency: 0.1, // Frequency of the the yaw rotation
1443
+ pitchFrequency: 0.1, // Frequency of the pitch rotation
1444
+ rollFrequency: 0.1, // Frequency of the roll rotation
1445
+ intensity: 1, // initial intensity of the shake
1446
+ decay: false, // should the intensity decay over time
1447
+ decayRate: 0.65, // if decay = true this is the rate at which intensity will reduce at
1448
+ controls: undefined, // if using orbit controls, pass a ref here so we can update the rotation
1449
+ }
1450
+
1451
+ ;<CameraShake {...config} />
1452
+ ```
1453
+
1454
+ ```ts
1455
+ interface ShakeController {
1456
+ getIntensity: () => number
1457
+ setIntensity: (val: number) => void
1458
+ }
1459
+ ```
1460
+
1461
+ #### Float
1462
+
1463
+ This component makes its contents float or hover.
1464
+
1465
+ ```js
1466
+ <Float
1467
+ speed={1} // Animation speed, defaults to 1
1468
+ rotationIntensity={1} // XYZ rotation intensity, defaults to 1
1469
+ floatIntensity={1} // Up/down float intensity, defaults to 1
1470
+ >
1471
+ <mesh />
1472
+ </Float>
1473
+ ```
1474
+
1475
+ #### Stage
1476
+
1477
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/prototyping-stage--stage-st)
1478
+
1479
+ Creates a "stage" with proper studio lighting, content centered and planar, shadows and ground-contact shadows.
1480
+
1481
+ Make sure to set the `makeDefault` prop on your controls, in that case you do not need to provide `controls` via prop.
1482
+
1483
+ ```jsx
1484
+ <Stage contactShadow shadows adjustCamera intensity={1} environment="city" preset="rembrandt" controls={controlsRef}>
1485
+ <mesh />
1486
+ </Stage>
1487
+ ```
1488
+
1489
+ #### Backdrop
1490
+
1491
+ A curved plane, like a studio backdrop. This is for presentational purposes, to break up light and shadows more interestingly.
1492
+
1493
+ ```jsx
1494
+ <Backdrop
1495
+ floor={0.25} // Stretches the floor segment, 0.25 by default
1496
+ segments={20} // Mesh-resolution, 20 by default
1497
+ >
1498
+ <meshStandardMaterial color="#353540" />
1499
+ </Backdrop>
1500
+ ```
1501
+
1502
+ #### Shadow
1503
+
1504
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-shadow--shadow-st)
1505
+
1506
+ A cheap canvas-texture-based circular gradient.
1507
+
1508
+ ```jsx
1509
+ <Shadow
1510
+ color="black"
1511
+ colorStop={0}
1512
+ opacity={0.5}
1513
+ fog={false} // Reacts to fog (default=false)
1514
+ />
1515
+ ```
1516
+
1517
+ #### ContactShadows
1518
+
1519
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/shaders-contactshadows--contact-shadow-st)
1520
+
1521
+ A [contact shadow](https://threejs.org/examples/?q=con#webgl_shadow_contact) implementation, facing upwards (positive Y) by default. `scale` can be a positive number or a 2D array `[x: number, y: number]`.
1522
+
1523
+ ```jsx
1524
+ <ContactShadows opacity={1} scale={10} blur={1} far={10} resolution={256} />
1525
+ ```
1526
+
1527
+ Since this is a rather expensive effect you can limit the amount of frames it renders when your objects are static. For instance making it render only once:
1528
+
1529
+ ```jsx
1530
+ <ContactShadows frames={1} />
1531
+ ```
1532
+
1533
+ #### SpotLight
1534
+
1535
+ A Volumetric spotlight.
1536
+
1537
+ ```jsx
1538
+ <SpotLight
1539
+ distance={5}
1540
+ angle={0.15}
1541
+ attenuation={5}
1542
+ anglePower={5} // Diffuse-cone anglePower (default: 5)
1543
+ />
1544
+ ```
1545
+
1546
+ Optionally you can provide a depth-buffer which converts the spotlight into a soft particle.
1547
+
1548
+ ```jsx
1549
+ function Foo() {
1550
+ const depthBuffer = useDepthBuffer()
1551
+ return <SpotLight depthBuffer={depthBuffer} />
1552
+ ```
1553
+
1554
+ #### Environment
1555
+
1556
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/abstractions-environment--environment-st)
1557
+
1558
+ Sets up a global cubemap, which affects the default `scene.environment`, and optionally `scene.background`, unless a custom scene has been passed. A selection of [presets](src/helpers/environment-assets.ts) from [HDRI Haven](https://hdrihaven.com/) are available for convenience. If you pass an array of files it will use THREE.CubeTextureLoader.
1559
+
1560
+ ```jsx
1561
+ <Environment
1562
+ background={false}
1563
+ files={['px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png']}
1564
+ path="/"
1565
+ preset={null}
1566
+ scene={undefined} // adds the ability to pass a custom THREE.Scene
1567
+ />
1568
+ ```
1569
+
1570
+ If you provide a single string it will use THREE.RGBELoader.
1571
+
1572
+ ```jsx
1573
+ <Environment files="file.hdr" />
1574
+ ```
1575
+
1576
+ #### Sky
1577
+
1578
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/shaders-sky--sky-st)
1579
+
1580
+ Adds a [sky](https://threejs.org/examples/webgl_shaders_sky.html) to your scene.
1581
+
1582
+ ```jsx
1583
+ <Sky distance={450000} sunPosition={[0, 1, 0]} inclination={0} azimuth={0.25} {...props} />
1584
+ ```
1585
+
1586
+ #### Stars
1587
+
1588
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/shaders-stars--stars-st)
1589
+
1590
+ Adds a blinking shader-based starfield to your scene.
1591
+
1592
+ ```jsx
1593
+ <Stars radius={100} depth={50} count={5000} factor={4} saturation={0} fade />
1594
+ ```
1595
+
1596
+ #### Cloud
1597
+
1598
+ Particle based cloud.
1599
+
1600
+ ```jsx
1601
+ <Cloud
1602
+ opacity={0.5}
1603
+ speed={0.4} // Rotation speed
1604
+ width={10} // Width of the full cloud
1605
+ depth={1.5} // Z-dir depth
1606
+ segments={20} // Number of particles
1607
+ />
1608
+ ```
1609
+
1610
+ #### useMatcapTexture
1611
+
1612
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/prototyping-usematcaptexture) ![](https://img.shields.io/badge/-suspense-brightgreen)
1613
+
1614
+ Loads matcap textures from this repository: https://github.com/emmelleppi/matcaps
1615
+
1616
+ (It is a fork of this repository: https://github.com/nidorx/matcaps)
1617
+
1618
+ ```jsx
1619
+ const [matcap, url] = useMatcapTexture(
1620
+ 0, // index of the matcap texture https://github.com/emmelleppi/matcaps/blob/master/matcap-list.json
1621
+ 1024 // size of the texture ( 64, 128, 256, 512, 1024 )
1622
+ )
1623
+
1624
+ return (
1625
+ ...
1626
+ <meshMatcapMaterial matcap={matcap} />
1627
+ ...
1628
+ )
1629
+ ```
1630
+
1631
+ 👉 You can also use the exact name of the matcap texture, like so:
1632
+
1633
+ ```jsx
1634
+ const [matcap] = useMatcapTexture('3E2335_D36A1B_8E4A2E_2842A5')
1635
+ ```
1636
+
1637
+ 👉 Use the `url` to download the texture when you are ready for production!
1638
+
1639
+ #### useNormalTexture
1640
+
1641
+ [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/prototyping-usenormaltexture) ![](https://img.shields.io/badge/-suspense-brightgreen)
1642
+
1643
+ Loads normal textures from this repository: https://github.com/emmelleppi/normal-maps
1644
+
1645
+ ```jsx
1646
+ const [normalMap, url] = useNormalTexture(
1647
+ 1, // index of the normal texture - https://github.com/emmelleppi/normal-maps/blob/master/normals.json
1648
+ // second argument is texture attributes
1649
+ {
1650
+ offset: [0, 0],
1651
+ repeat: [normRepeat, normRepeat],
1652
+ anisotropy: 8
1653
+ }
1654
+ )
1655
+
1656
+ return (
1657
+ ...
1658
+ <meshStandardMaterial normalMap={normalMap} />
1659
+ ...
1660
+ )
1661
+ ```