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

通过纹理向片段着色器传递浮点数组(音频波形)的精度问题

搞定1px纹理采样瑕疵的几个关键点

嘿,我之前也踩过用1像素高的纹理传音频波形的坑!你遇到的随机瑕疵问题,大概率是纹理采样的过滤逻辑、坐标精度或者数据格式这几个环节出了问题,咱们一步步来解决:

1. 先把纹理过滤模式改成「精准采样」

默认的LINEAR过滤模式会让GPU尝试插值相邻像素,但你的纹理只有1行,GPU可能会误采样到不存在的上下像素(或者触发mipmap逻辑),导致读出奇怪的值。

直接把过滤模式改成NEAREST,同时禁用mipmap,让GPU精准命中单个像素:

// 创建纹理时设置这些参数
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
// 彻底禁用mipmap,避免不必要的采样计算
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 0);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 0);

2. 修正纹理坐标的精度偏差

你用floor计算barIndex再转纹理坐标的方式,在mediump精度下容易出现浮点误差——比如本该取第5个波形点,结果因为精度偏移取到了第4或第6个,就会出现瑕疵。

解决办法是直接采样纹理像素的中心,而不是边缘:

precision mediump float;
uniform sampler2D uDisp;
uniform float barsCount;
uniform float availableWidth;
uniform float paddingH;
uniform vec2 textureSize; // 把纹理的宽高传进来,比如vec2(barsCount, 1.0)

void main(){
    vec2 coord = gl_FragCoord.xy;
    float columnWidth = availableWidth / barsCount;
    float barIndex = floor((coord.x - paddingH) / columnWidth);
    
    // 关键修正:用(索引+0.5)/纹理宽度,精准命中像素中心
    float textureX = (barIndex + 0.5) / textureSize.x;
    // 纹理高度是1,y坐标固定取0.5就行
    float sampleValue = texture2D(uDisp, vec2(textureX, 0.5)).r;
    
    // 你的绘制逻辑...
}

3. 检查纹理数据格式的精度

如果你的音频波形是浮点数据,别用8位的纹理格式(比如gl.RGB),不然会把0-1的浮点值压缩到0-255再还原,损失精度还可能引入异常值。

直接用浮点纹理格式:

// 假设audioWaveform是你的浮点波形数组,范围0-1
const data = new Float32Array(audioWaveform);
// 用R32F格式存储单通道浮点数据
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, barsCount, 1, 0, gl.RED, gl.FLOAT, data);

额外小提示:处理非2的幂纹理

如果你的barsCount不是2的幂,有些老GPU可能会有纹理对齐问题。如果还是有瑕疵,可以把纹理宽度向上取最近的2的幂,然后在着色器里计算时忽略多余的部分,或者补0填充波形数据。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:01:45