OpenGL中采样相邻纹理?解决分块纹理腐蚀轮廓断裂问题
灰度腐蚀形态学操作的纹理分块边界问题解决方法
问题描述
我正在GLSL中实现形态学灰度腐蚀以提取标记图像的轮廓。当前纹理以256x256分块加载,使用texelFetch无法采样块边界外的偏移像素:不加边界判断会出现块边界伪影;添加边界判断后,块边界处的轮廓会断开。请问是否有采样相邻纹理块的方法,或其他解决该问题的方案?
用户提供的Shader代码:
#version 430 in vec2 texCoords; out vec4 outColor; uniform isampler2D samplerTex; ivec2 offsets[4] = ivec2[](ivec2(0, -1), ivec2(-1, 0), ivec2(1, 0), ivec2(0, 1)); void main() { ivec2 texsize = textureSize(samplerTex, 0); ivec2 outcoords = ivec2(texCoords * texsize); uint pixel = texelFetch(samplerTex, outcoords, 0).x; if (pixel == 0) discard; uint erosion = pixel; for (int i = 0; i < 4; i++) { ivec2 coord = outcoords + offsets[i]; if (coord.x < 0 || coord.y < 0 || coord.x >= texsize.x || coord.y >= texsize.y) continue; uint val = texelFetch(samplerTex, coord, 0).x; erosion = min(erosion, val); } if (pixel != erosion) outColor = vec4(1.0, 1.0, 1.0, 1.0); else discard; }
解决方案
扩展纹理块的边界数据
加载256x256分块纹理时,为每个块额外加载周围1像素的相邻块数据,让每个实际传入Shader的块尺寸变为258x258(边缘1像素是相邻块的内容)。这样Shader中使用texelFetch采样偏移像素时,块边缘的像素也能取到正确的相邻值,无需跳过边界判断,避免轮廓断开。优化边界采样逻辑
不要直接跳过边界外的采样,而是为边界外的像素设置合理默认值。灰度腐蚀取最小值,所以可以把边界外像素设为灰度最大值(比如255,需匹配你的灰度值范围),这样不会影响腐蚀计算结果。修改Shader中的循环代码:for (int i = 0; i < 4; i++) { ivec2 coord = outcoords + offsets[i]; uint val; // 边界外像素设为最大值,不影响min计算 if (coord.x < 0 || coord.y < 0 || coord.x >= texsize.x || coord.y >= texsize.y) val = 255; else val = texelFetch(samplerTex, coord, 0).x; erosion = min(erosion, val); }这样块边缘的像素能完成完整的腐蚀计算,不会出现轮廓断开的问题。
纹理边界模式设置(针对单纹理分块采样场景)
如果是将整个大图像作为单纹理,通过分块坐标采样,可以调用OpenGL API设置纹理的边界环绕模式:glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);这种模式下,采样超出纹理范围的坐标会被钳制到纹理边缘的像素值,适合图像真实边缘的处理,但对于分块加载的多纹理场景,还是前两种方法更有效。
内容的提问来源于stack exchange,提问作者tboschi
相关产品推荐
相关产品推荐

