在 Three.js 的三维场景构建中,着色器(Shader)是极为强大的工具,能显著提升场景渲染效果,创造独特视觉体验。本文假定你已掌握 Three.js 基础,将深入探讨着色器在 Three.js 中的运用。
理解着色器
着色器是运行在 GPU 上的小程序,分为顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)。顶点着色器处理几何体顶点,常用于控制物体形状、位置和方向;片段着色器处理每个像素颜色,决定物体表面最终呈现颜色。在 Three.js 中,通过自定义着色器可实现复杂光影效果、材质模拟等。
在 Three.js 中使用自定义着色器
1. 创建着色器材质
使用ShaderMaterial类创建自定义着色器材质。需提供顶点着色器和片段着色器代码字符串。
js
const vertexShader = `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const fragmentShader = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
const shaderMaterial = new THREE.ShaderMaterial({
vertexShader,
fragmentShader
});
上述代码中,顶点着色器仅进行常规坐标变换,将顶点位置转换到屏幕空间。片段着色器将所有像素设置为红色。
2. 应用材质到几何体
将创建的ShaderMaterial应用到几何体上,与使用普通材质类似。
js
const geometry = new THREE.BoxGeometry(1, 1, 1);
const mesh = new THREE.Mesh(geometry, shaderMaterial);
scene.add(mesh);
此时,场景中立方体将呈现红色。
示例:实现简单的渐变效果
修改片段着色器实现从顶部蓝色到底部绿色的渐变效果。
js
const vertexShader = `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const fragmentShader = `
varying vec2 vUv;
void main() {
vec4 topColor = vec4(0.0, 0.0, 1.0, 1.0);
vec4 bottomColor = vec4(0.0, 1.0, 0.0, 1.0);
float interpolate = vUv.y;
gl_FragColor = mix(topColor, bottomColor, interpolate);
}
`;
const shaderMaterial = new THREE.ShaderMaterial({
vertexShader,
fragmentShader
});
// 在顶点着色器中传递纹理坐标
const geometry = new THREE.BoxGeometry(1, 1, 1);
geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array([
0, 0, 1, 0, 1, 1, 0, 1
]), 2));
const mesh = new THREE.Mesh(geometry, shaderMaterial);
scene.add(mesh);
这里,在顶点着色器中未做太多修改。片段着色器引入vUv变量(用于存储纹理坐标),通过vUv.y值(范围 0 - 1)对顶部蓝色和底部绿色进行线性插值,实现渐变效果。需注意,要为几何体设置uv属性传递纹理坐标信息。
传递 Uniform 变量
Uniform 变量是在着色器中可在每一帧更新的全局变量。如传递时间变量实现动画效果。
js
const vertexShader = `
uniform float time;
void main() {
vec3 newPosition = position;
newPosition.y += sin(time + position.x) * 0.2;
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
}
`;
const fragmentShader = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
const shaderMaterial = new THREE.ShaderMaterial({
vertexShader,
fragmentShader,
uniforms: {
time: { value: 0 }
}
});
function animate() {
requestAnimationFrame(animate);
shaderMaterial.uniforms.time.value += 0.05;
renderer.render(scene, camera);
}
animate();
在上述代码中,顶点着色器引入time uniform 变量,根据时间和顶点x坐标修改顶点y坐标,实现波浪状动画效果。在animate函数中每一帧更新time uniform 变量值。
总结
通过上述示例,你了解了在 Three.js 中创建和使用自定义着色器、实现渐变效果及传递 uniform 变量。着色器功能强大,可实现复杂材质、光影和动画效果。深入研究着色器语言(GLSL)语法和特性,能为 Three.js 场景开发带来更多创意和可能。