如何在Three.js中使用ShaderToy着色器?求转换与配置协助
ShaderToy着色器转Three.js适配实现
顶点着色器(vertexShader)
使用全屏平面的基础顶点着色器即可,代码如下:
void main() { gl_Position = vec4(position, 1.0); }
如果需要传递UV坐标用于后续计算,可使用:
varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }
片元着色器(fragmentShader)转换
针对目标ShaderToy着色器,按以下规则修改核心逻辑:
- 参数映射:
- ShaderToy的
fragCoord→ 替换为gl_FragCoord.xy,结合resolution做坐标归一化:vec2 uv = gl_FragCoord.xy / resolution.xy; - ShaderToy的
iTime→ 对应Three.js的timeuniform(传入秒级时间值) - ShaderToy的
iResolution→ 对应Three.js的resolutionuniform(传入窗口宽高) - 原
mainImage(out vec4 fragColor, in vec2 fragCoord)入口改为Three.js的void main(),最终将结果赋值给gl_FragColor
- ShaderToy的
转换后的片元着色器示例(基于目标ShaderToy代码适配):
uniform float time; uniform vec2 resolution; // 复制原ShaderToy中的所有自定义函数(如噪波、颜色计算逻辑) float noise(vec2 p) { return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); } // 原ShaderToy中的其他函数... void main() { vec2 uv = gl_FragCoord.xy / resolution.xy; // 若原ShaderToy使用从下到上的Y轴,添加反转:uv.y = 1.0 - uv.y; vec4 fragColor = vec4(0.0); // 复制原ShaderToy中mainImage内的计算逻辑,替换fragCoord为uv相关变量 float n = noise(uv * 10.0 + time); fragColor = vec4(vec3(n), 1.0); gl_FragColor = fragColor; }
Uniforms配置
在Three.js中定义并初始化所需uniforms:
const uniforms = { time: { value: 0 }, resolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) } // 若原ShaderToy使用iMouse,添加: // mouse: { value: new THREE.Vector2(0, 0) } };
完整使用流程
- 创建ShaderMaterial:
const shaderMaterial = new THREE.ShaderMaterial({ vertexShader: 上述顶点着色器代码, fragmentShader: 上述转换后的片元着色器代码, uniforms: uniforms });
- 添加全屏平面到场景:
const geometry = new THREE.PlaneGeometry(2, 2); const plane = new THREE.Mesh(geometry, shaderMaterial); scene.add(plane);
- 动画循环更新时间:
function animate() { requestAnimationFrame(animate); uniforms.time.value = performance.now() / 1000; // 获取精确秒级时间 renderer.render(scene, camera); } animate();
- 窗口resize时更新分辨率:
window.addEventListener('resize', () => { uniforms.resolution.value.set(window.innerWidth, window.innerHeight); renderer.setSize(window.innerWidth, window.innerHeight); });
内容的提问来源于stack exchange,提问作者Tom Tefehne
相关产品推荐
相关产品推荐

