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
相关产品推荐
相关产品推荐

