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

GLSL值噪声实现疑问:为何输出呈块状且无相关性?

梯度噪声出现块状效果的问题分析与修复

问题根源

你代码里的核心错误是插值时使用了未取小数部分的全局UV坐标,而非当前网格单元内的相对位置:

  • 执行uv *= 100.0;后,UV的数值是形如(50.2, 30.7)的格式,整数部分代表网格ID,小数部分才是当前像素在网格单元内的[0,1]相对坐标。
  • 你直接用uv.x和uv.y作为mix的插值因子,这会导致插值参数远超出mix预期的[0,1]范围,且在网格边界处因UV整数部分的跳变,出现突变式的插值结果,最终形成块状断层。

修复方案

计算网格单元内的相对坐标(取UV的小数部分),用这个值作为插值因子:

float generateNoise( vec2 position){
    return fract(sin(dot(position, vec2(12.9898,78.233)))*100000.0);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;
    // uv.x *= iResolution.x/iResolution.y;
    uv *= 100.0;
    vec2 gridId = floor(uv);
    // 计算网格内的相对坐标(小数部分)
    vec2 fractUv = fract(uv);
    
    // four corner of the grid gridId
    vec2 br = gridId + vec2(1, 0); 
    vec2 bl = gridId + vec2(0, 0);
    vec2 tr = gridId + vec2(1, 1);
    vec2 tl = gridId + vec2(0, 1);
    
    float noiseBr = generateNoise(br);
    float noiseBl = generateNoise(bl);
    float noiseTr = generateNoise(tr);
    float noiseTl = generateNoise(tl);
    
    // 使用网格内相对坐标进行插值
    float a1 = mix(noiseBl, noiseBr, fractUv.x);
    float a2 = mix(noiseTl, noiseTr, fractUv.x);
    float value = mix(a1, a2, fractUv.y);
    
    fragColor = vec4(value, value, value, 1.0);
}

修复效果说明

修正后,每个网格单元内会基于四角的噪声值进行平滑的双线性插值,相邻网格单元共享边界处的噪声值,过渡自然连续,不会再出现块状断层,你原本预期的具有相关性的灰度过渡噪声就能正常呈现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:30:14