You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ShaderToy/GLSL中基于边距离着色矩形时对角线出现暗纹问题

解决ShaderToy中矩形距离着色的对角线暗纹问题

嘿,这个坑我之前踩过!你用max(uvn.y, uvn.x)来计算到矩形最近边的距离完全搞反了逻辑——这也是对角线暗纹出现的核心原因。

为什么max()会出问题?

max(uvn.x, uvn.y)取的是UV分量里较大的那个值,这和“到最近边的距离”完全不沾边:

  • 假设你的UV是归一到[0,1]×[0,1](从矩形一个角到对角),那么到左边的距离是uvn.x,到右边是1.0-uvn.x,到上下边同理。最近边的距离应该是这四个值里的最小值,而不是最大值。
  • 更关键的是,max()在uvn.x=uvn.y的对角线上会出现导数不连续的情况——也就是颜色梯度突然跳变,视觉上就是你看到的暗纹,完全做不到平滑插值。

正确的解决方法

第一步:计算正确的最近边距离

先根据你的UV归一方式选择对应的计算:

  1. UV范围是[-1,1]×[-1,1](中心在原点):
// 到左右边的距离:1减去x绝对值,到上下边同理
float dist_x = 1.0 - abs(uvn.x);
float dist_y = 1.0 - abs(uvn.y);
// 取最小值得到最近边距离
float dist_to_edge = min(dist_x, dist_y);
  1. UV范围是[0,1]×[0,1](从角落到对角):
float dist_left = uvn.x;
float dist_right = 1.0 - uvn.x;
float dist_bottom = uvn.y;
float dist_top = 1.0 - uvn.y;
// 多层min取四个方向里的最小值
float dist_to_edge = min(min(dist_left, dist_right), min(dist_bottom, dist_top));

第二步:添加平滑过渡(可选但推荐)

如果想要颜色过渡更柔和,避免硬边,可以用smoothstep或者自定义平滑min函数:

  • 用smoothstep快速实现:
// smoothstep(边缘起始值, 边缘结束值, 输入值)
// 这里0.0到0.1的范围是平滑过渡区域,可根据需求调整
float smooth_dist = smoothstep(0.0, 0.1, dist_to_edge);
vec3 color = vec3(smooth_dist);
  • 自定义带参数的平滑min(控制过渡强度):
float smoothmin(float a, float b, float k) {
    float h = clamp(0.5 + 0.5*(b-a)/k, 0.0, 1.0);
    return mix(b, a, h) - k*h*(1.0-h);
}

// 使用时,k值越大过渡越平缓
float smooth_dist = smoothmin(dist_x, dist_y, 0.1);
vec3 color = vec3(smooth_dist);

替换掉原来的max()逻辑后,对角线的暗纹就会消失,颜色也会按照到最近边的距离平滑变化啦。

内容的提问来源于stack exchange,提问作者Ivelate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:20:42