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

WebGL网格线宽度不均:每5条线异常变粗问题排查

网格线每5条异常变粗的问题排查请求

我用以下片元着色器绘制网格:

precision highp float;

uniform vec2 CANVAS_SIZE;
uniform float GRID_WIDTH;
uniform vec4 GRID_COLOR;

float isGridLine(float ordinate, float target, float halfThickness) {
    return step(ordinate, target + halfThickness) * step(target - halfThickness, ordinate);
}

void main() {
    vec2 uv = (gl_FragCoord.xy / CANVAS_SIZE);
    float halfGridWidth = GRID_WIDTH / 2.0;
    float gridLine = 0.0;
    for (float i = 0.0; i < 1.0; i += 0.05) {
        gridLine += isGridLine(uv.y, i, halfGridWidth);
        gridLine += isGridLine(uv.x, i, halfGridWidth);
    }
    gl_FragColor = mix(vec4(uv.rg, 0.0, 1.0), GRID_COLOR, step(1.0, gridLine));
}

顶点着色器仅通过JavaScript传入的顶点位置生成填充视口的静态平面,代码如下:

precision highp float;
attribute vec2 _vertexPosition;

void main() {
    gl_Position = vec4(_vertexPosition, 0.0, 1.0);
}

目前遇到异常:每第5条网格线会略微变粗,但着色器中并无针对第5条线的特殊逻辑。已完成排查:排除浮点精度问题(高低精度模式下均存在该异常),更换不同屏幕分辨率后,异常表现一致。恳请协助分析该问题的原因。

WebGL网格:每第5条线更粗


问题原因分析

核心问题出在循环的浮点累加精度误差上:

  • 0.05是二进制无法精确表示的无限循环浮点数,用i += 0.05累加时,多次循环后会产生偏差。当循环到第20次时,理论上i应等于1.0,但实际累加值会略小于1.0,导致循环多执行一次。
  • 这次额外循环会在i≈1.0的位置再画一条线,而这个位置和最后一条正常线(i=0.95)的位置极度接近,两条线重叠就造成了“变粗”的视觉效果——每20次循环对应4个0.05间隔(即第5条线),所以每第5条线会出现重叠。

修复方案

有两种简单的修复方式:

  1. 改用整数循环计算目标位置:彻底避免浮点累加误差,示例代码:
void main() {
    vec2 uv = (gl_FragCoord.xy / CANVAS_SIZE);
    float halfGridWidth = GRID_WIDTH / 2.0;
    float gridLine = 0.0;
    // 用整数循环控制次数,计算每个目标位置
    for (int i = 0; i < 20; i++) {
        float target = float(i) * 0.05;
        gridLine += isGridLine(uv.y, target, halfGridWidth);
        gridLine += isGridLine(uv.x, target, halfGridWidth);
    }
    gl_FragColor = mix(vec4(uv.rg, 0.0, 1.0), GRID_COLOR, step(1.0, gridLine));
}
  1. 调整循环终止条件:直接限制循环次数为20次,把i < 1.0改成i <= 0.95,避免多执行一次循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:30:18