Three.js 动态着色器切换玩具

🎯 提示词

PROMPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
使用 Three.js 实现动态切换着色器的效果展示工具,具体要求:

**核心特效**
- 6 种预设 GLSL 效果
- 实时切换着色器
- 立方体展示载体
- Phong 光照模型

**场景与光照**
- 白色立方体
- AmbientLight + DirectionalLight
- Phong ShaderMaterial

**交互与控制**
- GUI 下拉菜单切换
- 6 种预设效果
- 实时预览

**技术要求**
- Three.js 版本 (ES Module)
- ShaderMaterial
- 远程加载 .frag 文件
- UniformsUtils 合并

📖 效果拆解

层次 视觉效果 技术实现
基础 白色立方体 BoxGeometry
光照 Phong 模型 ShaderLib.phong
切换 远程加载 fetch() + replace
Uniforms 时间/分辨率 标准化接口

🔧 核心技术点

1. 着色器加载与替换

为什么需要这个技术:动态加载远程 GLSL 文件并替换标准着色器。

JAVASCRIPT
1
2
3
4
5
6
7
8
9
async function changeShader(url) {
    const str = await fetch(url).then((res) => res.text());
    shader.fragmentShader = str;
    shader.fragmentShader = shader.fragmentShader.replace(/gl_FragCoord/, "vUv * u_resolution.xy");
    shader.fragmentShader = shader.fragmentShader.replace(/uniform float u_time;/, `
        uniform float u_time;
        varying vec2 vUv;
    `);
}

2. Uniforms 标准化

为什么需要这个技术:确保加载的着色器获得标准 uniforms。

JAVASCRIPT
1
2
3
4
5
6
7
8
uniforms: THREE.UniformsUtils.merge([
    THREE.ShaderLib["phong"].uniforms,
    {
        u_resolution: { type: "v2", value: new THREE.Vector2(...) },
        u_time: { type: "f", value: 0.0 },
        u_mouse: { type: "v2", value: new THREE.Vector2(0, 0) }
    }
])

3. GUI 切换控制

为什么需要这个技术:通过下拉菜单选择不同的着色器。

JAVASCRIPT
1
2
const fileList = new Array(6).fill().map((_, i) => `/files/glsl/${i}.frag`);
gui.add({ url: fileList[0] }, "url", fileList).onChange((url) => changeShader(url));

💡 调试与优化

问题类型 表现形式 解决方案
加载失败 着色器空白 检查 URL 路径
坐标错误 效果错位 检查 u_resolution 替换
光照不匹配 颜色异常 确保 vUv 定义

🚀 扩展思路

变体效果 核心改动 难度
粒子效果 InstancedMesh
后处理 EffectComposer ⭐⭐
自定义上传 FileReader ⭐⭐
动画控制 GSAP
效果预览 缩略图 ⭐⭐

本文档由 ThreeLab 编辑整理,如需转载,请注明出处。