glslmedical-imagingvolume-rendering

Nearest neighbor interpolation in GLSL


I have a GLSL fragment shader as part of a pipeline that renders slices of two 3D volumes blended together. For one of the volumes, I would like to use nearest neighbor interpolation since it is a "segmentation mask" (i.e. at each voxel indicates, which structure the voxel in the other image belongs to, e.g. 0 for background, 1 for target structure; see purple overlay in the image below), since the default trilinear interpolation creates undesired artifacts at the borders (green line at the border in the image below)

enter image description here

How would I have to modify the fragment shader code below to use nearest neighbor interpolation on the segmentation mask (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;
}

Solution

  • you need to set the desired filtering for each texture on CPU side code:

    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);
    

    Basic supported filters are: GL_NEAREST,GL_LINEAR

    See this: setting up 3D texture for the whole thing.

    For more info also see glTexParameter docs

    In case you do not have access to CPU side code then You could align the texture coordinates to texel positions inside fragment shader. However for that you need to know the resolution of your textures.

    so for each coordinate x=<0,1> and resolution xs [textels] you could try this:

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

    and use that new coordinate for fetching texel ... However did not test it so its possible it would need some tweaking (like move the center of texel by 0.5 ...)