shader知识点
约 1100 字大约 4 分钟
2025-05-07
GLSL 函数
算术函数
| 函数名 | 描述 |
|---|---|
| abs(x) | 返回 x 的绝对值 |
| sign(x) | 返回 x 的符号,如果 x 是正数,返回 1;如果 x 是负数,返回-1;如果 x 是 0,返回 0 |
| floor(x) | 返回小于等于 x 的最大整数 |
| ceil(x) | 返回大于等于 x 的最小整数 |
| fract(x) | 返回 x 的小数部分 |
| mod(x,y) | 返回 x 除以 y 的余数 |
| max(x,y) | 返回 x 和 y 中的最大值 |
| min(x,y) | 返回 x 和 y 中的最小值 |
| mix(x,y,a) | 返回 x 和 y 的线性混合,a 是混合因子 |
| clamp(x,min,max) | 返回 x 被限制在 min 和 max 之间的值 |
| step(edge,x) | 如果 x 小于等于 edge,返回 0;否则返回 1 |
| smoothstep(edge0,edge1,x) | 返回 x 在 edge0 和 edge1 之间的平滑插值 |
几何函数
| 函数名 | 描述 |
|---|---|
| length(v) | 返回向量 v 的长度 |
| distance(v1,v2) | 返回向量 v1 和 v2 之间的距离 |
| dot(v1,v2) | 返回向量 v1 和 v2 的点积 |
| cross(v1,v2) | 返回向量 v1 和 v2 的叉积 |
| normalize(v) | 返回向量 v 的单位向量 |
| faceforward(n,i,nref) | 返回向量 n 的反射向量,i 是入射向量,nref 是法线向量 |
| reflect(i,n) | 返回向量 i 的反射向量,n 是法线向量 |
| refract(i,n,eta) | 返回向量 i 的折射向量,n 是法线向量,eta 是折射率 |
三角函数
| 函数名 | 描述 |
|---|---|
| radians(x) | 将角度 x 转换为弧度 |
| degrees(x) | 将弧度 x 转换为角度 |
| sin(x) | 返回 x 的正弦值 |
| cos(x) | 返回 x 的余弦值 |
| tan(x) | 返回 x 的正切值 |
| asin(x) | 返回 x 的反正弦值 |
| acos(x) | 返回 x 的反余弦值 |
| atan(y,x) | 返回 y/x 的反正切值 |
| sinh(x) | 返回 x 的双曲正弦值 |
| cosh(x) | 返回 x 的双曲余弦值 |
| tanh(x) | 返回 x 的双曲正切值 |
纹理函数
| 函数名 | 描述 |
|---|---|
| texture2D(s,v) | 从纹理 s 中采样,v 是纹理坐标,返回纹理的颜色值 |
| texture2DProj(s,v) | 从纹理 s 中采样,v 是投影纹理坐标,返回纹理的颜色值 |
| textureCube(s,v) | 从立方体纹理 s 中采样,v 是纹理坐标,返回纹理的颜色值 |
向量和矩阵函数
| 函数名 | 描述 |
|---|---|
| matrixCompMult(m1,m2) | 返回 m1 和 m2 的元素乘积 |
| outerProduct(u,v) | 返回向量 u 和 v 的外积 |
| transpose(m) | 返回矩阵 m 的转置矩阵 |
| determinant(m) | 返回矩阵 m 的行列式 |
| inverse(m) | 返回矩阵 m 的逆矩阵 |
着色器材质
ShaderMaterial:自定义着色器材质,可以完全控制顶点着色器和片元着色器的代码。
RawShaderMaterial:原始着色器材质,可以完全控制顶点着色器和片元着色器的代码,不会自动添加内置代码需要手动管理
uniform变量。
差异
ShaderMaterial 和 RawShaderMaterial 都是 Threejs 中用于自定义着色器的材质,他们的主要差异在于 Threejs 对着色器代码的处理方式。
ShaderMaterial 会自动添加常用的 GLSL 代码和变量,而 RawShaderMaterial 则要求开发者完全手动编写所有 GLSL 代码。
// ShaderMaterial
const material = new THREE.ShaderMaterial({
vertexShader: `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
});
// RawShaderMaterial
const material = new THREE.RawShaderMaterial({
vertexShader: `
attribute vec3 position;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
});自定义 uniforms
在 Threejs 中,uniforms 是一种特殊的变量,可以在着色器中访问,并且可以在 JavaScript 代码中动态更新。uniforms 可以是任何类型,包括标量、向量、矩阵、纹理等。
使用
每个 uniforms 都是一个对象,包含一个 value 属性,例如:
const material = new THREE.ShaderMaterial({
uniforms: {
color: { value: new THREE.Color(0xff0000) },
},
});传递纹理贴图
着色器类型材质不支持 map 属性做纹理贴图,需要使用 uniforms 传递纹理贴图,例如:
const material = new THREE.RawShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
uniforms: {
u_texture:{value:new THREE.TextureLoader().load('texture.jpg');}
}
})这个 u_texture 就是传递给着色器的纹理贴图,可以直接在片元着色器中可以通过 uniform sampler2D u_texture 来访问这个纹理贴图。
uniform sampler2D u_texture;
void main(){
vec4 color = texture2D(u_texture,uv);
gl_FragColor = vec4(1.0,0.0,0.0,1.0)*color; //将纹理贴图的颜色和红色混合
}sampler2D 是采样器类型,texture2D 是用于在片元着色器中对二维纹理采样的函数,uv 是纹理坐标,用于指定在纹理图像中采样的点。