Shadertoy纹理着色器移植到WebGL后运行效果与原版不一致
移植效果偏差原因及修复方案
问题原因
- 纹理包裹模式不匹配:Shadertoy默认纹理采样超出UV 0~1范围时自动重复,p5.js默认采用边缘截断模式,代码中UV加了时间偏移必然超出范围,导致采样结果完全不同。
- Y轴坐标未对齐:Shadertoy的UV原点在画布左下角,p5.js WEBGL模式下默认纹理UV原点在左上角,直接采样会导致纹理上下翻转,后续变换全部出错。
- 矩阵乘法顺序错误:GLSL默认采用列优先矩阵存储规则,原代码中使用行向量乘矩阵的写法,和常规变换逻辑相反,会导致缩放方向异常。
- 输入参数不匹配:若p5.js传入的
time单位为毫秒(而非Shadertoy的秒级单位),会导致动画速度差1000倍;若传入的两张纹理和原版不一致,也会直接导致效果偏差。
修复方案
1. 调整纹理包裹模式
在p5.js的setup函数中,加载完两张纹理后,分别设置重复采样模式:
// 替换为你自己定义的纹理变量名 texture1.wrap(REPEAT); texture2.wrap(REPEAT);
2. 修正UV坐标
在着色器中计算UV后先翻转Y轴,对齐坐标系。
3. 修正矩阵乘法顺序
将变换行的乘法顺序调整为列优先的矩阵乘向量,保证变换逻辑正确。
4. 校准输入参数
- 传入着色器的
time值使用秒级单位,比如用millis() / 1000替代直接传毫秒值。 - 确认传入的
texture和texture2和原版使用的两张噪波纹理完全一致,不要传错顺序。
修正后完整着色器代码
uniform vec2 resolution; uniform float time; uniform float mouse; uniform sampler2D texture; uniform sampler2D texture2; void main() { vec2 uv = gl_FragCoord.xy / resolution.xy; uv.y = 1.0 - uv.y; vec4 texCol = texture2D(texture, uv + time / 10.0); mat3 tfm; tfm[0] = vec3(texCol.z, 0.0, 0.0); tfm[1] = vec3(0.0, texCol.y, 0.0); tfm[2] = vec3(0.0, 0.0, 1.0); vec2 muv = (tfm * vec3(uv, 1.0)).xy - 0.1 * time; texCol = texture2D(texture2, muv); gl_FragColor = texCol; }
内容的提问来源于stack exchange,提问作者Alivajorg
相关产品推荐
相关产品推荐

