Skip to content

Commit 4561aac

Browse files
committed
✨ Add threejs journey notes 2 draft.
1 parent 21365a5 commit 4561aac

2 files changed

Lines changed: 209 additions & 1 deletion

File tree

content/posts/threejs-journey-notes-1-basics.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ date: 2025-02-26
55
categories: Learning
66
comments: true
77
ShowToc: true
8-
isCJKLanguage: true
8+
isCJKLanguage: false
99
---
1010

1111
课程链接:[three.js journey](https://threejs-journey.com/)
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
---
2+
draft: false
3+
title: Three.js Journey Notes 2 - Classic Techniques
4+
date: 2025-03-10
5+
categories: Learning
6+
comments: true
7+
ShowToc: true
8+
isCJKLanguage: false
9+
---
10+
11+
课程链接:[three.js journey](https://threejs-journey.com/)
12+
13+
[Notes 1 - Basics](../threejs-journey-notes-1-basics)
14+
15+
## Lights
16+
17+
basically walk through all lights types to demonstrate them one by one and
18+
feel what they can do.
19+
20+
- [AmbientLight](https://threejs.org/docs/index.html#api/en/lights/AmbientLight)
21+
- applies omnidirectional(全方向的) lighting on all geometries of the scene.
22+
- good to simulate light bouncing around the scene
23+
- cannot be used to cast shadows as it does not have a direction
24+
- [DirectionalLight](https://threejs.org/docs/index.html#api/en/lights/DirectionalLight)
25+
- coming from same direction, parallel, like the Sun
26+
- can cast shadows
27+
- [HemisphereLight](https://threejs.org/docs/index.html#api/en/lights/HemisphereLight)
28+
- similar to the *AmbientLight* but with a *different color* fading from the *sky* to the color coming from the ground.
29+
- Faces facing the sky will be lit by one color while another color will lit faces facing the ground.
30+
- cannot be used to cast shadows
31+
- [PointLight](https://threejs.org/docs/index.html#api/en/lights/PointLight)
32+
- almost like a lighter, light source is infinitely small, and the light spreads uniformly in every direction
33+
- can cast shadows
34+
- [RectAreaLight](https://threejs.org/docs/index.html#api/en/lights/RectAreaLight)
35+
- like a big rectangle lights you can see on the photoshoot set, big plane lighting
36+
- can be used to simulate light sources such as bright windows or strip lighting
37+
- only works with `MeshStandardMaterial` and `MeshPhysicalMaterial`
38+
- cannot be used to cast shadows
39+
- [SpotLight](https://threejs.org/docs/index.html#api/en/lights/SpotLight)
40+
- like flashlight, 手电筒🔦聚光灯效果
41+
- gets emitted from a single point in one direction, along a cone that increases in size the further from the light it gets
42+
- can cast shadows
43+
44+
### Performance
45+
46+
> Add as few lights as possible and try to use the lights that cost less
47+
48+
- Minimal cost:
49+
- AmbientLight
50+
- HemisphereLight
51+
- Moderate cost:
52+
- DirectionalLight
53+
- PointLight
54+
- High cost:
55+
- SpotLight
56+
- RectAreaLight
57+
58+
Another technique is called baking, idea it that you can bake the light into the texture.
59+
So that you can have the effects on the texture as loaded, but it can't be changed when you change the scene.
60+
61+
### Helpers
62+
63+
helpers for positioning and orienting the lights:
64+
- HemisphereLightHelper
65+
- DirectionalLightHelper
66+
- PointLightHelper
67+
- RectAreaLightHelper
68+
- SpotLightHelper
69+
70+
71+
## Shadows
72+
73+
> The back of the objects are indeed in the dark, and this is called the **core shadow**. What we are missing is the **drop shadow**, where objects create shadows on the other objects.
74+
75+
> When you do one render, Three.js will first do a render for each light supposed to cast shadows. Those renders will simulate what the light sees as if it was a camera. During these lights renders, MeshDepthMaterial replaces all meshes materials.
76+
77+
> The results are stored as textures and named shadow maps.
78+
79+
> You won't see those shadow maps directly, but they are used on every material supposed to receive shadows and projected on the geometry.
80+
Here's an excellent example of what the directional light and the spotlight see: https://threejs.org/examples/webgl_shadowmap_viewer.html
81+
82+
简单复述就是 three.js 会当作 camera 使用 MeshDepthMaterial 为 base 保存每一种 light 的模拟出的结果 shadow map,然后当成 texture 渲染出来
83+
84+
Only 3 types of lights supports shadows:
85+
- [PointLight](https://threejs.org/docs/index.html#api/en/lights/PointLight)
86+
- [DirectionalLight](https://threejs.org/docs/index.html#api/en/lights/DirectionalLight)
87+
- [SpotLight](https://threejs.org/docs/index.html#api/en/lights/SpotLight)
88+
89+
90+
```js
91+
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5)
92+
directionalLight.castShadow = true; // to activate shadow
93+
console.log(directionalLight.shadow); // can be accessed directly
94+
95+
// render size
96+
directionalLight.shadow.mapSize.width = 1024
97+
directionalLight.shadow.mapSize.height = 1024
98+
99+
// add camera helper to adjust near and far
100+
directionalLight.shadow.camera.near = 1
101+
directionalLight.shadow.camera.far = 6
102+
const directionalLightCameraHelper = new THREE.CameraHelper(directionalLight.shadow.camera)
103+
scene.add(directionalLightCameraHelper)
104+
105+
directionalLight.shadow.camera.top = 2
106+
directionalLight.shadow.camera.right = 2
107+
directionalLight.shadow.camera.bottom = - 2
108+
directionalLight.shadow.camera.left = - 2
109+
110+
// make shadow blur on edges
111+
directionalLight.shadow.radius = 10
112+
113+
// change shadow map algorithm
114+
renderer.shadowMap.enabled = true
115+
renderer.shadowMap.type = THREE.PCFSoftShadowMap
116+
```
117+
118+
Shadow map optimisations
119+
- render size
120+
- default is 512x512, we can improve it by assign bigger size like 1024x1024 (but cost more)
121+
- near and far
122+
- same as camera's near and far, can use [CameraHelper](https://threejs.org/docs/#api/en/helpers/CameraHelper) to adjust the values
123+
- amplitude
124+
- camera's amplitude
125+
- The smaller the values, the more precise the shadow will be. But if it's too small, the shadows will just be cropped
126+
- blue with `radius` property
127+
- Shadow map algorithm
128+
- **THREE.BasicShadowMap:** Very performant but lousy quality
129+
- **THREE.PCFShadowMap:** Less performant but smoother edges (default)
130+
- **THREE.PCFSoftShadowMap:** Less performant but even softer edges
131+
- **THREE.VSMShadowMap:** Less performant, more constraints, can have unexpected results
132+
133+
Baking shadows, exactly like baking light into textures. But it's static, if the object or the light moves, the shadow won't.
134+
Alternative is to use a more simple shadow under the sphere and slightly above the plane.
135+
It's less realistic but more dynamic.
136+
137+
138+
## Haunted House
139+
140+
完全跟着一步一步做的 demo, [code](https://github.com/bambooom/threejs-journey/blob/main/src/course/chapter2-classic-techniques/16-haunted-house.tsx)
141+
142+
![](https://static.zhuzi.dev/threejs-journey/haunted-house-1.png)
143+
![](https://static.zhuzi.dev/threejs-journey/haunted-house-2.png)
144+
145+
146+
## Particles
147+
148+
popular and can be used to achieve various effects such as stars, smoke, rain, dust, fire, and many other things.
149+
150+
each particle is composed of a plane (two triangles) always facing the camera.
151+
152+
need `BufferGeometry` and `PointsMaterial`, we need to create a [Points](https://threejs.org/docs/#api/en/objects/Points).
153+
154+
155+
```js
156+
// Material
157+
const particlesMaterial = new THREE.PointsMaterial({
158+
size: 0.02,
159+
sizeAttenuation: true
160+
});
161+
162+
// Points
163+
const particles = new THREE.Points(particlesGeometry, particlesMaterial)
164+
scene.add(particles)
165+
```
166+
167+
Custom geometry like space
168+
169+
```js
170+
// Geometry
171+
const particlesGeometry = new THREE.BufferGeometry()
172+
const count = 500
173+
174+
const positions = new Float32Array(count * 3) // Multiply by 3 because each position is composed of 3 values (x, y, z)
175+
176+
for(let i = 0; i < count * 3; i++) // Multiply by 3 for same reason
177+
{
178+
positions[i] = (Math.random() - 0.5) * 10 // Math.random() - 0.5 to have a random value between -0.5 and +0.5
179+
}
180+
181+
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)) // Create the Three.js BufferAttribute and specify that each information is composed of 3 values
182+
183+
184+
// particlesMaterial.alphaTest = 0.001
185+
// particlesMaterial.depthTest = false
186+
particlesMaterial.depthWrite = false
187+
particlesMaterial.blending = THREE.AdditiveBlending
188+
189+
particlesMaterial.vertexColors = true
190+
```
191+
192+
- alphaTest
193+
- value between 0 and 1 that enables the WebGL to know when not to render the pixel according to that pixel's transparency
194+
- depthTest
195+
- WebGL tests if what's being drawn is closer than what's already drawn
196+
- depthWrite
197+
- The depth of what's being drawn is stored in what we call a depth buffer. Instead of not testing if the particle is closer than what's in this depth buffer, we can tell the WebGL not to write particles in that depth buffer
198+
- blending
199+
- tell the WebGL not only to draw the pixel, but also to add the color of that pixel to the color of the pixel already drawn. That will have a saturation effect that can look amazing.
200+
- apply different colors
201+
202+
203+
make a galaxy by particles, [code](https://github.com/bambooom/threejs-journey/blob/main/src/course/chapter2-classic-techniques/18-galaxy-generator.tsx)
204+
205+
206+
![](https://static.zhuzi.dev/threejs-journey/galaxy.png)
207+
208+
[scroll based animation to make web page demo](https://github.com/bambooom/threejs-journey/blob/main/src/course/chapter2-classic-techniques/19-scroll-based-animation.tsx)

0 commit comments

Comments
 (0)