create-threejs-game 1.0.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.
- package/README.md +97 -0
- package/bin/cli.js +370 -0
- package/package.json +29 -0
- package/template/.claude/skills/threejs-animation/SKILL.md +552 -0
- package/template/.claude/skills/threejs-fundamentals/SKILL.md +488 -0
- package/template/.claude/skills/threejs-geometry/SKILL.md +548 -0
- package/template/.claude/skills/threejs-interaction/SKILL.md +660 -0
- package/template/.claude/skills/threejs-lighting/SKILL.md +481 -0
- package/template/.claude/skills/threejs-loaders/SKILL.md +623 -0
- package/template/.claude/skills/threejs-materials/SKILL.md +520 -0
- package/template/.claude/skills/threejs-postprocessing/SKILL.md +602 -0
- package/template/.claude/skills/threejs-shaders/SKILL.md +642 -0
- package/template/.claude/skills/threejs-textures/SKILL.md +628 -0
- package/template/.codex/skills/threejs-animation/SKILL.md +552 -0
- package/template/.codex/skills/threejs-fundamentals/SKILL.md +488 -0
- package/template/.codex/skills/threejs-geometry/SKILL.md +548 -0
- package/template/.codex/skills/threejs-interaction/SKILL.md +660 -0
- package/template/.codex/skills/threejs-lighting/SKILL.md +481 -0
- package/template/.codex/skills/threejs-loaders/SKILL.md +623 -0
- package/template/.codex/skills/threejs-materials/SKILL.md +520 -0
- package/template/.codex/skills/threejs-postprocessing/SKILL.md +602 -0
- package/template/.codex/skills/threejs-shaders/SKILL.md +642 -0
- package/template/.codex/skills/threejs-textures/SKILL.md +628 -0
- package/template/README.md +352 -0
- package/template/docs/.gitkeep +0 -0
- package/template/plans/.gitkeep +0 -0
- package/template/prompts/01-mockup-generation.md +44 -0
- package/template/prompts/02-prd-generation.md +119 -0
- package/template/prompts/03-tdd-generation.md +127 -0
- package/template/prompts/04-execution-plan.md +89 -0
- package/template/prompts/05-implementation.md +61 -0
- package/template/public/assets/.gitkeep +0 -0
- package/template/scripts/config.example.json +12 -0
- package/template/scripts/generate-assets-json.js +149 -0
- package/template/scripts/generate-mockup.js +197 -0
- package/template/scripts/generate-plan.js +295 -0
- package/template/scripts/generate-prd.js +297 -0
- package/template/scripts/generate-tdd.js +283 -0
- package/template/scripts/pipeline.js +229 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: threejs-materials
|
|
3
|
+
description: Three.js materials - PBR, basic, phong, shader materials, material properties. Use when styling meshes, working with textures, creating custom shaders, or optimizing material performance.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Three.js Materials
|
|
7
|
+
|
|
8
|
+
## Quick Start
|
|
9
|
+
|
|
10
|
+
```javascript
|
|
11
|
+
import * as THREE from "three";
|
|
12
|
+
|
|
13
|
+
// PBR material (recommended for realistic rendering)
|
|
14
|
+
const material = new THREE.MeshStandardMaterial({
|
|
15
|
+
color: 0x00ff00,
|
|
16
|
+
roughness: 0.5,
|
|
17
|
+
metalness: 0.5,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const mesh = new THREE.Mesh(geometry, material);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Material Types Overview
|
|
24
|
+
|
|
25
|
+
| Material | Use Case | Lighting |
|
|
26
|
+
| -------------------- | ------------------------------------- | ------------------ |
|
|
27
|
+
| MeshBasicMaterial | Unlit, flat colors, wireframes | No |
|
|
28
|
+
| MeshLambertMaterial | Matte surfaces, performance | Yes (diffuse only) |
|
|
29
|
+
| MeshPhongMaterial | Shiny surfaces, specular highlights | Yes |
|
|
30
|
+
| MeshStandardMaterial | PBR, realistic materials | Yes (PBR) |
|
|
31
|
+
| MeshPhysicalMaterial | Advanced PBR, clearcoat, transmission | Yes (PBR+) |
|
|
32
|
+
| MeshToonMaterial | Cel-shaded, cartoon look | Yes (toon) |
|
|
33
|
+
| MeshNormalMaterial | Debug normals | No |
|
|
34
|
+
| MeshDepthMaterial | Depth visualization | No |
|
|
35
|
+
| ShaderMaterial | Custom GLSL shaders | Custom |
|
|
36
|
+
| RawShaderMaterial | Full shader control | Custom |
|
|
37
|
+
|
|
38
|
+
## MeshBasicMaterial
|
|
39
|
+
|
|
40
|
+
No lighting calculations. Fast, always visible.
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
const material = new THREE.MeshBasicMaterial({
|
|
44
|
+
color: 0xff0000,
|
|
45
|
+
transparent: true,
|
|
46
|
+
opacity: 0.5,
|
|
47
|
+
side: THREE.DoubleSide, // FrontSide, BackSide, DoubleSide
|
|
48
|
+
wireframe: false,
|
|
49
|
+
map: texture, // Color/diffuse texture
|
|
50
|
+
alphaMap: alphaTexture, // Transparency texture
|
|
51
|
+
envMap: envTexture, // Reflection texture
|
|
52
|
+
reflectivity: 1, // Env map intensity
|
|
53
|
+
fog: true, // Affected by scene fog
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## MeshLambertMaterial
|
|
58
|
+
|
|
59
|
+
Diffuse-only lighting. Fast, no specular highlights.
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
const material = new THREE.MeshLambertMaterial({
|
|
63
|
+
color: 0x00ff00,
|
|
64
|
+
emissive: 0x111111, // Self-illumination color
|
|
65
|
+
emissiveIntensity: 1,
|
|
66
|
+
map: texture,
|
|
67
|
+
emissiveMap: emissiveTexture,
|
|
68
|
+
envMap: envTexture,
|
|
69
|
+
reflectivity: 0.5,
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## MeshPhongMaterial
|
|
74
|
+
|
|
75
|
+
Specular highlights. Good for shiny, plastic-like surfaces.
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
const material = new THREE.MeshPhongMaterial({
|
|
79
|
+
color: 0x0000ff,
|
|
80
|
+
specular: 0xffffff, // Highlight color
|
|
81
|
+
shininess: 100, // Highlight sharpness (0-1000)
|
|
82
|
+
emissive: 0x000000,
|
|
83
|
+
flatShading: false, // Flat vs smooth shading
|
|
84
|
+
map: texture,
|
|
85
|
+
specularMap: specTexture, // Per-pixel shininess
|
|
86
|
+
normalMap: normalTexture,
|
|
87
|
+
normalScale: new THREE.Vector2(1, 1),
|
|
88
|
+
bumpMap: bumpTexture,
|
|
89
|
+
bumpScale: 1,
|
|
90
|
+
displacementMap: dispTexture,
|
|
91
|
+
displacementScale: 1,
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## MeshStandardMaterial (PBR)
|
|
96
|
+
|
|
97
|
+
Physically-based rendering. Recommended for realistic results.
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
const material = new THREE.MeshStandardMaterial({
|
|
101
|
+
color: 0xffffff,
|
|
102
|
+
roughness: 0.5, // 0 = mirror, 1 = diffuse
|
|
103
|
+
metalness: 0.0, // 0 = dielectric, 1 = metal
|
|
104
|
+
|
|
105
|
+
// Textures
|
|
106
|
+
map: colorTexture, // Albedo/base color
|
|
107
|
+
roughnessMap: roughTexture, // Per-pixel roughness
|
|
108
|
+
metalnessMap: metalTexture, // Per-pixel metalness
|
|
109
|
+
normalMap: normalTexture, // Surface detail
|
|
110
|
+
normalScale: new THREE.Vector2(1, 1),
|
|
111
|
+
aoMap: aoTexture, // Ambient occlusion (uses uv2!)
|
|
112
|
+
aoMapIntensity: 1,
|
|
113
|
+
displacementMap: dispTexture, // Vertex displacement
|
|
114
|
+
displacementScale: 0.1,
|
|
115
|
+
displacementBias: 0,
|
|
116
|
+
|
|
117
|
+
// Emissive
|
|
118
|
+
emissive: 0x000000,
|
|
119
|
+
emissiveIntensity: 1,
|
|
120
|
+
emissiveMap: emissiveTexture,
|
|
121
|
+
|
|
122
|
+
// Environment
|
|
123
|
+
envMap: envTexture,
|
|
124
|
+
envMapIntensity: 1,
|
|
125
|
+
|
|
126
|
+
// Other
|
|
127
|
+
flatShading: false,
|
|
128
|
+
wireframe: false,
|
|
129
|
+
fog: true,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Note: aoMap requires second UV channel
|
|
133
|
+
geometry.setAttribute("uv2", geometry.attributes.uv);
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## MeshPhysicalMaterial (Advanced PBR)
|
|
137
|
+
|
|
138
|
+
Extends MeshStandardMaterial with advanced features.
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
const material = new THREE.MeshPhysicalMaterial({
|
|
142
|
+
// All MeshStandardMaterial properties plus:
|
|
143
|
+
|
|
144
|
+
// Clearcoat (car paint, lacquer)
|
|
145
|
+
clearcoat: 1.0, // 0-1 clearcoat layer strength
|
|
146
|
+
clearcoatRoughness: 0.1,
|
|
147
|
+
clearcoatMap: ccTexture,
|
|
148
|
+
clearcoatRoughnessMap: ccrTexture,
|
|
149
|
+
clearcoatNormalMap: ccnTexture,
|
|
150
|
+
clearcoatNormalScale: new THREE.Vector2(1, 1),
|
|
151
|
+
|
|
152
|
+
// Transmission (glass, water)
|
|
153
|
+
transmission: 1.0, // 0 = opaque, 1 = fully transparent
|
|
154
|
+
transmissionMap: transTexture,
|
|
155
|
+
thickness: 0.5, // Volume thickness for refraction
|
|
156
|
+
thicknessMap: thickTexture,
|
|
157
|
+
attenuationDistance: 1, // Absorption distance
|
|
158
|
+
attenuationColor: new THREE.Color(0xffffff),
|
|
159
|
+
|
|
160
|
+
// Refraction
|
|
161
|
+
ior: 1.5, // Index of refraction (1-2.333)
|
|
162
|
+
|
|
163
|
+
// Sheen (fabric, velvet)
|
|
164
|
+
sheen: 1.0,
|
|
165
|
+
sheenRoughness: 0.5,
|
|
166
|
+
sheenColor: new THREE.Color(0xffffff),
|
|
167
|
+
sheenColorMap: sheenTexture,
|
|
168
|
+
sheenRoughnessMap: sheenRoughTexture,
|
|
169
|
+
|
|
170
|
+
// Iridescence (soap bubbles, oil slicks)
|
|
171
|
+
iridescence: 1.0,
|
|
172
|
+
iridescenceIOR: 1.3,
|
|
173
|
+
iridescenceThicknessRange: [100, 400],
|
|
174
|
+
iridescenceMap: iridTexture,
|
|
175
|
+
iridescenceThicknessMap: iridThickTexture,
|
|
176
|
+
|
|
177
|
+
// Anisotropy (brushed metal)
|
|
178
|
+
anisotropy: 1.0,
|
|
179
|
+
anisotropyRotation: 0,
|
|
180
|
+
anisotropyMap: anisoTexture,
|
|
181
|
+
|
|
182
|
+
// Specular
|
|
183
|
+
specularIntensity: 1,
|
|
184
|
+
specularColor: new THREE.Color(0xffffff),
|
|
185
|
+
specularIntensityMap: specIntTexture,
|
|
186
|
+
specularColorMap: specColorTexture,
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Glass Material Example
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
const glass = new THREE.MeshPhysicalMaterial({
|
|
194
|
+
color: 0xffffff,
|
|
195
|
+
metalness: 0,
|
|
196
|
+
roughness: 0,
|
|
197
|
+
transmission: 1,
|
|
198
|
+
thickness: 0.5,
|
|
199
|
+
ior: 1.5,
|
|
200
|
+
envMapIntensity: 1,
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Car Paint Example
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
const carPaint = new THREE.MeshPhysicalMaterial({
|
|
208
|
+
color: 0xff0000,
|
|
209
|
+
metalness: 0.9,
|
|
210
|
+
roughness: 0.5,
|
|
211
|
+
clearcoat: 1,
|
|
212
|
+
clearcoatRoughness: 0.1,
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## MeshToonMaterial
|
|
217
|
+
|
|
218
|
+
Cel-shaded cartoon look.
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
const material = new THREE.MeshToonMaterial({
|
|
222
|
+
color: 0x00ff00,
|
|
223
|
+
gradientMap: gradientTexture, // Optional: custom shading gradient
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// Create step gradient texture
|
|
227
|
+
const colors = new Uint8Array([0, 128, 255]);
|
|
228
|
+
const gradientMap = new THREE.DataTexture(colors, 3, 1, THREE.RedFormat);
|
|
229
|
+
gradientMap.minFilter = THREE.NearestFilter;
|
|
230
|
+
gradientMap.magFilter = THREE.NearestFilter;
|
|
231
|
+
gradientMap.needsUpdate = true;
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## MeshNormalMaterial
|
|
235
|
+
|
|
236
|
+
Visualize surface normals. Useful for debugging.
|
|
237
|
+
|
|
238
|
+
```javascript
|
|
239
|
+
const material = new THREE.MeshNormalMaterial({
|
|
240
|
+
flatShading: false,
|
|
241
|
+
wireframe: false,
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## MeshDepthMaterial
|
|
246
|
+
|
|
247
|
+
Render depth values. Used for shadow maps, DOF effects.
|
|
248
|
+
|
|
249
|
+
```javascript
|
|
250
|
+
const material = new THREE.MeshDepthMaterial({
|
|
251
|
+
depthPacking: THREE.RGBADepthPacking,
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## PointsMaterial
|
|
256
|
+
|
|
257
|
+
For point clouds.
|
|
258
|
+
|
|
259
|
+
```javascript
|
|
260
|
+
const material = new THREE.PointsMaterial({
|
|
261
|
+
color: 0xffffff,
|
|
262
|
+
size: 0.1,
|
|
263
|
+
sizeAttenuation: true, // Scale with distance
|
|
264
|
+
map: pointTexture,
|
|
265
|
+
alphaMap: alphaTexture,
|
|
266
|
+
transparent: true,
|
|
267
|
+
alphaTest: 0.5, // Discard pixels below threshold
|
|
268
|
+
vertexColors: true, // Use per-vertex colors
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
const points = new THREE.Points(geometry, material);
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## LineBasicMaterial & LineDashedMaterial
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
// Solid lines
|
|
278
|
+
const lineMaterial = new THREE.LineBasicMaterial({
|
|
279
|
+
color: 0xffffff,
|
|
280
|
+
linewidth: 1, // Note: >1 only works on some systems
|
|
281
|
+
linecap: "round",
|
|
282
|
+
linejoin: "round",
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Dashed lines
|
|
286
|
+
const dashedMaterial = new THREE.LineDashedMaterial({
|
|
287
|
+
color: 0xffffff,
|
|
288
|
+
dashSize: 0.5,
|
|
289
|
+
gapSize: 0.25,
|
|
290
|
+
scale: 1,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// Required for dashed lines
|
|
294
|
+
const line = new THREE.Line(geometry, dashedMaterial);
|
|
295
|
+
line.computeLineDistances();
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## ShaderMaterial
|
|
299
|
+
|
|
300
|
+
Custom GLSL shaders with Three.js uniforms.
|
|
301
|
+
|
|
302
|
+
```javascript
|
|
303
|
+
const material = new THREE.ShaderMaterial({
|
|
304
|
+
uniforms: {
|
|
305
|
+
time: { value: 0 },
|
|
306
|
+
color: { value: new THREE.Color(0xff0000) },
|
|
307
|
+
texture1: { value: texture },
|
|
308
|
+
},
|
|
309
|
+
vertexShader: `
|
|
310
|
+
varying vec2 vUv;
|
|
311
|
+
uniform float time;
|
|
312
|
+
|
|
313
|
+
void main() {
|
|
314
|
+
vUv = uv;
|
|
315
|
+
vec3 pos = position;
|
|
316
|
+
pos.z += sin(pos.x * 10.0 + time) * 0.1;
|
|
317
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
|
|
318
|
+
}
|
|
319
|
+
`,
|
|
320
|
+
fragmentShader: `
|
|
321
|
+
varying vec2 vUv;
|
|
322
|
+
uniform vec3 color;
|
|
323
|
+
uniform sampler2D texture1;
|
|
324
|
+
|
|
325
|
+
void main() {
|
|
326
|
+
// Use texture2D() for GLSL 1.0, texture() for GLSL 3.0 (glslVersion: THREE.GLSL3)
|
|
327
|
+
vec4 texColor = texture2D(texture1, vUv);
|
|
328
|
+
gl_FragColor = vec4(color * texColor.rgb, 1.0);
|
|
329
|
+
}
|
|
330
|
+
`,
|
|
331
|
+
transparent: true,
|
|
332
|
+
side: THREE.DoubleSide,
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Update uniform in animation loop
|
|
336
|
+
material.uniforms.time.value = clock.getElapsedTime();
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Built-in Uniforms (auto-provided)
|
|
340
|
+
|
|
341
|
+
```glsl
|
|
342
|
+
// Vertex shader
|
|
343
|
+
uniform mat4 modelMatrix; // Object to world
|
|
344
|
+
uniform mat4 modelViewMatrix; // Object to camera
|
|
345
|
+
uniform mat4 projectionMatrix; // Camera projection
|
|
346
|
+
uniform mat4 viewMatrix; // World to camera
|
|
347
|
+
uniform mat3 normalMatrix; // For transforming normals
|
|
348
|
+
uniform vec3 cameraPosition; // Camera world position
|
|
349
|
+
|
|
350
|
+
// Attributes
|
|
351
|
+
attribute vec3 position;
|
|
352
|
+
attribute vec3 normal;
|
|
353
|
+
attribute vec2 uv;
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## RawShaderMaterial
|
|
357
|
+
|
|
358
|
+
Full control - no built-in uniforms/attributes.
|
|
359
|
+
|
|
360
|
+
```javascript
|
|
361
|
+
const material = new THREE.RawShaderMaterial({
|
|
362
|
+
uniforms: {
|
|
363
|
+
projectionMatrix: { value: camera.projectionMatrix },
|
|
364
|
+
modelViewMatrix: { value: new THREE.Matrix4() },
|
|
365
|
+
},
|
|
366
|
+
vertexShader: `
|
|
367
|
+
precision highp float;
|
|
368
|
+
attribute vec3 position;
|
|
369
|
+
uniform mat4 projectionMatrix;
|
|
370
|
+
uniform mat4 modelViewMatrix;
|
|
371
|
+
|
|
372
|
+
void main() {
|
|
373
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
374
|
+
}
|
|
375
|
+
`,
|
|
376
|
+
fragmentShader: `
|
|
377
|
+
precision highp float;
|
|
378
|
+
|
|
379
|
+
void main() {
|
|
380
|
+
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
|
381
|
+
}
|
|
382
|
+
`,
|
|
383
|
+
});
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Common Material Properties
|
|
387
|
+
|
|
388
|
+
All materials share these base properties:
|
|
389
|
+
|
|
390
|
+
```javascript
|
|
391
|
+
// Visibility
|
|
392
|
+
material.visible = true;
|
|
393
|
+
material.transparent = false;
|
|
394
|
+
material.opacity = 1.0;
|
|
395
|
+
material.alphaTest = 0; // Discard pixels with alpha < value
|
|
396
|
+
|
|
397
|
+
// Rendering
|
|
398
|
+
material.side = THREE.FrontSide; // FrontSide, BackSide, DoubleSide
|
|
399
|
+
material.depthTest = true;
|
|
400
|
+
material.depthWrite = true;
|
|
401
|
+
material.colorWrite = true;
|
|
402
|
+
|
|
403
|
+
// Blending
|
|
404
|
+
material.blending = THREE.NormalBlending;
|
|
405
|
+
// NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending
|
|
406
|
+
|
|
407
|
+
// Stencil
|
|
408
|
+
material.stencilWrite = false;
|
|
409
|
+
material.stencilFunc = THREE.AlwaysStencilFunc;
|
|
410
|
+
material.stencilRef = 0;
|
|
411
|
+
material.stencilMask = 0xff;
|
|
412
|
+
|
|
413
|
+
// Polygon offset (z-fighting fix)
|
|
414
|
+
material.polygonOffset = false;
|
|
415
|
+
material.polygonOffsetFactor = 0;
|
|
416
|
+
material.polygonOffsetUnits = 0;
|
|
417
|
+
|
|
418
|
+
// Misc
|
|
419
|
+
material.dithering = false;
|
|
420
|
+
material.toneMapped = true;
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
## Multiple Materials
|
|
424
|
+
|
|
425
|
+
```javascript
|
|
426
|
+
// Assign different materials to geometry groups
|
|
427
|
+
const geometry = new THREE.BoxGeometry(1, 1, 1);
|
|
428
|
+
const materials = [
|
|
429
|
+
new THREE.MeshBasicMaterial({ color: 0xff0000 }), // right
|
|
430
|
+
new THREE.MeshBasicMaterial({ color: 0x00ff00 }), // left
|
|
431
|
+
new THREE.MeshBasicMaterial({ color: 0x0000ff }), // top
|
|
432
|
+
new THREE.MeshBasicMaterial({ color: 0xffff00 }), // bottom
|
|
433
|
+
new THREE.MeshBasicMaterial({ color: 0xff00ff }), // front
|
|
434
|
+
new THREE.MeshBasicMaterial({ color: 0x00ffff }), // back
|
|
435
|
+
];
|
|
436
|
+
const mesh = new THREE.Mesh(geometry, materials);
|
|
437
|
+
|
|
438
|
+
// Custom groups
|
|
439
|
+
geometry.clearGroups();
|
|
440
|
+
geometry.addGroup(0, 6, 0); // start, count, materialIndex
|
|
441
|
+
geometry.addGroup(6, 6, 1);
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
## Environment Maps
|
|
445
|
+
|
|
446
|
+
```javascript
|
|
447
|
+
// Load cube texture
|
|
448
|
+
const cubeLoader = new THREE.CubeTextureLoader();
|
|
449
|
+
const envMap = cubeLoader.load([
|
|
450
|
+
"px.jpg",
|
|
451
|
+
"nx.jpg", // positive/negative X
|
|
452
|
+
"py.jpg",
|
|
453
|
+
"ny.jpg", // positive/negative Y
|
|
454
|
+
"pz.jpg",
|
|
455
|
+
"nz.jpg", // positive/negative Z
|
|
456
|
+
]);
|
|
457
|
+
|
|
458
|
+
// Apply to material
|
|
459
|
+
material.envMap = envMap;
|
|
460
|
+
material.envMapIntensity = 1;
|
|
461
|
+
|
|
462
|
+
// Or set as scene environment (affects all PBR materials)
|
|
463
|
+
scene.environment = envMap;
|
|
464
|
+
|
|
465
|
+
// HDR environment (recommended)
|
|
466
|
+
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
|
|
467
|
+
const rgbeLoader = new RGBELoader();
|
|
468
|
+
rgbeLoader.load("environment.hdr", (texture) => {
|
|
469
|
+
texture.mapping = THREE.EquirectangularReflectionMapping;
|
|
470
|
+
scene.environment = texture;
|
|
471
|
+
scene.background = texture;
|
|
472
|
+
});
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
## Material Cloning and Modification
|
|
476
|
+
|
|
477
|
+
```javascript
|
|
478
|
+
// Clone material
|
|
479
|
+
const clone = material.clone();
|
|
480
|
+
clone.color.set(0x00ff00);
|
|
481
|
+
|
|
482
|
+
// Modify at runtime
|
|
483
|
+
material.color.set(0xff0000);
|
|
484
|
+
material.needsUpdate = true; // Only needed for some changes
|
|
485
|
+
|
|
486
|
+
// When needsUpdate is required:
|
|
487
|
+
// - Changing flat shading
|
|
488
|
+
// - Changing texture
|
|
489
|
+
// - Changing transparent
|
|
490
|
+
// - Custom shader code changes
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
## Performance Tips
|
|
494
|
+
|
|
495
|
+
1. **Reuse materials**: Same material = batched draw calls
|
|
496
|
+
2. **Avoid transparent when possible**: Transparent materials require sorting
|
|
497
|
+
3. **Use alphaTest instead of transparency**: When applicable, faster
|
|
498
|
+
4. **Choose simpler materials**: Basic > Lambert > Phong > Standard > Physical
|
|
499
|
+
5. **Limit active lights**: Each light adds shader complexity
|
|
500
|
+
|
|
501
|
+
```javascript
|
|
502
|
+
// Material pooling
|
|
503
|
+
const materialCache = new Map();
|
|
504
|
+
function getMaterial(color) {
|
|
505
|
+
const key = color.toString(16);
|
|
506
|
+
if (!materialCache.has(key)) {
|
|
507
|
+
materialCache.set(key, new THREE.MeshStandardMaterial({ color }));
|
|
508
|
+
}
|
|
509
|
+
return materialCache.get(key);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Dispose when done
|
|
513
|
+
material.dispose();
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
## See Also
|
|
517
|
+
|
|
518
|
+
- `threejs-textures` - Texture loading and configuration
|
|
519
|
+
- `threejs-shaders` - Custom shader development
|
|
520
|
+
- `threejs-lighting` - Light interaction with materials
|