@lark-apaas/coding-steering 0.1.3 → 0.1.4
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.
- package/package.json +8 -13
- package/steering/vite-react/skills/react-three-fiber/SKILL.md +214 -0
- package/steering/vite-react/skills/react-three-fiber/references/animation.md +1001 -0
- package/steering/vite-react/skills/react-three-fiber/references/fundamentals.md +877 -0
- package/steering/vite-react/skills/react-three-fiber/references/geometry.md +717 -0
- package/steering/vite-react/skills/react-three-fiber/references/interaction.md +880 -0
- package/steering/vite-react/skills/react-three-fiber/references/lighting.md +668 -0
- package/steering/vite-react/skills/react-three-fiber/references/loaders.md +607 -0
- package/steering/vite-react/skills/react-three-fiber/references/materials.md +601 -0
- package/steering/vite-react/skills/react-three-fiber/references/physics.md +820 -0
- package/steering/vite-react/skills/react-three-fiber/references/postprocessing.md +754 -0
- package/steering/vite-react/skills/react-three-fiber/references/shaders.md +874 -0
- package/steering/vite-react/skills/react-three-fiber/references/textures.md +635 -0
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
# React Three Fiber Lighting
|
|
2
|
+
|
|
3
|
+
## Quick Start
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Canvas } from '@react-three/fiber'
|
|
7
|
+
|
|
8
|
+
function Scene() {
|
|
9
|
+
return (
|
|
10
|
+
<Canvas shadows>
|
|
11
|
+
{/* Ambient fill */}
|
|
12
|
+
<ambientLight intensity={0.5} />
|
|
13
|
+
|
|
14
|
+
{/* Main light with shadows */}
|
|
15
|
+
<directionalLight
|
|
16
|
+
position={[5, 5, 5]}
|
|
17
|
+
intensity={1}
|
|
18
|
+
castShadow
|
|
19
|
+
shadow-mapSize={[2048, 2048]}
|
|
20
|
+
/>
|
|
21
|
+
|
|
22
|
+
{/* Objects */}
|
|
23
|
+
<mesh castShadow receiveShadow>
|
|
24
|
+
<boxGeometry />
|
|
25
|
+
<meshStandardMaterial color="orange" />
|
|
26
|
+
</mesh>
|
|
27
|
+
|
|
28
|
+
{/* Ground */}
|
|
29
|
+
<mesh receiveShadow rotation={[-Math.PI / 2, 0, 0]} position={[0, -0.5, 0]}>
|
|
30
|
+
<planeGeometry args={[10, 10]} />
|
|
31
|
+
<meshStandardMaterial color="#888" />
|
|
32
|
+
</mesh>
|
|
33
|
+
</Canvas>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Light Types Overview
|
|
39
|
+
|
|
40
|
+
| Light | Description | Shadow Support | Cost |
|
|
41
|
+
|-------|-------------|----------------|------|
|
|
42
|
+
| ambientLight | Uniform everywhere | No | Very Low |
|
|
43
|
+
| hemisphereLight | Sky/ground gradient | No | Very Low |
|
|
44
|
+
| directionalLight | Parallel rays (sun) | Yes | Low |
|
|
45
|
+
| pointLight | Omnidirectional (bulb) | Yes | Medium |
|
|
46
|
+
| spotLight | Cone-shaped | Yes | Medium |
|
|
47
|
+
| rectAreaLight | Area light (window) | No* | High |
|
|
48
|
+
|
|
49
|
+
## ambientLight
|
|
50
|
+
|
|
51
|
+
Illuminates all objects equally. No direction, no shadows.
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
<ambientLight
|
|
55
|
+
color="#ffffff" // or color={new THREE.Color('#ffffff')}
|
|
56
|
+
intensity={0.5}
|
|
57
|
+
/>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## hemisphereLight
|
|
61
|
+
|
|
62
|
+
Gradient from sky to ground. Good for outdoor scenes.
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
<hemisphereLight
|
|
66
|
+
color="#87ceeb" // Sky color
|
|
67
|
+
groundColor="#8b4513" // Ground color
|
|
68
|
+
intensity={0.6}
|
|
69
|
+
position={[0, 50, 0]}
|
|
70
|
+
/>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## directionalLight
|
|
74
|
+
|
|
75
|
+
Parallel light rays. Simulates distant light (sun).
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
<directionalLight
|
|
79
|
+
color="#ffffff"
|
|
80
|
+
intensity={1}
|
|
81
|
+
position={[5, 10, 5]}
|
|
82
|
+
|
|
83
|
+
// Shadow configuration
|
|
84
|
+
castShadow
|
|
85
|
+
shadow-mapSize={[2048, 2048]}
|
|
86
|
+
shadow-camera-near={0.5}
|
|
87
|
+
shadow-camera-far={50}
|
|
88
|
+
shadow-camera-left={-10}
|
|
89
|
+
shadow-camera-right={10}
|
|
90
|
+
shadow-camera-top={10}
|
|
91
|
+
shadow-camera-bottom={-10}
|
|
92
|
+
shadow-bias={-0.0001}
|
|
93
|
+
shadow-normalBias={0.02}
|
|
94
|
+
/>
|
|
95
|
+
|
|
96
|
+
// With target (light points at target)
|
|
97
|
+
function DirectionalWithTarget() {
|
|
98
|
+
const lightRef = useRef()
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<>
|
|
102
|
+
<directionalLight
|
|
103
|
+
ref={lightRef}
|
|
104
|
+
position={[5, 10, 5]}
|
|
105
|
+
target-position={[0, 0, 0]}
|
|
106
|
+
/>
|
|
107
|
+
</>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## pointLight
|
|
113
|
+
|
|
114
|
+
Emits light in all directions. Like a light bulb.
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
<pointLight
|
|
118
|
+
color="#ffffff"
|
|
119
|
+
intensity={1}
|
|
120
|
+
position={[0, 5, 0]}
|
|
121
|
+
distance={100} // Maximum range (0 = infinite)
|
|
122
|
+
decay={2} // Light falloff (physically correct = 2)
|
|
123
|
+
|
|
124
|
+
// Shadows
|
|
125
|
+
castShadow
|
|
126
|
+
shadow-mapSize={[1024, 1024]}
|
|
127
|
+
shadow-camera-near={0.5}
|
|
128
|
+
shadow-camera-far={50}
|
|
129
|
+
shadow-bias={-0.005}
|
|
130
|
+
/>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## spotLight
|
|
134
|
+
|
|
135
|
+
Cone-shaped light. Like a flashlight.
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
<spotLight
|
|
139
|
+
color="#ffffff"
|
|
140
|
+
intensity={1}
|
|
141
|
+
position={[0, 10, 0]}
|
|
142
|
+
angle={Math.PI / 6} // Cone angle (max Math.PI/2)
|
|
143
|
+
penumbra={0.5} // Soft edge (0-1)
|
|
144
|
+
distance={100} // Range
|
|
145
|
+
decay={2} // Falloff
|
|
146
|
+
|
|
147
|
+
// Target
|
|
148
|
+
target-position={[0, 0, 0]}
|
|
149
|
+
|
|
150
|
+
// Shadows
|
|
151
|
+
castShadow
|
|
152
|
+
shadow-mapSize={[1024, 1024]}
|
|
153
|
+
shadow-camera-near={0.5}
|
|
154
|
+
shadow-camera-far={50}
|
|
155
|
+
shadow-camera-fov={30}
|
|
156
|
+
shadow-bias={-0.0001}
|
|
157
|
+
/>
|
|
158
|
+
|
|
159
|
+
// SpotLight helper
|
|
160
|
+
import { useHelper } from '@react-three/drei'
|
|
161
|
+
import { SpotLightHelper } from 'three'
|
|
162
|
+
|
|
163
|
+
function SpotLightWithHelper() {
|
|
164
|
+
const lightRef = useRef()
|
|
165
|
+
useHelper(lightRef, SpotLightHelper, 'cyan')
|
|
166
|
+
|
|
167
|
+
return <spotLight ref={lightRef} position={[0, 5, 0]} />
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## rectAreaLight
|
|
172
|
+
|
|
173
|
+
Rectangular area light. Great for soft, realistic lighting.
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper'
|
|
177
|
+
|
|
178
|
+
function AreaLight() {
|
|
179
|
+
const lightRef = useRef()
|
|
180
|
+
|
|
181
|
+
return (
|
|
182
|
+
<>
|
|
183
|
+
<rectAreaLight
|
|
184
|
+
ref={lightRef}
|
|
185
|
+
color="#ffffff"
|
|
186
|
+
intensity={5}
|
|
187
|
+
width={4}
|
|
188
|
+
height={2}
|
|
189
|
+
position={[0, 5, 0]}
|
|
190
|
+
rotation={[-Math.PI / 2, 0, 0]} // Point downward
|
|
191
|
+
/>
|
|
192
|
+
</>
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Note: RectAreaLight only works with MeshStandardMaterial and MeshPhysicalMaterial
|
|
197
|
+
// Does not cast shadows natively
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Shadow Setup
|
|
201
|
+
|
|
202
|
+
### Enable Shadows on Canvas
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
<Canvas
|
|
206
|
+
shadows // or shadows="soft" | "basic" | "percentage" | "variance"
|
|
207
|
+
>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Shadow Types
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
// Basic shadows (fastest, hard edges)
|
|
214
|
+
<Canvas shadows="basic">
|
|
215
|
+
|
|
216
|
+
// PCF shadows (default, filtered)
|
|
217
|
+
<Canvas shadows>
|
|
218
|
+
|
|
219
|
+
// Soft shadows (PCFSoft, softer edges)
|
|
220
|
+
<Canvas shadows="soft">
|
|
221
|
+
|
|
222
|
+
// VSM shadows (variance shadow map)
|
|
223
|
+
<Canvas shadows="variance">
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Configure Shadow-Casting Objects
|
|
227
|
+
|
|
228
|
+
```tsx
|
|
229
|
+
// Light must cast shadows
|
|
230
|
+
<directionalLight castShadow />
|
|
231
|
+
|
|
232
|
+
// Objects must cast and/or receive shadows
|
|
233
|
+
<mesh castShadow receiveShadow>
|
|
234
|
+
<boxGeometry />
|
|
235
|
+
<meshStandardMaterial />
|
|
236
|
+
</mesh>
|
|
237
|
+
|
|
238
|
+
// Ground typically only receives
|
|
239
|
+
<mesh receiveShadow>
|
|
240
|
+
<planeGeometry args={[100, 100]} />
|
|
241
|
+
<meshStandardMaterial />
|
|
242
|
+
</mesh>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Shadow Camera Helper
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { useHelper } from '@react-three/drei'
|
|
249
|
+
import { CameraHelper } from 'three'
|
|
250
|
+
|
|
251
|
+
function LightWithShadowHelper() {
|
|
252
|
+
const lightRef = useRef()
|
|
253
|
+
|
|
254
|
+
// Visualize shadow camera frustum
|
|
255
|
+
useHelper(lightRef.current?.shadow.camera, CameraHelper)
|
|
256
|
+
|
|
257
|
+
return (
|
|
258
|
+
<directionalLight
|
|
259
|
+
ref={lightRef}
|
|
260
|
+
castShadow
|
|
261
|
+
shadow-camera-left={-10}
|
|
262
|
+
shadow-camera-right={10}
|
|
263
|
+
shadow-camera-top={10}
|
|
264
|
+
shadow-camera-bottom={-10}
|
|
265
|
+
/>
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Drei Lighting Helpers
|
|
271
|
+
|
|
272
|
+
### Environment
|
|
273
|
+
|
|
274
|
+
HDR environment lighting with presets or custom files.
|
|
275
|
+
|
|
276
|
+
```tsx
|
|
277
|
+
import { Environment } from '@react-three/drei'
|
|
278
|
+
|
|
279
|
+
// Preset environments
|
|
280
|
+
<Environment
|
|
281
|
+
preset="sunset" // apartment, city, dawn, forest, lobby, night, park, studio, sunset, warehouse
|
|
282
|
+
background // Also use as background
|
|
283
|
+
backgroundBlurriness={0} // Background blur
|
|
284
|
+
backgroundIntensity={1} // Background brightness
|
|
285
|
+
environmentIntensity={1} // Lighting intensity
|
|
286
|
+
/>
|
|
287
|
+
|
|
288
|
+
// Custom HDR file
|
|
289
|
+
<Environment files="/hdri/studio.hdr" />
|
|
290
|
+
|
|
291
|
+
// Cube map (6 images)
|
|
292
|
+
<Environment
|
|
293
|
+
files={['px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png']}
|
|
294
|
+
path="/textures/cube/"
|
|
295
|
+
/>
|
|
296
|
+
|
|
297
|
+
// Ground projection
|
|
298
|
+
<Environment
|
|
299
|
+
preset="city"
|
|
300
|
+
ground={{
|
|
301
|
+
height: 15,
|
|
302
|
+
radius: 100,
|
|
303
|
+
scale: 100,
|
|
304
|
+
}}
|
|
305
|
+
/>
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Lightformer
|
|
309
|
+
|
|
310
|
+
Create custom light shapes inside Environment.
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
import { Environment, Lightformer } from '@react-three/drei'
|
|
314
|
+
|
|
315
|
+
<Environment>
|
|
316
|
+
<Lightformer
|
|
317
|
+
form="ring" // circle, ring, rect
|
|
318
|
+
intensity={2}
|
|
319
|
+
color="white"
|
|
320
|
+
scale={10}
|
|
321
|
+
position={[0, 5, -5]}
|
|
322
|
+
target={[0, 0, 0]} // Point at target
|
|
323
|
+
/>
|
|
324
|
+
|
|
325
|
+
<Lightformer
|
|
326
|
+
form="rect"
|
|
327
|
+
intensity={1}
|
|
328
|
+
color="red"
|
|
329
|
+
scale={[5, 2]}
|
|
330
|
+
position={[-5, 5, 0]}
|
|
331
|
+
/>
|
|
332
|
+
</Environment>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Sky
|
|
336
|
+
|
|
337
|
+
Procedural sky with sun.
|
|
338
|
+
|
|
339
|
+
```tsx
|
|
340
|
+
import { Sky } from '@react-three/drei'
|
|
341
|
+
|
|
342
|
+
<Sky
|
|
343
|
+
distance={450000}
|
|
344
|
+
sunPosition={[0, 1, 0]} // Or calculate from inclination/azimuth
|
|
345
|
+
inclination={0.6} // Sun elevation (0 = horizon, 0.5 = zenith)
|
|
346
|
+
azimuth={0.25} // Sun rotation around horizon
|
|
347
|
+
turbidity={10} // Haziness
|
|
348
|
+
rayleigh={2} // Light scattering
|
|
349
|
+
mieCoefficient={0.005}
|
|
350
|
+
mieDirectionalG={0.8}
|
|
351
|
+
/>
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Stars
|
|
355
|
+
|
|
356
|
+
Starfield background.
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
import { Stars } from '@react-three/drei'
|
|
360
|
+
|
|
361
|
+
<Stars
|
|
362
|
+
radius={100} // Sphere radius
|
|
363
|
+
depth={50} // Depth of star distribution
|
|
364
|
+
count={5000} // Number of stars
|
|
365
|
+
factor={4} // Size factor
|
|
366
|
+
saturation={0} // Color saturation
|
|
367
|
+
fade // Fade at edges
|
|
368
|
+
speed={1} // Twinkle speed
|
|
369
|
+
/>
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Stage
|
|
373
|
+
|
|
374
|
+
Quick lighting setup for product showcase.
|
|
375
|
+
|
|
376
|
+
```tsx
|
|
377
|
+
import { Stage } from '@react-three/drei'
|
|
378
|
+
|
|
379
|
+
<Stage
|
|
380
|
+
preset="rembrandt" // rembrandt, portrait, upfront, soft
|
|
381
|
+
intensity={1}
|
|
382
|
+
shadows="contact" // false, 'contact', 'accumulative', true
|
|
383
|
+
environment="city"
|
|
384
|
+
adjustCamera={1.2} // Adjust camera to fit content
|
|
385
|
+
>
|
|
386
|
+
<Model />
|
|
387
|
+
</Stage>
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### ContactShadows
|
|
391
|
+
|
|
392
|
+
Fast fake shadows without shadow mapping.
|
|
393
|
+
|
|
394
|
+
```tsx
|
|
395
|
+
import { ContactShadows } from '@react-three/drei'
|
|
396
|
+
|
|
397
|
+
<ContactShadows
|
|
398
|
+
position={[0, -0.5, 0]}
|
|
399
|
+
opacity={0.5}
|
|
400
|
+
scale={10}
|
|
401
|
+
blur={1}
|
|
402
|
+
far={10}
|
|
403
|
+
resolution={256}
|
|
404
|
+
color="#000000"
|
|
405
|
+
frames={1} // Render once (for static scenes)
|
|
406
|
+
/>
|
|
407
|
+
|
|
408
|
+
// For animated scenes
|
|
409
|
+
<ContactShadows frames={Infinity} />
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### AccumulativeShadows
|
|
413
|
+
|
|
414
|
+
Soft, accumulated shadows.
|
|
415
|
+
|
|
416
|
+
```tsx
|
|
417
|
+
import { AccumulativeShadows, RandomizedLight } from '@react-three/drei'
|
|
418
|
+
|
|
419
|
+
<AccumulativeShadows
|
|
420
|
+
position={[0, -0.5, 0]}
|
|
421
|
+
scale={10}
|
|
422
|
+
color="#316d39"
|
|
423
|
+
opacity={0.8}
|
|
424
|
+
frames={100}
|
|
425
|
+
temporal // Smooth accumulation over time
|
|
426
|
+
>
|
|
427
|
+
<RandomizedLight
|
|
428
|
+
amount={8}
|
|
429
|
+
radius={4}
|
|
430
|
+
ambient={0.5}
|
|
431
|
+
intensity={1}
|
|
432
|
+
position={[5, 5, -10]}
|
|
433
|
+
bias={0.001}
|
|
434
|
+
/>
|
|
435
|
+
</AccumulativeShadows>
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### SoftShadows
|
|
439
|
+
|
|
440
|
+
Enable PCF soft shadows globally.
|
|
441
|
+
|
|
442
|
+
```tsx
|
|
443
|
+
import { SoftShadows } from '@react-three/drei'
|
|
444
|
+
|
|
445
|
+
<Canvas shadows>
|
|
446
|
+
<SoftShadows
|
|
447
|
+
size={25}
|
|
448
|
+
samples={10}
|
|
449
|
+
focus={0}
|
|
450
|
+
/>
|
|
451
|
+
</Canvas>
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### BakeShadows
|
|
455
|
+
|
|
456
|
+
Bake shadows for static scenes.
|
|
457
|
+
|
|
458
|
+
```tsx
|
|
459
|
+
import { BakeShadows } from '@react-three/drei'
|
|
460
|
+
|
|
461
|
+
<Canvas shadows>
|
|
462
|
+
<BakeShadows /> {/* Bakes shadows once on mount */}
|
|
463
|
+
</Canvas>
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## Common Lighting Setups
|
|
467
|
+
|
|
468
|
+
### Three-Point Lighting
|
|
469
|
+
|
|
470
|
+
```tsx
|
|
471
|
+
function ThreePointLighting() {
|
|
472
|
+
return (
|
|
473
|
+
<>
|
|
474
|
+
{/* Key light (main) */}
|
|
475
|
+
<directionalLight
|
|
476
|
+
position={[5, 5, 5]}
|
|
477
|
+
intensity={1}
|
|
478
|
+
castShadow
|
|
479
|
+
/>
|
|
480
|
+
|
|
481
|
+
{/* Fill light (softer, opposite side) */}
|
|
482
|
+
<directionalLight
|
|
483
|
+
position={[-5, 3, 5]}
|
|
484
|
+
intensity={0.5}
|
|
485
|
+
/>
|
|
486
|
+
|
|
487
|
+
{/* Back light (rim lighting) */}
|
|
488
|
+
<directionalLight
|
|
489
|
+
position={[0, 5, -5]}
|
|
490
|
+
intensity={0.3}
|
|
491
|
+
/>
|
|
492
|
+
|
|
493
|
+
{/* Ambient fill */}
|
|
494
|
+
<ambientLight intensity={0.2} />
|
|
495
|
+
</>
|
|
496
|
+
)
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### Outdoor Daylight
|
|
501
|
+
|
|
502
|
+
```tsx
|
|
503
|
+
import { Sky, Environment } from '@react-three/drei'
|
|
504
|
+
|
|
505
|
+
function OutdoorLighting() {
|
|
506
|
+
return (
|
|
507
|
+
<>
|
|
508
|
+
<Sky sunPosition={[100, 100, 100]} />
|
|
509
|
+
<Environment preset="dawn" />
|
|
510
|
+
|
|
511
|
+
<directionalLight
|
|
512
|
+
position={[50, 100, 50]}
|
|
513
|
+
intensity={1.5}
|
|
514
|
+
castShadow
|
|
515
|
+
shadow-mapSize={[2048, 2048]}
|
|
516
|
+
shadow-camera-far={200}
|
|
517
|
+
shadow-camera-left={-50}
|
|
518
|
+
shadow-camera-right={50}
|
|
519
|
+
shadow-camera-top={50}
|
|
520
|
+
shadow-camera-bottom={-50}
|
|
521
|
+
/>
|
|
522
|
+
|
|
523
|
+
<hemisphereLight
|
|
524
|
+
color="#87ceeb"
|
|
525
|
+
groundColor="#8b4513"
|
|
526
|
+
intensity={0.5}
|
|
527
|
+
/>
|
|
528
|
+
</>
|
|
529
|
+
)
|
|
530
|
+
}
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### Studio Lighting
|
|
534
|
+
|
|
535
|
+
```tsx
|
|
536
|
+
import { Environment, Lightformer, ContactShadows } from '@react-three/drei'
|
|
537
|
+
|
|
538
|
+
function StudioLighting() {
|
|
539
|
+
return (
|
|
540
|
+
<>
|
|
541
|
+
<Environment resolution={256}>
|
|
542
|
+
{/* Key light */}
|
|
543
|
+
<Lightformer
|
|
544
|
+
form="rect"
|
|
545
|
+
intensity={4}
|
|
546
|
+
position={[5, 5, -5]}
|
|
547
|
+
scale={[10, 5]}
|
|
548
|
+
target={[0, 0, 0]}
|
|
549
|
+
/>
|
|
550
|
+
|
|
551
|
+
{/* Fill light */}
|
|
552
|
+
<Lightformer
|
|
553
|
+
form="rect"
|
|
554
|
+
intensity={2}
|
|
555
|
+
position={[-5, 5, 5]}
|
|
556
|
+
scale={[10, 5]}
|
|
557
|
+
/>
|
|
558
|
+
|
|
559
|
+
{/* Rim light */}
|
|
560
|
+
<Lightformer
|
|
561
|
+
form="ring"
|
|
562
|
+
intensity={1}
|
|
563
|
+
position={[0, 5, -10]}
|
|
564
|
+
scale={5}
|
|
565
|
+
/>
|
|
566
|
+
</Environment>
|
|
567
|
+
|
|
568
|
+
<ContactShadows
|
|
569
|
+
position={[0, -0.5, 0]}
|
|
570
|
+
opacity={0.5}
|
|
571
|
+
blur={2}
|
|
572
|
+
/>
|
|
573
|
+
</>
|
|
574
|
+
)
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
## Animated Lighting
|
|
579
|
+
|
|
580
|
+
```tsx
|
|
581
|
+
import { useFrame } from '@react-three/fiber'
|
|
582
|
+
import { useRef } from 'react'
|
|
583
|
+
|
|
584
|
+
function AnimatedLight() {
|
|
585
|
+
const lightRef = useRef()
|
|
586
|
+
|
|
587
|
+
useFrame(({ clock }) => {
|
|
588
|
+
const t = clock.elapsedTime
|
|
589
|
+
|
|
590
|
+
// Orbit around scene
|
|
591
|
+
lightRef.current.position.x = Math.cos(t) * 5
|
|
592
|
+
lightRef.current.position.z = Math.sin(t) * 5
|
|
593
|
+
|
|
594
|
+
// Pulsing intensity
|
|
595
|
+
lightRef.current.intensity = 1 + Math.sin(t * 2) * 0.5
|
|
596
|
+
|
|
597
|
+
// Color cycling
|
|
598
|
+
lightRef.current.color.setHSL((t * 0.1) % 1, 1, 0.5)
|
|
599
|
+
})
|
|
600
|
+
|
|
601
|
+
return (
|
|
602
|
+
<pointLight ref={lightRef} position={[5, 3, 0]} castShadow />
|
|
603
|
+
)
|
|
604
|
+
}
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
## Light Helpers
|
|
608
|
+
|
|
609
|
+
```tsx
|
|
610
|
+
import { useHelper } from '@react-three/drei'
|
|
611
|
+
import {
|
|
612
|
+
DirectionalLightHelper,
|
|
613
|
+
PointLightHelper,
|
|
614
|
+
SpotLightHelper,
|
|
615
|
+
HemisphereLightHelper,
|
|
616
|
+
} from 'three'
|
|
617
|
+
|
|
618
|
+
function LightWithHelpers() {
|
|
619
|
+
const dirLightRef = useRef()
|
|
620
|
+
const pointLightRef = useRef()
|
|
621
|
+
const spotLightRef = useRef()
|
|
622
|
+
const hemiLightRef = useRef()
|
|
623
|
+
|
|
624
|
+
useHelper(dirLightRef, DirectionalLightHelper, 5, 'red')
|
|
625
|
+
useHelper(pointLightRef, PointLightHelper, 1, 'green')
|
|
626
|
+
useHelper(spotLightRef, SpotLightHelper, 'blue')
|
|
627
|
+
useHelper(hemiLightRef, HemisphereLightHelper, 5, 'yellow', 'brown')
|
|
628
|
+
|
|
629
|
+
return (
|
|
630
|
+
<>
|
|
631
|
+
<directionalLight ref={dirLightRef} position={[5, 5, 5]} />
|
|
632
|
+
<pointLight ref={pointLightRef} position={[-5, 5, 0]} />
|
|
633
|
+
<spotLight ref={spotLightRef} position={[0, 5, 5]} />
|
|
634
|
+
<hemisphereLight ref={hemiLightRef} />
|
|
635
|
+
</>
|
|
636
|
+
)
|
|
637
|
+
}
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
## Performance Tips
|
|
641
|
+
|
|
642
|
+
1. **Limit light count**: Each light adds shader complexity
|
|
643
|
+
2. **Use baked lighting**: For static scenes
|
|
644
|
+
3. **Smaller shadow maps**: 512-1024 often sufficient
|
|
645
|
+
4. **Tight shadow frustums**: Only cover needed area
|
|
646
|
+
5. **Disable unused shadows**: Not all lights need shadows
|
|
647
|
+
6. **Use Environment**: More efficient than many lights
|
|
648
|
+
|
|
649
|
+
```tsx
|
|
650
|
+
// Selective shadows
|
|
651
|
+
<mesh castShadow={isHero}>
|
|
652
|
+
<boxGeometry />
|
|
653
|
+
</mesh>
|
|
654
|
+
|
|
655
|
+
// Only update shadows when needed
|
|
656
|
+
<ContactShadows frames={isAnimating ? Infinity : 1} />
|
|
657
|
+
|
|
658
|
+
// Use layers to exclude objects from lights
|
|
659
|
+
<directionalLight layers={1} />
|
|
660
|
+
<mesh layers={1}> {/* Affected by light */}
|
|
661
|
+
<mesh layers={2}> {/* Not affected */}
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
## See Also
|
|
665
|
+
|
|
666
|
+
- `r3f-materials` - Material light response
|
|
667
|
+
- `r3f-textures` - Environment maps
|
|
668
|
+
- `r3f-postprocessing` - Bloom and light effects
|