OpenGL计算着色器texture()采样异常,texelFetch()正常问题求助
OpenGL计算着色器depth采样问题:texture()锯齿 vs texelFetch()正常
问题现象
- 开发计算着色器采样depth
sampler2D时,用texture()函数采样出现明显锯齿边缘,换成texelFetch()后采样结果完全正常 - 采样器已配置为nearest过滤,且未启用mipmap
效果对比
- 使用
texelFetch()的结果:
- 使用
texture()的结果:
着色器核心逻辑(截图内容)
从截图看,着色器通过gl_GlobalInvocationID.xy获取线程索引,转换为纹理坐标后采样depth纹理,核心代码类似:
layout(local_size_x = 16, local_size_y = 16) in; layout(r32f, binding = 0) uniform image2D outputTex; uniform sampler2D depthTex; void main() { ivec2 texCoord = ivec2(gl_GlobalInvocationID.xy); vec2 uv = vec2(texCoord) / textureSize(depthTex, 0); float depth = texture(depthTex, uv).r; // texelFetch版本: // float depth = texelFetch(depthTex, texCoord, 0).r; imageStore(outputTex, texCoord, vec4(depth, 0, 0, 1)); }
问题根源
texture()和texelFetch()的核心区别在于坐标体系:
texelFetch()直接使用整数像素索引,精准定位单个texel,不存在坐标转换误差texture()使用标准化纹理坐标(范围[0,1]),而OpenGL中每个texel的采样中心是(x + 0.5)/width,不是直接的x/width。如果直接用gl_GlobalInvocationID.xy / textureSize(...),得到的是texel的左下角坐标,虽然nearest过滤理论上会采样当前texel,但浮点计算的精度误差(比如纹理尺寸非2的幂、线程索引计算舍入)可能导致坐标偏移,错误采样到相邻texel,从而出现锯齿。
解决方法
方法1:修正texture()的坐标计算
把标准化坐标调整到像素中心,修改坐标逻辑:
vec2 texSize = textureSize(depthTex, 0); vec2 uv = (vec2(gl_GlobalInvocationID.xy) + 0.5) / texSize; float depth = texture(depthTex, uv).r;
方法2:继续使用texelFetch()
对于计算着色器的逐像素处理场景,texelFetch()本身就是更直接的选择——不需要坐标转换,完全规避精度问题,推荐优先使用。
内容的提问来源于stack exchange,提问作者DarxDev
相关产品推荐
相关产品推荐

