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,481 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: threejs-lighting
|
|
3
|
+
description: Three.js lighting - light types, shadows, environment lighting. Use when adding lights, configuring shadows, setting up IBL, or optimizing lighting performance.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Three.js Lighting
|
|
7
|
+
|
|
8
|
+
## Quick Start
|
|
9
|
+
|
|
10
|
+
```javascript
|
|
11
|
+
import * as THREE from "three";
|
|
12
|
+
|
|
13
|
+
// Basic lighting setup
|
|
14
|
+
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
|
|
15
|
+
scene.add(ambientLight);
|
|
16
|
+
|
|
17
|
+
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
|
|
18
|
+
directionalLight.position.set(5, 5, 5);
|
|
19
|
+
scene.add(directionalLight);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Light Types Overview
|
|
23
|
+
|
|
24
|
+
| Light | Description | Shadow Support | Cost |
|
|
25
|
+
| ---------------- | ---------------------- | -------------- | -------- |
|
|
26
|
+
| AmbientLight | Uniform everywhere | No | Very Low |
|
|
27
|
+
| HemisphereLight | Sky/ground gradient | No | Very Low |
|
|
28
|
+
| DirectionalLight | Parallel rays (sun) | Yes | Low |
|
|
29
|
+
| PointLight | Omnidirectional (bulb) | Yes | Medium |
|
|
30
|
+
| SpotLight | Cone-shaped | Yes | Medium |
|
|
31
|
+
| RectAreaLight | Area light (window) | No\* | High |
|
|
32
|
+
|
|
33
|
+
\*RectAreaLight shadows require custom solutions
|
|
34
|
+
|
|
35
|
+
## AmbientLight
|
|
36
|
+
|
|
37
|
+
Illuminates all objects equally. No direction, no shadows.
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
// AmbientLight(color, intensity)
|
|
41
|
+
const ambient = new THREE.AmbientLight(0xffffff, 0.5);
|
|
42
|
+
scene.add(ambient);
|
|
43
|
+
|
|
44
|
+
// Modify at runtime
|
|
45
|
+
ambient.color.set(0xffffcc);
|
|
46
|
+
ambient.intensity = 0.3;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## HemisphereLight
|
|
50
|
+
|
|
51
|
+
Gradient from sky to ground color. Good for outdoor scenes.
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
// HemisphereLight(skyColor, groundColor, intensity)
|
|
55
|
+
const hemi = new THREE.HemisphereLight(0x87ceeb, 0x8b4513, 0.6);
|
|
56
|
+
hemi.position.set(0, 50, 0);
|
|
57
|
+
scene.add(hemi);
|
|
58
|
+
|
|
59
|
+
// Properties
|
|
60
|
+
hemi.color; // Sky color
|
|
61
|
+
hemi.groundColor; // Ground color
|
|
62
|
+
hemi.intensity;
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## DirectionalLight
|
|
66
|
+
|
|
67
|
+
Parallel light rays. Simulates distant light source (sun).
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
// DirectionalLight(color, intensity)
|
|
71
|
+
const dirLight = new THREE.DirectionalLight(0xffffff, 1);
|
|
72
|
+
dirLight.position.set(5, 10, 5);
|
|
73
|
+
|
|
74
|
+
// Light points at target (default: 0, 0, 0)
|
|
75
|
+
dirLight.target.position.set(0, 0, 0);
|
|
76
|
+
scene.add(dirLight.target);
|
|
77
|
+
|
|
78
|
+
scene.add(dirLight);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### DirectionalLight Shadows
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
dirLight.castShadow = true;
|
|
85
|
+
|
|
86
|
+
// Shadow map size (higher = sharper, more expensive)
|
|
87
|
+
dirLight.shadow.mapSize.width = 2048;
|
|
88
|
+
dirLight.shadow.mapSize.height = 2048;
|
|
89
|
+
|
|
90
|
+
// Shadow camera (orthographic)
|
|
91
|
+
dirLight.shadow.camera.near = 0.5;
|
|
92
|
+
dirLight.shadow.camera.far = 50;
|
|
93
|
+
dirLight.shadow.camera.left = -10;
|
|
94
|
+
dirLight.shadow.camera.right = 10;
|
|
95
|
+
dirLight.shadow.camera.top = 10;
|
|
96
|
+
dirLight.shadow.camera.bottom = -10;
|
|
97
|
+
|
|
98
|
+
// Shadow softness
|
|
99
|
+
dirLight.shadow.radius = 4; // Blur radius (PCFSoftShadowMap only)
|
|
100
|
+
|
|
101
|
+
// Shadow bias (fixes shadow acne)
|
|
102
|
+
dirLight.shadow.bias = -0.0001;
|
|
103
|
+
dirLight.shadow.normalBias = 0.02;
|
|
104
|
+
|
|
105
|
+
// Helper to visualize shadow camera
|
|
106
|
+
const helper = new THREE.CameraHelper(dirLight.shadow.camera);
|
|
107
|
+
scene.add(helper);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## PointLight
|
|
111
|
+
|
|
112
|
+
Emits light in all directions from a point. Like a light bulb.
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
// PointLight(color, intensity, distance, decay)
|
|
116
|
+
const pointLight = new THREE.PointLight(0xffffff, 1, 100, 2);
|
|
117
|
+
pointLight.position.set(0, 5, 0);
|
|
118
|
+
scene.add(pointLight);
|
|
119
|
+
|
|
120
|
+
// Properties
|
|
121
|
+
pointLight.distance; // Maximum range (0 = infinite)
|
|
122
|
+
pointLight.decay; // Light falloff (physically correct = 2)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### PointLight Shadows
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
pointLight.castShadow = true;
|
|
129
|
+
pointLight.shadow.mapSize.width = 1024;
|
|
130
|
+
pointLight.shadow.mapSize.height = 1024;
|
|
131
|
+
|
|
132
|
+
// Shadow camera (perspective - 6 directions for cube map)
|
|
133
|
+
pointLight.shadow.camera.near = 0.5;
|
|
134
|
+
pointLight.shadow.camera.far = 50;
|
|
135
|
+
|
|
136
|
+
pointLight.shadow.bias = -0.005;
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## SpotLight
|
|
140
|
+
|
|
141
|
+
Cone-shaped light. Like a flashlight or stage light.
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
// SpotLight(color, intensity, distance, angle, penumbra, decay)
|
|
145
|
+
const spotLight = new THREE.SpotLight(0xffffff, 1, 100, Math.PI / 6, 0.5, 2);
|
|
146
|
+
spotLight.position.set(0, 10, 0);
|
|
147
|
+
|
|
148
|
+
// Target (light points at this)
|
|
149
|
+
spotLight.target.position.set(0, 0, 0);
|
|
150
|
+
scene.add(spotLight.target);
|
|
151
|
+
|
|
152
|
+
scene.add(spotLight);
|
|
153
|
+
|
|
154
|
+
// Properties
|
|
155
|
+
spotLight.angle; // Cone angle (radians, max Math.PI/2)
|
|
156
|
+
spotLight.penumbra; // Soft edge (0-1)
|
|
157
|
+
spotLight.distance; // Range
|
|
158
|
+
spotLight.decay; // Falloff
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### SpotLight Shadows
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
spotLight.castShadow = true;
|
|
165
|
+
spotLight.shadow.mapSize.width = 1024;
|
|
166
|
+
spotLight.shadow.mapSize.height = 1024;
|
|
167
|
+
|
|
168
|
+
// Shadow camera (perspective)
|
|
169
|
+
spotLight.shadow.camera.near = 0.5;
|
|
170
|
+
spotLight.shadow.camera.far = 50;
|
|
171
|
+
spotLight.shadow.camera.fov = 30;
|
|
172
|
+
|
|
173
|
+
spotLight.shadow.bias = -0.0001;
|
|
174
|
+
|
|
175
|
+
// Focus (affects shadow projection)
|
|
176
|
+
spotLight.shadow.focus = 1;
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## RectAreaLight
|
|
180
|
+
|
|
181
|
+
Rectangular area light. Great for soft, realistic lighting.
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
import { RectAreaLightHelper } from "three/examples/jsm/helpers/RectAreaLightHelper.js";
|
|
185
|
+
import { RectAreaLightUniformsLib } from "three/examples/jsm/lights/RectAreaLightUniformsLib.js";
|
|
186
|
+
|
|
187
|
+
// Must initialize uniforms first
|
|
188
|
+
RectAreaLightUniformsLib.init();
|
|
189
|
+
|
|
190
|
+
// RectAreaLight(color, intensity, width, height)
|
|
191
|
+
const rectLight = new THREE.RectAreaLight(0xffffff, 5, 4, 2);
|
|
192
|
+
rectLight.position.set(0, 5, 0);
|
|
193
|
+
rectLight.lookAt(0, 0, 0);
|
|
194
|
+
scene.add(rectLight);
|
|
195
|
+
|
|
196
|
+
// Helper
|
|
197
|
+
const helper = new RectAreaLightHelper(rectLight);
|
|
198
|
+
rectLight.add(helper);
|
|
199
|
+
|
|
200
|
+
// Note: Only works with MeshStandardMaterial and MeshPhysicalMaterial
|
|
201
|
+
// Does not cast shadows natively
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Shadow Setup
|
|
205
|
+
|
|
206
|
+
### Enable Shadows
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
// 1. Enable on renderer
|
|
210
|
+
renderer.shadowMap.enabled = true;
|
|
211
|
+
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
|
212
|
+
|
|
213
|
+
// Shadow map types:
|
|
214
|
+
// THREE.BasicShadowMap - fastest, low quality
|
|
215
|
+
// THREE.PCFShadowMap - default, filtered
|
|
216
|
+
// THREE.PCFSoftShadowMap - softer edges
|
|
217
|
+
// THREE.VSMShadowMap - variance shadow map
|
|
218
|
+
|
|
219
|
+
// 2. Enable on light
|
|
220
|
+
light.castShadow = true;
|
|
221
|
+
|
|
222
|
+
// 3. Enable on objects
|
|
223
|
+
mesh.castShadow = true;
|
|
224
|
+
mesh.receiveShadow = true;
|
|
225
|
+
|
|
226
|
+
// Ground plane
|
|
227
|
+
floor.receiveShadow = true;
|
|
228
|
+
floor.castShadow = false; // Usually false for floors
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Optimizing Shadows
|
|
232
|
+
|
|
233
|
+
```javascript
|
|
234
|
+
// Tight shadow camera frustum
|
|
235
|
+
const d = 10;
|
|
236
|
+
dirLight.shadow.camera.left = -d;
|
|
237
|
+
dirLight.shadow.camera.right = d;
|
|
238
|
+
dirLight.shadow.camera.top = d;
|
|
239
|
+
dirLight.shadow.camera.bottom = -d;
|
|
240
|
+
dirLight.shadow.camera.near = 0.5;
|
|
241
|
+
dirLight.shadow.camera.far = 30;
|
|
242
|
+
|
|
243
|
+
// Fix shadow acne
|
|
244
|
+
dirLight.shadow.bias = -0.0001; // Depth bias
|
|
245
|
+
dirLight.shadow.normalBias = 0.02; // Bias along normal
|
|
246
|
+
|
|
247
|
+
// Shadow map size (balance quality vs performance)
|
|
248
|
+
// 512 - low quality
|
|
249
|
+
// 1024 - medium quality
|
|
250
|
+
// 2048 - high quality
|
|
251
|
+
// 4096 - very high quality (expensive)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Contact Shadows (Fake, Fast)
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
import { ContactShadows } from "three/examples/jsm/objects/ContactShadows.js";
|
|
258
|
+
|
|
259
|
+
const contactShadows = new ContactShadows({
|
|
260
|
+
resolution: 512,
|
|
261
|
+
blur: 2,
|
|
262
|
+
opacity: 0.5,
|
|
263
|
+
scale: 10,
|
|
264
|
+
position: [0, 0, 0],
|
|
265
|
+
});
|
|
266
|
+
scene.add(contactShadows);
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Light Helpers
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
import { RectAreaLightHelper } from "three/examples/jsm/helpers/RectAreaLightHelper.js";
|
|
273
|
+
|
|
274
|
+
// DirectionalLight helper
|
|
275
|
+
const dirHelper = new THREE.DirectionalLightHelper(dirLight, 5);
|
|
276
|
+
scene.add(dirHelper);
|
|
277
|
+
|
|
278
|
+
// PointLight helper
|
|
279
|
+
const pointHelper = new THREE.PointLightHelper(pointLight, 1);
|
|
280
|
+
scene.add(pointHelper);
|
|
281
|
+
|
|
282
|
+
// SpotLight helper
|
|
283
|
+
const spotHelper = new THREE.SpotLightHelper(spotLight);
|
|
284
|
+
scene.add(spotHelper);
|
|
285
|
+
|
|
286
|
+
// Hemisphere helper
|
|
287
|
+
const hemiHelper = new THREE.HemisphereLightHelper(hemiLight, 5);
|
|
288
|
+
scene.add(hemiHelper);
|
|
289
|
+
|
|
290
|
+
// RectAreaLight helper
|
|
291
|
+
const rectHelper = new RectAreaLightHelper(rectLight);
|
|
292
|
+
rectLight.add(rectHelper);
|
|
293
|
+
|
|
294
|
+
// Update helpers when light changes
|
|
295
|
+
dirHelper.update();
|
|
296
|
+
spotHelper.update();
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## Environment Lighting (IBL)
|
|
300
|
+
|
|
301
|
+
Image-Based Lighting using HDR environment maps.
|
|
302
|
+
|
|
303
|
+
```javascript
|
|
304
|
+
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
|
|
305
|
+
|
|
306
|
+
const rgbeLoader = new RGBELoader();
|
|
307
|
+
rgbeLoader.load("environment.hdr", (texture) => {
|
|
308
|
+
texture.mapping = THREE.EquirectangularReflectionMapping;
|
|
309
|
+
|
|
310
|
+
// Set as scene environment (affects all PBR materials)
|
|
311
|
+
scene.environment = texture;
|
|
312
|
+
|
|
313
|
+
// Optional: also use as background
|
|
314
|
+
scene.background = texture;
|
|
315
|
+
scene.backgroundBlurriness = 0; // 0-1, blur the background
|
|
316
|
+
scene.backgroundIntensity = 1;
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// PMREMGenerator for better reflections
|
|
320
|
+
const pmremGenerator = new THREE.PMREMGenerator(renderer);
|
|
321
|
+
pmremGenerator.compileEquirectangularShader();
|
|
322
|
+
|
|
323
|
+
rgbeLoader.load("environment.hdr", (texture) => {
|
|
324
|
+
const envMap = pmremGenerator.fromEquirectangular(texture).texture;
|
|
325
|
+
scene.environment = envMap;
|
|
326
|
+
texture.dispose();
|
|
327
|
+
pmremGenerator.dispose();
|
|
328
|
+
});
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Cube Texture Environment
|
|
332
|
+
|
|
333
|
+
```javascript
|
|
334
|
+
const cubeLoader = new THREE.CubeTextureLoader();
|
|
335
|
+
const envMap = cubeLoader.load([
|
|
336
|
+
"px.jpg",
|
|
337
|
+
"nx.jpg",
|
|
338
|
+
"py.jpg",
|
|
339
|
+
"ny.jpg",
|
|
340
|
+
"pz.jpg",
|
|
341
|
+
"nz.jpg",
|
|
342
|
+
]);
|
|
343
|
+
|
|
344
|
+
scene.environment = envMap;
|
|
345
|
+
scene.background = envMap;
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## Light Probes (Advanced)
|
|
349
|
+
|
|
350
|
+
Capture lighting from a point in space for ambient lighting.
|
|
351
|
+
|
|
352
|
+
```javascript
|
|
353
|
+
import { LightProbeGenerator } from "three/examples/jsm/lights/LightProbeGenerator.js";
|
|
354
|
+
|
|
355
|
+
// Generate from cube texture
|
|
356
|
+
const lightProbe = new THREE.LightProbe();
|
|
357
|
+
scene.add(lightProbe);
|
|
358
|
+
|
|
359
|
+
lightProbe.copy(LightProbeGenerator.fromCubeTexture(cubeTexture));
|
|
360
|
+
|
|
361
|
+
// Or from render target
|
|
362
|
+
const cubeCamera = new THREE.CubeCamera(
|
|
363
|
+
0.1,
|
|
364
|
+
100,
|
|
365
|
+
new THREE.WebGLCubeRenderTarget(256),
|
|
366
|
+
);
|
|
367
|
+
cubeCamera.update(renderer, scene);
|
|
368
|
+
lightProbe.copy(
|
|
369
|
+
LightProbeGenerator.fromCubeRenderTarget(renderer, cubeCamera.renderTarget),
|
|
370
|
+
);
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Common Lighting Setups
|
|
374
|
+
|
|
375
|
+
### Three-Point Lighting
|
|
376
|
+
|
|
377
|
+
```javascript
|
|
378
|
+
// Key light (main light)
|
|
379
|
+
const keyLight = new THREE.DirectionalLight(0xffffff, 1);
|
|
380
|
+
keyLight.position.set(5, 5, 5);
|
|
381
|
+
scene.add(keyLight);
|
|
382
|
+
|
|
383
|
+
// Fill light (softer, opposite side)
|
|
384
|
+
const fillLight = new THREE.DirectionalLight(0xffffff, 0.5);
|
|
385
|
+
fillLight.position.set(-5, 3, 5);
|
|
386
|
+
scene.add(fillLight);
|
|
387
|
+
|
|
388
|
+
// Back light (rim lighting)
|
|
389
|
+
const backLight = new THREE.DirectionalLight(0xffffff, 0.3);
|
|
390
|
+
backLight.position.set(0, 5, -5);
|
|
391
|
+
scene.add(backLight);
|
|
392
|
+
|
|
393
|
+
// Ambient fill
|
|
394
|
+
const ambient = new THREE.AmbientLight(0x404040, 0.3);
|
|
395
|
+
scene.add(ambient);
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Outdoor Daylight
|
|
399
|
+
|
|
400
|
+
```javascript
|
|
401
|
+
// Sun
|
|
402
|
+
const sun = new THREE.DirectionalLight(0xffffcc, 1.5);
|
|
403
|
+
sun.position.set(50, 100, 50);
|
|
404
|
+
sun.castShadow = true;
|
|
405
|
+
scene.add(sun);
|
|
406
|
+
|
|
407
|
+
// Sky ambient
|
|
408
|
+
const hemi = new THREE.HemisphereLight(0x87ceeb, 0x8b4513, 0.6);
|
|
409
|
+
scene.add(hemi);
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Indoor Studio
|
|
413
|
+
|
|
414
|
+
```javascript
|
|
415
|
+
// Multiple area lights
|
|
416
|
+
RectAreaLightUniformsLib.init();
|
|
417
|
+
|
|
418
|
+
const light1 = new THREE.RectAreaLight(0xffffff, 5, 2, 2);
|
|
419
|
+
light1.position.set(3, 3, 3);
|
|
420
|
+
light1.lookAt(0, 0, 0);
|
|
421
|
+
scene.add(light1);
|
|
422
|
+
|
|
423
|
+
const light2 = new THREE.RectAreaLight(0xffffff, 3, 2, 2);
|
|
424
|
+
light2.position.set(-3, 3, 3);
|
|
425
|
+
light2.lookAt(0, 0, 0);
|
|
426
|
+
scene.add(light2);
|
|
427
|
+
|
|
428
|
+
// Ambient fill
|
|
429
|
+
const ambient = new THREE.AmbientLight(0x404040, 0.2);
|
|
430
|
+
scene.add(ambient);
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## Light Animation
|
|
434
|
+
|
|
435
|
+
```javascript
|
|
436
|
+
const clock = new THREE.Clock();
|
|
437
|
+
|
|
438
|
+
function animate() {
|
|
439
|
+
const time = clock.getElapsedTime();
|
|
440
|
+
|
|
441
|
+
// Orbit light around scene
|
|
442
|
+
light.position.x = Math.cos(time) * 5;
|
|
443
|
+
light.position.z = Math.sin(time) * 5;
|
|
444
|
+
|
|
445
|
+
// Pulsing intensity
|
|
446
|
+
light.intensity = 1 + Math.sin(time * 2) * 0.5;
|
|
447
|
+
|
|
448
|
+
// Color cycling
|
|
449
|
+
light.color.setHSL((time * 0.1) % 1, 1, 0.5);
|
|
450
|
+
|
|
451
|
+
// Update helpers if using
|
|
452
|
+
lightHelper.update();
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
## Performance Tips
|
|
457
|
+
|
|
458
|
+
1. **Limit light count**: Each light adds shader complexity
|
|
459
|
+
2. **Use baked lighting**: For static scenes, bake to textures
|
|
460
|
+
3. **Smaller shadow maps**: 512-1024 often sufficient
|
|
461
|
+
4. **Tight shadow frustums**: Only cover needed area
|
|
462
|
+
5. **Disable unused shadows**: Not all lights need shadows
|
|
463
|
+
6. **Use light layers**: Exclude objects from certain lights
|
|
464
|
+
|
|
465
|
+
```javascript
|
|
466
|
+
// Light layers
|
|
467
|
+
light.layers.set(1); // Light only affects layer 1
|
|
468
|
+
mesh.layers.enable(1); // Mesh is on layer 1
|
|
469
|
+
otherMesh.layers.disable(1); // Other mesh not affected
|
|
470
|
+
|
|
471
|
+
// Selective shadows
|
|
472
|
+
mesh.castShadow = true;
|
|
473
|
+
mesh.receiveShadow = true;
|
|
474
|
+
decorMesh.castShadow = false; // Small objects often don't need to cast
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## See Also
|
|
478
|
+
|
|
479
|
+
- `threejs-materials` - Material light response
|
|
480
|
+
- `threejs-textures` - Lightmaps and environment maps
|
|
481
|
+
- `threejs-postprocessing` - Bloom and other light effects
|