Skip to content

Commit 54d5c85

Browse files
committed
✨ Init shaders note part1
1 parent 7b0a2c7 commit 54d5c85

1 file changed

Lines changed: 184 additions & 0 deletions

File tree

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
---
2+
draft: false
3+
title: Three.js Journey Notes 6 - Shaders Part1
4+
date: 2025-04-03
5+
categories: Learning
6+
comments: true
7+
ShowToc: true
8+
isCJKLanguage: false
9+
---
10+
11+
12+
## What is a shader
13+
14+
- one of the main components of WebGL
15+
- a program written in **GLSL**
16+
- sent to GPU
17+
- Position each vertex of a geometry
18+
- Colorize each visible *"pixel"* (accurately should be using term *"fragment"*) of that geometry
19+
20+
> Then we send a lot of data to the shader such as the vertices coordinates, the mesh transformation, information about the camera and its field of view, parameters like the color, the textures, the lights, the fog, etc. The GPU then processes all of this data following the shader instructions, and our geometry appears in the render.
21+
22+
Two types of shaders
23+
- **Vertex shader**
24+
- position the vertices of the geometry
25+
- send vertices positions, mesh transformations (its position, rotation, scale), camera information (its position, rotation, and field of view) to GPU
26+
- GPU use these data to project the vertices on a 2D space aka our canvas
27+
- data changes between vertices called **attribute**, like vertex position
28+
- attribute can only be used in vertex shader
29+
- data doesn't change between vertices called **uniform**, like position of the mesh
30+
- uniform can be used in both vertex shader and fragment shader
31+
- vertex shader happens first, and the fragment shader is proceeded
32+
- **Fragment shader**
33+
- color each visible fragment of the geometry
34+
- send data like color by using **uniform**, or
35+
- *send data from vertex shader to fragment shader*, this kind of data is called **varying**
36+
- 中间状态会 get interpolated,比如三角形每个顶点的 color 不一样的话,中间的点的颜色就会混合三种颜色。也不仅是 color 有这种效果
37+
38+
![[Screenshot 2025-04-03 at 11.00.10.png]]
39+
40+
Why creating our own shaders
41+
- Three.js materials are limited
42+
- shaders can be very simple and performant
43+
- can apply post-process
44+
45+
## `RawShaderMaterial`
46+
47+
```javascript
48+
const material = new THREE.RawShaderMaterial({
49+
vertexShader: `
50+
uniform mat4 projectionMatrix;
51+
uniform mat4 viewMatrix;
52+
uniform mat4 modelMatrix;
53+
54+
attribute vec3 position;
55+
56+
void main()
57+
{
58+
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
59+
}
60+
`,
61+
fragmentShader: `
62+
precision mediump float;
63+
64+
void main()
65+
{
66+
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
67+
}
68+
`
69+
})
70+
```
71+
72+
inside `vertexShader` and `fragmentShader` is the GLSL code for shaders.
73+
74+
better to use separate GLSL file for this, add plugins like [vite-plugin-glsl](https://www.npmjs.com/package/vite-plugin-glsl) to make the project can import GLSL file
75+
76+
```javascript
77+
import testVertexShader from './shaders/test/vertex.glsl'
78+
import testFragmentShader from './shaders/test/fragment.glsl'
79+
80+
const material = new THREE.RawShaderMaterial({
81+
vertexShader: testVertexShader,
82+
fragmentShader: testFragmentShader
83+
})
84+
```
85+
86+
## GLSL basics
87+
88+
- stands for OpenGL Shading Language
89+
- types language, close to C language
90+
- no way to log values
91+
- indentation not essential
92+
- semicolon is required, forgetting one will probably result in compilation error
93+
- Variable
94+
- `float` `int` `bool` `vec2` `vec3` `vec4`
95+
- functions
96+
- built-in native functions: as `sin``cos``max``min``pow``exp``mod``clamp`, but also very practical functions like `cross``dot``mix``step``smoothstep``length``distance``reflect``refract``normalize`
97+
- Docs:
98+
- [Shaderific for OpenGL](https://shaderific.com/glsl.html)
99+
- [OpenGL 4.x Reference Pages](https://registry.khronos.org/OpenGL-Refpages/gl4/html/indexflat.php)
100+
- [The Book of Shaders](https://thebookofshaders.com/)
101+
102+
```glsl
103+
float a = 1.0;
104+
float b = 2.0;
105+
float c = a * b;
106+
107+
int d = 2;
108+
float e = b * float(d);
109+
110+
bool foo = true;
111+
bool bar = false;
112+
113+
vec2 foo = vec2(1.0, 2.0); // store 2 coordinates x, y
114+
// foo.x = 1.5;
115+
// foo.y = 3.0;
116+
foo *= 2.0; // will get (2.0, 4.0)
117+
118+
vec3 purpleColor = vec3(0.0);
119+
purpleColor.r = 0.5; // can use r, g, b (alias)
120+
purpleColor.b = 1.0;
121+
122+
123+
// create vec3 from vec2
124+
vec2 foo2 = vec2(1.0, 2.0);
125+
vec3 bar = vec3(foo2, 3.0);
126+
127+
128+
// create vec2 from vec3
129+
vec3 foo3 = vec3(1.0, 2.0, 3.0);
130+
vec2 bar2 = foo.xy; // bar2 will be (x,y), order matters
131+
132+
// vec3, xyzw, rgba
133+
vec4 foo4 = vec4(1.0, 2.0, 3.0, 4.0);
134+
float bar3 = foo4.w; // 4th value. same as foo4.a
135+
136+
// functions
137+
float loremIpsum() {
138+
float a = 1.0;
139+
float b = 2.0;
140+
return a + b;
141+
}
142+
143+
// use function
144+
float result = loremIpsum();
145+
```
146+
147+
## Understanding the vertex shader
148+
149+
```glsl
150+
uniform mat4 projectionMatrix;
151+
uniform mat4 viewMatrix;
152+
uniform mat4 modelMatrix;
153+
attribute vec3 position;
154+
155+
void main()
156+
{
157+
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
158+
// gl_Position.x += 0.5;
159+
// gl_Position.y += 0.5;
160+
}
161+
```
162+
163+
`main` function will be called automatically.
164+
The goal of the instructions in `main` function is to set `gl_Position` properly. And at the end, it's a `vec4`. We can access its `x` `y` `z` `w` properties.
165+
166+
- First retrieve the vertex `position` with `attribute vec3 position;`
167+
- it can be applied for each vertex as `gl_Position = /* ... */ vec4(position, 1.0);`
168+
- 3 matrices transformations
169+
- `modelMatrix` apply transformations relative to Mesh. If we scale, rotate or move the Mesh
170+
- `viewMatrix` apply transformations relative to camera. If we rotate the camera to the left, the vertices should be on the right, if we move the camera in direction of the Mesh, the vertices should get bigger, etc
171+
- `projectionMatrix` finally transform our coordinations into the final clip space coordinations
172+
- read more: [LearnOpenGL - Coordinate Systems](https://learnopengl.com/Getting-started/Coordinate-Systems)
173+
174+
175+
Transforming our plane like wave via using `sin` on `z`
176+
```glsl
177+
void main()
178+
{
179+
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
180+
modelPosition.z += sin(modelPosition.x * 10.0) * 0.1;
181+
182+
// ...
183+
}
184+
```

0 commit comments

Comments
 (0)