在WebGL和Three.js的3D图形渲染中,着色器(Shader) 是实现复杂视觉效果的核心工具。通过编写自定义的着色器代码,开发者可以直接操作GPU,实现从基础颜色渲染到动态光照、粒子效果等高级图形技术。本文将深入解析Three.js中着色器的核心概念、实现原理及实战应用,并结合代码示例帮助读者全面掌握这一关键技术。
核心特点:
顶点着色器负责处理几何体的每个顶点,主要功能包括:
gl_Position
输出)void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
说明:projectionMatrix
(投影矩阵)、modelViewMatrix
(模型视图矩阵)由Three.js自动注入,position
是顶点的原始坐标。
片元着色器决定每个像素的最终颜色,通过 gl_FragColor
输出:
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
}
特性:颜色支持动态计算,如基于光照模型、纹理采样等。
Three.js提供两种自定义着色器材质:
ShaderMaterial
:简化版材质,内置常用变量(如modelViewMatrix
、projectionMatrix
),适合快速开发。
RawShaderMaterial
:需手动声明所有变量(如attribute
、uniform
),灵活性更高,适合深度优化。
示例代码:创建基础着色器材质
const material = new THREE.ShaderMaterial({
vertexShader: vertexShaderCode,
fragmentShader: fragmentShaderCode,
uniforms: {
time: { value: 0 },
color: { value: new THREE.Color(0xff0000) }
}
});
ShaderMaterial
的 uniforms
属性设置const material = new THREE.ShaderMaterial({
uniforms: {
uTime: { value: 0 },
uTexture: { value: new THREE.TextureLoader().load("texture.png") }
}
});
在着色器中声明:uniform float uTime;
geometry.setAttribute('displacement', new THREE.BufferAttribute(displacementArray, 1));
在顶点着色器中访问:attribute float displacement;
// 顶点着色器
varying vec2 vUv;
void main() {
vUv = uv;
// ...
}
// 片元着色器
varying vec2 vUv;
void main() {
vec4 color = texture2D(uTexture, vUv);
}
注意:变量名需在两者中保持一致。
顶点变换遵循 “右乘”顺序,确保坐标正确转换:
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
原理:从模型空间→世界空间→相机空间→裁剪空间逐步变换。
顶点着色器(传递UV坐标):
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
片元着色器(动态波纹计算):
uniform float uTime;
varying vec2 vUv;
void main() {
float ripple = sin(length(vUv - 0.5) * 10.0 - uTime * 2.0);
float opacity = smoothstep(0.0, 0.2, abs(ripple));
gl_FragColor = vec4(0.2, 0.5, 1.0, opacity);
}
const material = new THREE.ShaderMaterial({
uniforms: {
uTime: { value: 0 }
},
vertexShader: vertexShaderCode,
fragmentShader: fragmentShaderCode,
transparent: true
});
// 动画循环中更新Uniform
function animate() {
material.uniforms.uTime.value += 0.01;
requestAnimationFrame(animate);
}
效果:实现以中心向外扩散的蓝色波纹。
mix()
或 step()
替代 if-else
vec3
/vec4
代替多个 float
计算#version 300 es
)precision mediump float;
)通过 EffectComposer
和 ShaderPass
实现屏幕后处理:
import { EffectComposer, ShaderPass } from 'three/examples/jsm/postprocessing';
const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));
const customPass = new ShaderPass(customShaderMaterial);
composer.addPass(customPass);
典型效果:模糊、Bloom光效、颜色校正等。
Three.js着色器为开发者打开了高性能图形编程的大门。通过深入理解GLSL语法、矩阵变换和变量传递机制,可以创造出从基础颜色变化到复杂物理模拟的全方位视觉效果。建议通过Shadertoy平台进行实时演练,结合Three.js文档探索更多可能性。