GLSL 中的最近邻插值

Nearest neighbor interpolation in GLSL

我有一个 GLSL 片段着色器作为管道的一部分,用于渲染混合在一起的两个 3D 体积的切片。对于其中一个卷,我想使用最近邻插值,因为它是一个“分割掩码”(即在每个体素处指示另一个图像中的体素属于哪个结构,例如 0 表示背景,1 表示目标结构;请参见下图中的紫色叠加层),因为默认的三线性插值会在边界处产生不需要的伪影(下图中边界处的绿线)

我将如何修改下面的片段着色器代码以在分割蒙版上使用最近邻插值 (vol2)?

uniform sampler3D vol1;
uniform sampler3D vol2;
uniform sampler2D lut1;
uniform sampler2D lut2;

uniform float maskAlpha = 0.5;

void main()
{
    float data1 = texture3D(vol1, gl_TexCoord[0].xyz).r;
    float data2 = texture3D(vol2, gl_TexCoord[0].xyz).r;
    vec4 col1 = texture2D(lut1, vec2(data1));
    vec4 col2 = texture2D(lut2, vec2(data2));
    
    gl_FragColor = col1 + col2 * maskAlpha;
}

您需要在 CPU 侧代码上为每个纹理设置所需的过滤:

glEnable(GL_TEXTURE_3D);    
glBindTexture(GL_TEXTURE_3D,???); // here the ??? is the texture ID ...
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);

支持的基本过滤器有:GL_NEAREST,GL_LINEAR

看到这个: 了解整个事情。

有关详细信息,另请参阅 glTexParameter 文档

如果您无法访问 CPU 辅助代码,那么您可以将纹理坐标与片段着色器中的纹素位置对齐。然而为此你需要知道你的纹理的分辨率。

所以对于每个坐标 x=<0,1> 和分辨率 xs [textels] 你可以试试这个:

x' = floor((x*(xs-1)+0.5))/(xs-1);

并使用该新坐标来获取纹素...但是没有对其进行测试,因此可能需要进行一些调整(例如将纹素的中心移动 0.5 ...)