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);
出于测试目的,我想显示 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);