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