GLSL Waves着色器边缘出现缠绕问题,寻求修复方案
修复ShaderToy中UV坐标超出导致的边缘缠绕问题
你已经明确问题根源:当UV坐标超出[0,1]范围时,ShaderToy默认的纹理采样模式为重复(REPEAT),超出部分会从图像对面边缘衔接,从而出现缠绕现象。以下是几种具体修复方案:
方案1:限制UV范围到[0,1]
使用clamp()函数将偏移后的UV坐标固定在0到1之间,超出部分直接取图像边缘像素,避免缠绕:
const float INTENSITY = 0.5; const float SPEED = 0.5; const float SIZE = 0.2; void mainImage(out vec4 fragColor, in vec2 fragCoord) { vec2 uv = gl_FragCoord.xy / iResolution.xy; vec4 color = texture(iChannel0, uv); vec2 ghostOffset = vec2(cos(uv.y * SPEED * sin(iTime)), sin(uv.x * SPEED)); // 限制UV在合法范围内 vec2 sampledUV = clamp(uv + ghostOffset * SIZE, vec2(0.0), vec2(1.0)); color += INTENSITY * texture(iChannel0, sampledUV); fragColor = color; }
该方案实现简单,但边缘处的虚影效果会被截断。
方案2:使用镜像采样
通过手动计算实现镜像重复采样,让超出部分以翻转方式显示,视觉过渡更自然:
const float INTENSITY = 0.5; const float SPEED = 0.5; const float SIZE = 0.2; void mainImage(out vec4 fragColor, in vec2 fragCoord) { vec2 uv = gl_FragCoord.xy / iResolution.xy; vec4 color = texture(iChannel0, uv); vec2 ghostOffset = vec2(cos(uv.y * SPEED * sin(iTime)), sin(uv.x * SPEED)); vec2 sampledUV = uv + ghostOffset * SIZE; // 计算镜像UV:先取小数部分,再翻转超出0.5的区域 sampledUV = abs(fract(sampledUV) * 2.0 - 1.0); color += INTENSITY * texture(iChannel0, sampledUV); fragColor = color; }
方案3:边缘淡入淡出
根据UV坐标距离边缘的距离,动态降低虚影的透明度,实现柔和过渡:
const float INTENSITY = 0.5; const float SPEED = 0.5; const float SIZE = 0.2; // 边缘过渡区域的宽度,可根据效果调整 const float EDGE_FADE = 0.1; void mainImage(out vec4 fragColor, in vec2 fragCoord) { vec2 uv = gl_FragCoord.xy / iResolution.xy; vec4 color = texture(iChannel0, uv); vec2 ghostOffset = vec2(cos(uv.y * SPEED * sin(iTime)), sin(uv.x * SPEED)); vec2 sampledUV = uv + ghostOffset * SIZE; // 计算边缘衰减因子:距离边缘越近,因子越小 vec2 edgeFactor = smoothstep(0.0, EDGE_FADE, sampledUV) * smoothstep(1.0, 1.0 - EDGE_FADE, sampledUV); float fadeFactor = edgeFactor.x * edgeFactor.y; vec4 ghostColor = texture(iChannel0, clamp(sampledUV, vec2(0.0), vec2(1.0))); color += INTENSITY * fadeFactor * ghostColor; fragColor = color; }
内容的提问来源于stack exchange,提问作者tuxifan
相关产品推荐
相关产品推荐

