@lark-apaas/coding-steering 0.1.2 → 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/html/skills/rich-interactive-design/SKILL.md +5 -2
- package/steering/html/skills/rich-interactive-design/references/tasks/interactive-scene.md +1 -0
- 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,601 @@
|
|
|
1
|
+
# React Three Fiber Materials
|
|
2
|
+
|
|
3
|
+
## Quick Start
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Canvas } from '@react-three/fiber'
|
|
7
|
+
|
|
8
|
+
function Scene() {
|
|
9
|
+
return (
|
|
10
|
+
<Canvas>
|
|
11
|
+
<ambientLight intensity={0.5} />
|
|
12
|
+
<directionalLight position={[5, 5, 5]} />
|
|
13
|
+
|
|
14
|
+
<mesh>
|
|
15
|
+
<boxGeometry />
|
|
16
|
+
<meshStandardMaterial
|
|
17
|
+
color="hotpink"
|
|
18
|
+
roughness={0.5}
|
|
19
|
+
metalness={0.5}
|
|
20
|
+
/>
|
|
21
|
+
</mesh>
|
|
22
|
+
</Canvas>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Material Types Overview
|
|
28
|
+
|
|
29
|
+
| Material | Use Case | Lighting |
|
|
30
|
+
|----------|----------|----------|
|
|
31
|
+
| meshBasicMaterial | Unlit, flat colors | No |
|
|
32
|
+
| meshLambertMaterial | Matte surfaces, fast | Yes (diffuse) |
|
|
33
|
+
| meshPhongMaterial | Shiny, specular | Yes |
|
|
34
|
+
| meshStandardMaterial | PBR, realistic | Yes (PBR) |
|
|
35
|
+
| meshPhysicalMaterial | Advanced PBR | Yes (PBR+) |
|
|
36
|
+
| meshToonMaterial | Cel-shaded | Yes (toon) |
|
|
37
|
+
| meshNormalMaterial | Debug normals | No |
|
|
38
|
+
| shaderMaterial | Custom GLSL | Custom |
|
|
39
|
+
|
|
40
|
+
## meshBasicMaterial
|
|
41
|
+
|
|
42
|
+
No lighting calculations. Always visible, fast.
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
<mesh>
|
|
46
|
+
<boxGeometry />
|
|
47
|
+
<meshBasicMaterial
|
|
48
|
+
color="red"
|
|
49
|
+
transparent
|
|
50
|
+
opacity={0.5}
|
|
51
|
+
side={THREE.DoubleSide} // FrontSide, BackSide, DoubleSide
|
|
52
|
+
wireframe={false}
|
|
53
|
+
map={colorTexture}
|
|
54
|
+
alphaMap={alphaTexture}
|
|
55
|
+
envMap={envTexture}
|
|
56
|
+
fog={true}
|
|
57
|
+
/>
|
|
58
|
+
</mesh>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## meshStandardMaterial (PBR)
|
|
62
|
+
|
|
63
|
+
Physically-based rendering. Recommended for realistic results.
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { useTexture } from '@react-three/drei'
|
|
67
|
+
import * as THREE from 'three'
|
|
68
|
+
|
|
69
|
+
function PBRMesh() {
|
|
70
|
+
// Load PBR texture set
|
|
71
|
+
const [colorMap, normalMap, roughnessMap, metalnessMap, aoMap] = useTexture([
|
|
72
|
+
'/textures/color.jpg',
|
|
73
|
+
'/textures/normal.jpg',
|
|
74
|
+
'/textures/roughness.jpg',
|
|
75
|
+
'/textures/metalness.jpg',
|
|
76
|
+
'/textures/ao.jpg',
|
|
77
|
+
])
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<mesh>
|
|
81
|
+
<sphereGeometry args={[1, 64, 64]} />
|
|
82
|
+
<meshStandardMaterial
|
|
83
|
+
// Base color
|
|
84
|
+
color="#ffffff"
|
|
85
|
+
map={colorMap}
|
|
86
|
+
|
|
87
|
+
// PBR properties
|
|
88
|
+
roughness={1} // 0 = mirror, 1 = diffuse
|
|
89
|
+
roughnessMap={roughnessMap}
|
|
90
|
+
metalness={0} // 0 = dielectric, 1 = metal
|
|
91
|
+
metalnessMap={metalnessMap}
|
|
92
|
+
|
|
93
|
+
// Surface detail
|
|
94
|
+
normalMap={normalMap}
|
|
95
|
+
normalScale={[1, 1]}
|
|
96
|
+
|
|
97
|
+
// Ambient occlusion (requires uv2)
|
|
98
|
+
aoMap={aoMap}
|
|
99
|
+
aoMapIntensity={1}
|
|
100
|
+
|
|
101
|
+
// Emissive
|
|
102
|
+
emissive="#000000"
|
|
103
|
+
emissiveIntensity={1}
|
|
104
|
+
emissiveMap={emissiveTexture}
|
|
105
|
+
|
|
106
|
+
// Environment
|
|
107
|
+
envMap={envTexture}
|
|
108
|
+
envMapIntensity={1}
|
|
109
|
+
|
|
110
|
+
// Other
|
|
111
|
+
flatShading={false}
|
|
112
|
+
fog={true}
|
|
113
|
+
transparent={false}
|
|
114
|
+
/>
|
|
115
|
+
</mesh>
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## meshPhysicalMaterial (Advanced PBR)
|
|
121
|
+
|
|
122
|
+
Extends Standard with clearcoat, transmission, sheen, etc.
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
// Glass material
|
|
126
|
+
function Glass() {
|
|
127
|
+
return (
|
|
128
|
+
<mesh>
|
|
129
|
+
<sphereGeometry args={[1, 64, 64]} />
|
|
130
|
+
<meshPhysicalMaterial
|
|
131
|
+
color="#ffffff"
|
|
132
|
+
metalness={0}
|
|
133
|
+
roughness={0}
|
|
134
|
+
transmission={1} // 0 = opaque, 1 = fully transparent
|
|
135
|
+
thickness={0.5} // Volume thickness for refraction
|
|
136
|
+
ior={1.5} // Index of refraction (glass ~1.5)
|
|
137
|
+
envMapIntensity={1}
|
|
138
|
+
/>
|
|
139
|
+
</mesh>
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Car paint
|
|
144
|
+
function CarPaint() {
|
|
145
|
+
return (
|
|
146
|
+
<mesh>
|
|
147
|
+
<boxGeometry />
|
|
148
|
+
<meshPhysicalMaterial
|
|
149
|
+
color="#ff0000"
|
|
150
|
+
metalness={0.9}
|
|
151
|
+
roughness={0.5}
|
|
152
|
+
clearcoat={1} // Clearcoat layer strength
|
|
153
|
+
clearcoatRoughness={0.1} // Clearcoat roughness
|
|
154
|
+
/>
|
|
155
|
+
</mesh>
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Fabric/velvet (sheen)
|
|
160
|
+
function Fabric() {
|
|
161
|
+
return (
|
|
162
|
+
<mesh>
|
|
163
|
+
<sphereGeometry args={[1, 64, 64]} />
|
|
164
|
+
<meshPhysicalMaterial
|
|
165
|
+
color="#8844aa"
|
|
166
|
+
roughness={0.8}
|
|
167
|
+
sheen={1}
|
|
168
|
+
sheenRoughness={0.5}
|
|
169
|
+
sheenColor="#ff88ff"
|
|
170
|
+
/>
|
|
171
|
+
</mesh>
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Iridescent (soap bubbles)
|
|
176
|
+
function Iridescent() {
|
|
177
|
+
return (
|
|
178
|
+
<mesh>
|
|
179
|
+
<sphereGeometry args={[1, 64, 64]} />
|
|
180
|
+
<meshPhysicalMaterial
|
|
181
|
+
color="#ffffff"
|
|
182
|
+
iridescence={1}
|
|
183
|
+
iridescenceIOR={1.3}
|
|
184
|
+
iridescenceThicknessRange={[100, 400]}
|
|
185
|
+
/>
|
|
186
|
+
</mesh>
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Drei Special Materials
|
|
192
|
+
|
|
193
|
+
### MeshReflectorMaterial
|
|
194
|
+
|
|
195
|
+
Realistic mirror-like reflections.
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
import { MeshReflectorMaterial } from '@react-three/drei'
|
|
199
|
+
|
|
200
|
+
function ReflectiveFloor() {
|
|
201
|
+
return (
|
|
202
|
+
<mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, -0.5, 0]}>
|
|
203
|
+
<planeGeometry args={[10, 10]} />
|
|
204
|
+
<MeshReflectorMaterial
|
|
205
|
+
blur={[400, 100]} // Blur amount [x, y]
|
|
206
|
+
resolution={1024} // Reflection resolution
|
|
207
|
+
mixBlur={1} // Mix blur with reflection
|
|
208
|
+
mixStrength={0.5} // Reflection strength
|
|
209
|
+
roughness={1}
|
|
210
|
+
depthScale={1.2}
|
|
211
|
+
minDepthThreshold={0.4}
|
|
212
|
+
maxDepthThreshold={1.4}
|
|
213
|
+
color="#333"
|
|
214
|
+
metalness={0.5}
|
|
215
|
+
mirror={0.5}
|
|
216
|
+
/>
|
|
217
|
+
</mesh>
|
|
218
|
+
)
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### MeshWobbleMaterial
|
|
223
|
+
|
|
224
|
+
Animated wobble effect.
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
import { MeshWobbleMaterial } from '@react-three/drei'
|
|
228
|
+
|
|
229
|
+
function WobblyMesh() {
|
|
230
|
+
return (
|
|
231
|
+
<mesh>
|
|
232
|
+
<torusKnotGeometry args={[1, 0.4, 100, 16]} />
|
|
233
|
+
<MeshWobbleMaterial
|
|
234
|
+
factor={1} // Wobble amplitude
|
|
235
|
+
speed={2} // Wobble speed
|
|
236
|
+
color="hotpink"
|
|
237
|
+
metalness={0}
|
|
238
|
+
roughness={0.5}
|
|
239
|
+
/>
|
|
240
|
+
</mesh>
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### MeshDistortMaterial
|
|
246
|
+
|
|
247
|
+
Perlin noise distortion.
|
|
248
|
+
|
|
249
|
+
```tsx
|
|
250
|
+
import { MeshDistortMaterial } from '@react-three/drei'
|
|
251
|
+
|
|
252
|
+
function DistortedMesh() {
|
|
253
|
+
return (
|
|
254
|
+
<mesh>
|
|
255
|
+
<sphereGeometry args={[1, 64, 64]} />
|
|
256
|
+
<MeshDistortMaterial
|
|
257
|
+
distort={0.5} // Distortion amount
|
|
258
|
+
speed={2} // Animation speed
|
|
259
|
+
color="cyan"
|
|
260
|
+
roughness={0.2}
|
|
261
|
+
/>
|
|
262
|
+
</mesh>
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### MeshTransmissionMaterial
|
|
268
|
+
|
|
269
|
+
Better glass/refractive materials.
|
|
270
|
+
|
|
271
|
+
```tsx
|
|
272
|
+
import { MeshTransmissionMaterial } from '@react-three/drei'
|
|
273
|
+
|
|
274
|
+
function GlassSphere() {
|
|
275
|
+
return (
|
|
276
|
+
<mesh>
|
|
277
|
+
<sphereGeometry args={[1, 64, 64]} />
|
|
278
|
+
<MeshTransmissionMaterial
|
|
279
|
+
backside // Render backside
|
|
280
|
+
samples={16} // Refraction samples
|
|
281
|
+
resolution={1024} // Buffer resolution
|
|
282
|
+
transmission={1} // Transmission factor
|
|
283
|
+
roughness={0.0}
|
|
284
|
+
thickness={0.5} // Volume thickness
|
|
285
|
+
ior={1.5} // Index of refraction
|
|
286
|
+
chromaticAberration={0.06}
|
|
287
|
+
anisotropy={0.1}
|
|
288
|
+
distortion={0.0}
|
|
289
|
+
distortionScale={0.3}
|
|
290
|
+
temporalDistortion={0.5}
|
|
291
|
+
clearcoat={1}
|
|
292
|
+
attenuationDistance={0.5}
|
|
293
|
+
attenuationColor="#ffffff"
|
|
294
|
+
color="#c9ffa1"
|
|
295
|
+
/>
|
|
296
|
+
</mesh>
|
|
297
|
+
)
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### MeshDiscardMaterial
|
|
302
|
+
|
|
303
|
+
Discard fragments - useful for shadows only.
|
|
304
|
+
|
|
305
|
+
```tsx
|
|
306
|
+
import { MeshDiscardMaterial } from '@react-three/drei'
|
|
307
|
+
|
|
308
|
+
function ShadowOnlyMesh() {
|
|
309
|
+
return (
|
|
310
|
+
<mesh castShadow>
|
|
311
|
+
<boxGeometry />
|
|
312
|
+
<MeshDiscardMaterial /> {/* Invisible but casts shadows */}
|
|
313
|
+
</mesh>
|
|
314
|
+
)
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Points and Lines Materials
|
|
319
|
+
|
|
320
|
+
```tsx
|
|
321
|
+
// Points material
|
|
322
|
+
<points>
|
|
323
|
+
<bufferGeometry />
|
|
324
|
+
<pointsMaterial
|
|
325
|
+
size={0.1}
|
|
326
|
+
sizeAttenuation={true}
|
|
327
|
+
color="white"
|
|
328
|
+
map={spriteTexture}
|
|
329
|
+
transparent
|
|
330
|
+
alphaTest={0.5}
|
|
331
|
+
vertexColors
|
|
332
|
+
/>
|
|
333
|
+
</points>
|
|
334
|
+
|
|
335
|
+
// Line materials
|
|
336
|
+
<line>
|
|
337
|
+
<bufferGeometry />
|
|
338
|
+
<lineBasicMaterial color="white" linewidth={1} />
|
|
339
|
+
</line>
|
|
340
|
+
|
|
341
|
+
<line>
|
|
342
|
+
<bufferGeometry />
|
|
343
|
+
<lineDashedMaterial
|
|
344
|
+
color="white"
|
|
345
|
+
dashSize={0.5}
|
|
346
|
+
gapSize={0.25}
|
|
347
|
+
scale={1}
|
|
348
|
+
/>
|
|
349
|
+
</line>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Common Material Properties
|
|
353
|
+
|
|
354
|
+
All materials share these base properties:
|
|
355
|
+
|
|
356
|
+
```tsx
|
|
357
|
+
<meshStandardMaterial
|
|
358
|
+
// Visibility
|
|
359
|
+
visible={true}
|
|
360
|
+
transparent={false}
|
|
361
|
+
opacity={1}
|
|
362
|
+
alphaTest={0} // Discard pixels with alpha < value
|
|
363
|
+
|
|
364
|
+
// Rendering
|
|
365
|
+
side={THREE.FrontSide} // FrontSide, BackSide, DoubleSide
|
|
366
|
+
depthTest={true}
|
|
367
|
+
depthWrite={true}
|
|
368
|
+
colorWrite={true}
|
|
369
|
+
|
|
370
|
+
// Blending
|
|
371
|
+
blending={THREE.NormalBlending}
|
|
372
|
+
// NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending
|
|
373
|
+
|
|
374
|
+
// Polygon offset (z-fighting fix)
|
|
375
|
+
polygonOffset={false}
|
|
376
|
+
polygonOffsetFactor={0}
|
|
377
|
+
polygonOffsetUnits={0}
|
|
378
|
+
|
|
379
|
+
// Misc
|
|
380
|
+
dithering={false}
|
|
381
|
+
toneMapped={true}
|
|
382
|
+
/>
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## Dynamic Materials
|
|
386
|
+
|
|
387
|
+
### Updating Material Properties
|
|
388
|
+
|
|
389
|
+
```tsx
|
|
390
|
+
import { useRef } from 'react'
|
|
391
|
+
import { useFrame } from '@react-three/fiber'
|
|
392
|
+
|
|
393
|
+
function AnimatedMaterial() {
|
|
394
|
+
const materialRef = useRef()
|
|
395
|
+
|
|
396
|
+
useFrame(({ clock }) => {
|
|
397
|
+
const t = clock.elapsedTime
|
|
398
|
+
|
|
399
|
+
// Update color
|
|
400
|
+
materialRef.current.color.setHSL((t * 0.1) % 1, 1, 0.5)
|
|
401
|
+
|
|
402
|
+
// Update properties
|
|
403
|
+
materialRef.current.roughness = (Math.sin(t) + 1) / 2
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
return (
|
|
407
|
+
<mesh>
|
|
408
|
+
<boxGeometry />
|
|
409
|
+
<meshStandardMaterial ref={materialRef} />
|
|
410
|
+
</mesh>
|
|
411
|
+
)
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Shared Materials
|
|
416
|
+
|
|
417
|
+
```tsx
|
|
418
|
+
import { useMemo } from 'react'
|
|
419
|
+
import * as THREE from 'three'
|
|
420
|
+
|
|
421
|
+
function SharedMaterial() {
|
|
422
|
+
// Create once, use many times
|
|
423
|
+
const material = useMemo(() =>
|
|
424
|
+
new THREE.MeshStandardMaterial({ color: 'red' }),
|
|
425
|
+
[])
|
|
426
|
+
|
|
427
|
+
return (
|
|
428
|
+
<>
|
|
429
|
+
<mesh position={[-2, 0, 0]} material={material}>
|
|
430
|
+
<boxGeometry />
|
|
431
|
+
</mesh>
|
|
432
|
+
<mesh position={[0, 0, 0]} material={material}>
|
|
433
|
+
<sphereGeometry />
|
|
434
|
+
</mesh>
|
|
435
|
+
<mesh position={[2, 0, 0]} material={material}>
|
|
436
|
+
<coneGeometry />
|
|
437
|
+
</mesh>
|
|
438
|
+
</>
|
|
439
|
+
)
|
|
440
|
+
}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Multiple Materials
|
|
444
|
+
|
|
445
|
+
```tsx
|
|
446
|
+
// Different materials per face (BoxGeometry has 6 material groups)
|
|
447
|
+
<mesh>
|
|
448
|
+
<boxGeometry />
|
|
449
|
+
<meshStandardMaterial attach="material-0" color="red" /> {/* +X */}
|
|
450
|
+
<meshStandardMaterial attach="material-1" color="green" /> {/* -X */}
|
|
451
|
+
<meshStandardMaterial attach="material-2" color="blue" /> {/* +Y */}
|
|
452
|
+
<meshStandardMaterial attach="material-3" color="yellow" />{/* -Y */}
|
|
453
|
+
<meshStandardMaterial attach="material-4" color="cyan" /> {/* +Z */}
|
|
454
|
+
<meshStandardMaterial attach="material-5" color="magenta" />{/* -Z */}
|
|
455
|
+
</mesh>
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
## Material with Textures
|
|
459
|
+
|
|
460
|
+
```tsx
|
|
461
|
+
import { useTexture } from '@react-three/drei'
|
|
462
|
+
import * as THREE from 'three'
|
|
463
|
+
|
|
464
|
+
function TexturedMaterial() {
|
|
465
|
+
// Named object pattern (recommended)
|
|
466
|
+
const textures = useTexture({
|
|
467
|
+
map: '/textures/color.jpg',
|
|
468
|
+
normalMap: '/textures/normal.jpg',
|
|
469
|
+
roughnessMap: '/textures/roughness.jpg',
|
|
470
|
+
})
|
|
471
|
+
|
|
472
|
+
// Set texture properties
|
|
473
|
+
Object.values(textures).forEach(texture => {
|
|
474
|
+
texture.wrapS = texture.wrapT = THREE.RepeatWrapping
|
|
475
|
+
texture.repeat.set(2, 2)
|
|
476
|
+
})
|
|
477
|
+
|
|
478
|
+
return (
|
|
479
|
+
<mesh>
|
|
480
|
+
<planeGeometry args={[5, 5]} />
|
|
481
|
+
<meshStandardMaterial {...textures} />
|
|
482
|
+
</mesh>
|
|
483
|
+
)
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
## Emissive Materials (Glow)
|
|
488
|
+
|
|
489
|
+
```tsx
|
|
490
|
+
// For bloom effect, emissive colors should exceed normal range
|
|
491
|
+
<meshStandardMaterial
|
|
492
|
+
color="black"
|
|
493
|
+
emissive="#ff0000"
|
|
494
|
+
emissiveIntensity={2} // > 1 for bloom
|
|
495
|
+
toneMapped={false} // Required for colors > 1
|
|
496
|
+
/>
|
|
497
|
+
|
|
498
|
+
// With emissive map
|
|
499
|
+
<meshStandardMaterial
|
|
500
|
+
emissive="white"
|
|
501
|
+
emissiveMap={emissiveTexture}
|
|
502
|
+
emissiveIntensity={2}
|
|
503
|
+
toneMapped={false}
|
|
504
|
+
/>
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
## Environment Maps
|
|
508
|
+
|
|
509
|
+
```tsx
|
|
510
|
+
import { useEnvironment } from '@react-three/drei'
|
|
511
|
+
|
|
512
|
+
function EnvMappedMaterial() {
|
|
513
|
+
const envMap = useEnvironment({ preset: 'sunset' })
|
|
514
|
+
|
|
515
|
+
return (
|
|
516
|
+
<mesh>
|
|
517
|
+
<sphereGeometry args={[1, 64, 64]} />
|
|
518
|
+
<meshStandardMaterial
|
|
519
|
+
metalness={1}
|
|
520
|
+
roughness={0}
|
|
521
|
+
envMap={envMap}
|
|
522
|
+
envMapIntensity={1}
|
|
523
|
+
/>
|
|
524
|
+
</mesh>
|
|
525
|
+
)
|
|
526
|
+
}
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
## Custom Shader Materials
|
|
530
|
+
|
|
531
|
+
See `r3f-shaders` for detailed shader material usage.
|
|
532
|
+
|
|
533
|
+
```tsx
|
|
534
|
+
import { shaderMaterial } from '@react-three/drei'
|
|
535
|
+
import { extend } from '@react-three/fiber'
|
|
536
|
+
|
|
537
|
+
const CustomMaterial = shaderMaterial(
|
|
538
|
+
{ time: 0, color: new THREE.Color('hotpink') },
|
|
539
|
+
// Vertex shader
|
|
540
|
+
`
|
|
541
|
+
varying vec2 vUv;
|
|
542
|
+
void main() {
|
|
543
|
+
vUv = uv;
|
|
544
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
545
|
+
}
|
|
546
|
+
`,
|
|
547
|
+
// Fragment shader
|
|
548
|
+
`
|
|
549
|
+
uniform float time;
|
|
550
|
+
uniform vec3 color;
|
|
551
|
+
varying vec2 vUv;
|
|
552
|
+
void main() {
|
|
553
|
+
gl_FragColor = vec4(color * (sin(time + vUv.x * 10.0) * 0.5 + 0.5), 1.0);
|
|
554
|
+
}
|
|
555
|
+
`
|
|
556
|
+
)
|
|
557
|
+
|
|
558
|
+
extend({ CustomMaterial })
|
|
559
|
+
|
|
560
|
+
function CustomShaderMesh() {
|
|
561
|
+
const materialRef = useRef()
|
|
562
|
+
|
|
563
|
+
useFrame(({ clock }) => {
|
|
564
|
+
materialRef.current.time = clock.elapsedTime
|
|
565
|
+
})
|
|
566
|
+
|
|
567
|
+
return (
|
|
568
|
+
<mesh>
|
|
569
|
+
<boxGeometry />
|
|
570
|
+
<customMaterial ref={materialRef} />
|
|
571
|
+
</mesh>
|
|
572
|
+
)
|
|
573
|
+
}
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
## Performance Tips
|
|
577
|
+
|
|
578
|
+
1. **Reuse materials**: Same material instance = batched draw calls
|
|
579
|
+
2. **Avoid transparent**: Requires sorting, slower
|
|
580
|
+
3. **Use alphaTest over transparent**: When possible, faster
|
|
581
|
+
4. **Simpler materials**: Basic > Lambert > Phong > Standard > Physical
|
|
582
|
+
5. **Limit texture sizes**: 1024-2048 usually sufficient
|
|
583
|
+
|
|
584
|
+
```tsx
|
|
585
|
+
// Material caching pattern
|
|
586
|
+
const materialCache = new Map()
|
|
587
|
+
|
|
588
|
+
function getCachedMaterial(color) {
|
|
589
|
+
const key = color.toString()
|
|
590
|
+
if (!materialCache.has(key)) {
|
|
591
|
+
materialCache.set(key, new THREE.MeshStandardMaterial({ color }))
|
|
592
|
+
}
|
|
593
|
+
return materialCache.get(key)
|
|
594
|
+
}
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
## See Also
|
|
598
|
+
|
|
599
|
+
- `r3f-textures` - Texture loading and configuration
|
|
600
|
+
- `r3f-shaders` - Custom shader development
|
|
601
|
+
- `r3f-lighting` - Light interaction with materials
|