OpenGL 3D纹理“闪耀”

OpenGL 3D纹理“闪耀”,opengl,textures,glsl,Opengl,Textures,Glsl,出于测试目的,我想显示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 textu

出于测试目的,我想显示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_纹理\u MIN_过滤器和/或GL_纹理\u MAG_过滤器纹理参数使用线性过滤值GL_linear时,样本的值通常由最靠近第三纹理坐标的两个切片确定

如果三维纹理的大小为d,则纹理坐标空间中第一个切片的位置为0.5/d。这是最容易理解的,如果您在纹理坐标空间中绘制具有特定厚度的每个切片。由于有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的线性采样将为您提供第一个切片和最后一个切片的平均值

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

数据加载或数据本身似乎更有可能出现问题,因此第一个切片实际上包含您看到的数据。例如,如果您正在读取DICOM数据集,则在同一目录中通常会有参考切片,而这些切片不是3D数据集的一部分。我无法想象您没有渲染的内容会如何神奇地出现。顺便说一句,为什么要从glTexImage3D调用中的行、cols和dep值中减去1?这些值真的比数据集的实际大小大1吗?是的,这些值用于从原始文件中提取数据,并且范围是独占的,在OpenGL中,如果省略-1,则整个数据集都会移位,它们显然是包含的。我还注意到,当拾取一个切片(例如0.5)时,切片显示正确。仅0和1出现错误。纹理包裹模式使用什么值?如果它们是GL_重复线性过滤,纹理坐标0.0将是第一个切片的一半和最后一个切片的一半。谢谢,就是这样!选择最近邻滤波或钳制R轴都有效!