ThreeJS 着色器图形特效
本文档涵盖Three.js中高级着色器图形特效的实现方法,基于实际代码示例进行讲解。
最终效果如图:
![]()
1. 着色器图形特效基础
1.1 复杂着色器材质创建
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import gsap from "gsap";
import * as dat from "dat.gui";
import deepVertexShader from "../shaders/deep/vertex.glsl";
import deepFragmentShader from "../shaders/deep/fragment.glsl";
// 创建带有多个uniforms的着色器材质
const shaderMaterial = new THREE.ShaderMaterial({
vertexShader: deepVertexShader,
fragmentShader: deepFragmentShader,
uniforms: {
uColor: {
value: new THREE.Color("purple"),
},
// 波浪的频率
uFrequency: {
value: params.uFrequency,
},
// 波浪的幅度
uScale: {
value: params.uScale,
},
// 动画时间
uTime: {
value: 0,
},
uTexture: {
value: texture,
},
},
side: THREE.DoubleSide,
transparent: true,
});
1.2 GUI参数控制
通过dat.GUI实时控制着色器参数:
// 控制频率参数
gui
.add(params, "uFrequency")
.min(0)
.max(50)
.step(0.1)
.onChange((value) => {
shaderMaterial.uniforms.uFrequency.value = value;
});
// 控制幅度参数
gui
.add(params, "uScale")
.min(0)
.max(1)
.step(0.01)
.onChange((value) => {
shaderMaterial.uniforms.uScale.value = value;
});
2. 高级片元着色器技术
2.1 UV坐标操作
UV坐标是纹理映射的基础,也是创建各种图形效果的关键:
void main(){
// 1. 通过顶点对应的uv,决定每一个像素在uv图像的位置,通过这个位置x,y决定颜色
// gl_FragColor =vec4(vUv,0,1) ;
// 2. 对第一种变形
// gl_FragColor = vec4(vUv,1,1);
// 3. 利用uv实现渐变效果,从左到右
float strength = vUv.x;
gl_FragColor =vec4(strength,strength,strength,1);
}
2.2 数学函数应用
利用GLSL内置数学函数创建复杂效果:
// 随机函数
float random (vec2 st) {
return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
}
// 噪声函数
float noise (in vec2 _st) {
vec2 i = floor(_st);
vec2 f = fract(_st);
// 四个角落的随机值
float a = random(i);
float b = random(i + vec2(1.0, 0.0));
float c = random(i + vec2(0.0, 1.0));
float d = random(i + vec2(1.0, 1.0));
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) +
(c - a)* u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}
2.3 几何图形绘制
使用数学函数绘制各种几何图形:
// 绘制圆形
float strength = 1.0 - step(0.5,distance(vUv,vec2(0.5))+0.25) ;
gl_FragColor =vec4(strength,strength,strength,1);
// 绘制圆环
float strength = step(0.5,distance(vUv,vec2(0.5))+0.35) ;
strength *= (1.0 - step(0.5,distance(vUv,vec2(0.5))+0.25)) ;
gl_FragColor =vec4(strength,strength,strength,1);
// 波浪效果
vec2 waveUv = vec2(
vUv.x+sin(vUv.y*100.0)*0.1,
vUv.y+sin(vUv.x*100.0)*0.1
);
float strength = 1.0 - step(0.01,abs(distance(waveUv,vec2(0.5))-0.25)) ;
gl_FragColor =vec4(strength,strength,strength,1);
3. 动画与时间控制
3.1 时间uniform应用
在动画循环中更新时间uniform:
const clock = new THREE.Clock();
function animate(t) {
const elapsedTime = clock.getElapsedTime();
shaderMaterial.uniforms.uTime.value = elapsedTime; // 更新时间
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
3.2 着色器中的动画效果
// 使用时间创建波浪动画
float strength = step(0.9,sin(cnoise(vUv * 10.0)*20.0+uTime)) ;
// 波纹效果
float strength = sin(cnoise(vUv * 10.0)*5.0+uTime) ;
4. 颜色混合与插值
4.1 颜色混合函数
// 使用混合函数混颜色
vec3 purpleColor = vec3(1.0, 0.0, 1.0);
vec3 greenColor = vec3(1.0, 1.0, 1.0);
vec3 uvColor = vec3(vUv,1.0);
float strength = step(0.9,sin(cnoise(vUv * 10.0)*20.0)) ;
vec3 mixColor = mix(greenColor,uvColor,strength);
gl_FragColor =vec4(mixColor,1.0);
5. 纹理与采样
5.1 纹理采样
uniform sampler2D uTexture;
void main(){
vec4 textureColor = texture2D(uTexture,vUv);
textureColor.rgb*=height;
gl_FragColor = textureColor;
}
6. 几何变换
6.1 旋转函数
// 旋转函数
vec2 rotate(vec2 uv, float rotation, vec2 mid)
{
return vec2(
cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
);
}
// 使用旋转函数
vec2 rotateUv = rotate(vUv,-uTime*5.0,vec2(0.5));
7. 复杂效果实现
7.1 万花筒效果
// 万花筒效果
float angle = atan(vUv.x-0.5,vUv.y-0.5)/PI;
float strength = mod(angle*10.0,1.0);
gl_FragColor =vec4(strength,strength,strength,1);
7.2 雷达扫描效果
// 雷达扫描效果
vec2 rotateUv = rotate(vUv,-uTime*5.0,vec2(0.5));
float alpha = 1.0 - step(0.5,distance(vUv,vec2(0.5)));
float angle = atan(rotateUv.x-0.5,rotateUv.y-0.5);
float strength = (angle+3.14)/6.28;
gl_FragColor =vec4(strength,strength,strength,alpha);
8. 性能优化与调试
8.1 性能优化技巧
- 减少复杂计算:避免在着色器中进行过于复杂的数学运算
- 合理使用纹理:预先计算复杂效果并存储在纹理中
- 简化几何体:在不影响视觉效果的前提下减少顶点数
8.2 调试技巧
- 逐步构建:从简单效果开始,逐步增加复杂性
- 输出中间值:将中间计算结果输出为颜色进行调试
- 使用常量验证:先用常量验证逻辑,再引入变量
总结
本章深入探讨了Three.js中高级着色器图形特效的实现方法,包括:
- 复杂着色器材质的创建和参数控制
- 数学函数在图形生成中的应用
- UV坐标操作和几何图形绘制
- 时间动画和颜色混合技术
- 纹理采样和几何变换
- 复杂视觉效果的实现方法
- 性能优化和调试技巧
通过掌握这些技术,可以创建出丰富的视觉效果和动态图形。