GLSL片段着色器求助:实现从纹理1→颜色→纹理2的渐变过渡
实现GLSL双阶段渐变过渡的正确方式
你的代码核心问题是没有将progress的0-1范围拆分为两个独立的过渡阶段,导致混合逻辑不符合你想要的"tex1→目标色→tex2"的顺序。下面是正确的实现思路和代码:
核心思路
把progress的0-1范围映射为两个子阶段:
- 阶段1(progress: 0 → 0.5):从纹理1的颜色平滑过渡到目标颜色
- 阶段2(progress: 0.5 → 1):从目标颜色平滑过渡到纹理2的颜色
我们可以通过拉伸progress的范围,配合clamp函数来分别控制两个阶段的混合因子,再通过step函数切换阶段结果。
修正后的完整代码
// Uniforms uniform sampler2D tex1; uniform sampler2D tex2; uniform vec3 targetColor; // 目标过渡颜色 uniform float progress; // 过渡进度,0到1之间 // Varyings varying vec2 vUv; // Main function void main() { // 获取两个纹理的当前像素颜色 vec4 texel1 = texture2D(tex1, vUv); vec4 texel2 = texture2D(tex2, vUv); // 将progress的0-1范围拉伸为0-2,用于拆分两个过渡阶段 float t = progress * 2.0; // 阶段1:tex1 → targetColor(progress 0~0.5 对应 t 0~1) vec3 colorStage1 = mix(texel1.rgb, targetColor, clamp(t, 0.0, 1.0)); // 阶段2:targetColor → tex2(progress 0.5~1 对应 t-1 0~1) vec3 colorStage2 = mix(targetColor, texel2.rgb, clamp(t - 1.0, 0.0, 1.0)); // 根据progress是否超过0.5,选择对应的阶段颜色 vec3 finalRgb = mix(colorStage1, colorStage2, step(0.5, progress)); // 处理Alpha通道(这里直接沿用tex1的Alpha,也可根据需求混合tex2的Alpha) vec4 finalColor = vec4(finalRgb, texel1.a); gl_FragColor = finalColor; }
代码说明
- 拉伸进度范围:
t = progress * 2.0把0-1的进度转为0-2,前半段0-1对应第一个过渡阶段,后半段1-2对应第二个阶段。 - 阶段1混合:
clamp(t, 0.0, 1.0)确保当progress超过0.5时,混合因子固定为1,此时colorStage1等于目标颜色,不再变化。 - 阶段2混合:
t - 1.0把后半段的1-2转为0-1,clamp确保progress小于0.5时混合因子为0,此时colorStage2等于目标颜色,不再变化。 - 阶段切换:
step(0.5, progress)会在progress≥0.5时返回1,否则返回0,刚好实现两个阶段的无缝切换。 - Alpha处理:示例中直接使用了tex1的Alpha通道,如果你需要混合两个纹理的Alpha,可以用同样的阶段逻辑处理,比如:
float alphaStage1 = mix(texel1.a, 1.0, clamp(t, 0.0, 1.0)); // 假设目标颜色Alpha为1 float alphaStage2 = mix(1.0, texel2.a, clamp(t - 1.0, 0.0, 1.0)); float finalAlpha = mix(alphaStage1, alphaStage2, step(0.5, progress)); vec4 finalColor = vec4(finalRgb, finalAlpha);
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

