问题
For testing purposes I want to display the first slice of a 3D texture. However it seems that the other slices are also displayed.
My vertex shader:
#version 130
attribute vec4 position;
varying vec2 texcoord;
void main()
{
gl_Position = position;
texcoord = position.xy * vec2(0.5) + vec2(0.5);
}
The fragment shader:
#version 130
uniform sampler3D textures[1];
varying vec2 texcoord;
void main()
{
gl_FragColor = texture3D(textures[0], vec3(texcoord.x, texcoord.y, 0));
}
I bind the texture from my C++ code using
glTexImage3D(GL_TEXTURE_3D,0,GL_LUMINANCE,rows-1,cols-1,dep- 1,0,GL_RED,GL_UNSIGNED_SHORT, vol.data());
This is how it looks; the whole head should not be visible, only the upper portion of it.
回答1:
When you use linear filtering (value GL_LINEAR
for the GL_TEXTURE_MIN_FILTER
and/or GL_TEXTURE_MAG_FILTER
texture parameters), the value of your samples will generally be determined by the two slices closest to your 3rd texture coordinate.
If the size of your 3D texture in the 3rd dimension is d
, the position of the first slice in texture coordinate space is 0.5 / d
. This is easiest to understand if you picture each slice having a certain thickness in texture coordinate space. Since you have d
slices, and the texture coordinate range is [0.0, 1.0]
, each slice has thickness 1.0 / d
. Therefore, the first slice extends from 0.0
to 1.0 / d
, and its center is at 0.5 / d
.
When you use 0.0
for the 3rd texture coordinate, this is not the center of the first slice, and linear sampling comes into play. Since 0.0
is at the edge of the texture, the wrap modes become critical. The default wrap mode is GL_REPEAT
, meaning that sampling at the edges acts as if the texture was repeated. With this setting, the neighbor of the first slice is the last slice, and texture coordinate 0.0
is exactly in the middle between the first slice and the last slice.
The consequence is that linear sampling with texture coordinate 0.0
will give you the average of the first slice and the last slice.
While GL_REPEAT
is the default for the wrap modes, it is rarely what you want, unless your texture really contains a repeating pattern. It's certainly not the right setting in this case. What you need here is:
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);
来源:https://stackoverflow.com/questions/31810822/opengl-3d-texture-shine-through