OpenGL 3D 纹理 "shine through"

OpenGL 3D texture "shine through"

出于测试目的,我想显示 3D 纹理的第一个切片。不过好像其他切片也显示了。

我的顶点着色器:

#version 130

attribute vec4 position;

varying vec2 texcoord;

void main()
{
    gl_Position = position;
    texcoord = position.xy * vec2(0.5) + vec2(0.5);
}

片段着色器:

#version 130

uniform sampler3D textures[1];

varying vec2 texcoord;

void main()
{
    gl_FragColor = texture3D(textures[0], vec3(texcoord.x, texcoord.y, 0));
}

我使用

从我的 C++ 代码绑定纹理
     glTexImage3D(GL_TEXTURE_3D,0,GL_LUMINANCE,rows-1,cols-1,dep-  1,0,GL_RED,GL_UNSIGNED_SHORT, vol.data());

这是它的样子;整个头部不应该可见,只能看到它的上半部分。

当您使用线性过滤(GL_TEXTURE_MIN_FILTER and/or GL_TEXTURE_MAG_FILTER 纹理参数的值 GL_LINEAR 时,样本的值通常由两者决定切片最接近您的第三个纹理坐标。

如果您的 3D 纹理在第 3 维的大小为 d,则第一个切片在纹理坐标 space 中的位置为 0.5 / d。如果您将每个切片在纹理坐标 space 中描绘成具有一定厚度,这将最容易理解。因为你有d个切片,纹理坐标范围是[0.0, 1.0],每个切片的厚度是1.0 / d。因此,第一个切片从 0.0 延伸到 1.0 / d,其中心位于 0.5 / d.

当您使用 0.0 作为第三个纹理坐标时,这不是第一个切片的中心,线性采样开始发挥作用。由于 0.0 位于纹理的边缘,因此环绕模式变得至关重要。默认的环绕模式是 GL_REPEAT,这意味着在边缘采样就像重复纹理一样。使用此设置,第一个切片的邻居是最后一个切片,纹理坐标 0.0 恰好在第一个切片和最后一个切片的中间。

结果是使用纹理坐标 0.0 的线性采样将为您提供第一个切片和最后一个切片的平均值。

虽然 GL_REPEAT 是环绕模式的默认值,但它很少是您想要的,除非您的纹理确实包含重复图案。在这种情况下,这当然不是正确的设置。您需要的是:

glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);