着色器是运行在GPU上的小程序,用于控制3D图形的渲染过程。在Three.js中,主要有两种着色器:
GLSL(OpenGL Shading Language)作为面向图形编程的着色器语言,数据类型体系围绕图形计算需求设计
GLSL支持多种数据类型:
float f = 1.0; // 浮点数
int i = 1; // 整数
bool b = true; // 布尔值
vec2 v2 = vec2(1.0, 2.0); // 2维向量
vec3 v3 = vec3(1.0,2.0,3.0); // 3维向量
vec4 v4 = vec4(v3, 1.0); // 4维向量
mat4 m4 = mat4(1.0); // 4x4矩阵
首先,创建一个基本的Three.js场景
让我们先了解两种着色器的基本结构(示例):
// attribute: 每个顶点特有的数据(位置、法线、UV坐标等)
// uniform: 所有顶点共享的数据(变换矩阵、时间等)
// varying: 从顶点着色器传递到片段着色器的数据
// Three.js会自动提供的变量:
// attribute vec3 position; // 顶点位置
// attribute vec3 normal; // 法线向量
// attribute vec2 uv; // UV坐标
// Three.js会自动提供的uniform:
// uniform mat4 projectionMatrix; // 投影矩阵
// uniform mat4 modelViewMatrix; // 模型视图矩阵
varying vec2 vUv; // 声明一个varying变量,将UV坐标传递到片段着色器
void main() {
vUv = uv; // 传递UV坐标
// 将顶点位置转换为屏幕坐标
// position: 当前顶点的原始位置
// modelViewMatrix: 模型视图矩阵,将模型空间转换到视图空间
// projectionMatrix: 投影矩阵,将视图空间转换到裁剪空间
// gl_Position: OpenGL内置变量,表示顶点在裁剪空间中的位置
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// 主要负责计算每个像素的最终颜色
// 精度限定符,mediump表示中等精度(Three.js会自动提供)
precision mediump float;
// 从顶点着色器接收的变量
varying vec2 vUv;
void main() {
// 设置像素颜色
gl_FragColor = vec4(vUv, 0.0, 1.0); // 使用UV坐标作为颜色
}
现在让我们创建一个简单的自定义着色器材质:
// 创建自定义着色器材质
const vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const fragmentShader = `
precision mediump float;
varying vec2 vUv;
void main() {
// 使用UV坐标创建颜色渐变
vec3 color = vec3(vUv.x, vUv.y, 0.5);
gl_FragColor = vec4(color, 1.0);
}
`;
// 使用ShaderMaterial(Three.js会自动添加一些默认的uniform和attribute)
const shaderMaterial = new THREE.ShaderMaterial({
vertexShader: vertexShader, // 顶点着色器
fragmentShader: fragmentShader, // 片段着色器
wireframe: false // 设置为true可以查看网格结构
});
// 创建几何体并应用着色器材质
const geometry = new THREE.PlaneGeometry(10, 10, 100, 100);
const plane = new THREE.Mesh(geometry, shaderMaterial);
plane.rotation.x = -Math.PI / 2;
scene.add(plane);
着色器是 GPU 编程的核心,掌握了着色器编程,就掌握了高性能图形渲染的关键技术。通过自定义着色器,可以创造出无限可能的视觉效果。