正确使用GLTexImage3D时的问题

3
这是我向OpenGL提供Bitmaps的方式。(C#)
public static int Generate3DTexture( string[] names ) // file paths
{
    //basically merging the images into one vertical column of images
    MagickImageCollection allimages = new MagickImageCollection();
    foreach (string eachname in names)
        allimages.Add(new MagickImage(eachname));
    MagickImage template = new MagickImage(MagickColor.FromRgba(0, 0, 0, 0), MasterSize.Width, MasterSize.Height * names.Length);
    Point drawpnt = new Point(0, 0);
    foreach (MagickImage each in allimages)
    {
        template.Composite(each, drawpnt.X, drawpnt.Y, CompositeOperator.Overlay);
        drawpnt.Y += each.Height;
    }
    Bitmap merged = template.ToBitmap();
    //saving the bitmap here is confirmed to stack them vertically
    BitmapData thedata = merged.LockBits(new Rectangle(new Point(0, 0), merged.Size), ImageLockMode.ReadOnly, WfPixelFormat.Format32bppArgb);
    int texId = GL.GenTexture();
    GL.BindTexture(TextureTarget.Texture3D, texId);
    GL.TexImage3D(TextureTarget.Texture3D, 0, PixelInternalFormat.Rgba, MasterSize.Width, MasterSize.Height, names.Length, 0, GlPixelFormat.Bgra, PixelType.UnsignedByte, thedata.Scan0);
    GL.GenerateMipmap(GenerateMipmapTarget.Texture3D);
    GL.BindTexture(TextureTarget.Texture3D, 0);
    merged.UnlockBits(thedata);
    return texId;
}

我找到了一个关于数据应该如何组织的描述在这里,我理解为图像应该是垂直排列的,并且可能会翻转或其他操作。

因此,在我的测试中,我使用了2张图片,在片段着色器中,我这样应用纹理:

void main()
{
    outputColor =  texture3D(ThreeDTexture,vec3(texcoord.x, 1.0 - texcoord.y, 0));
}

结果是两个图像以大致相等的比例合并。如果我把vec3.z参数设为0.5,那就是我所期望的。所以我用三张图片试了一下。它给出了前两张图片和最后两张图片的50-50组合(?!?!?)。这是在不考虑我给vec3.z赋的值的情况下的行为。
我本来期望这个参数是提供的图像的Z轴。或者如果我使用整数,则为提供的图像数组的索引。
编辑:它是索引,但被投影到0到1的范围上,就像x、y坐标一样。
我哪里做错了?
我向OpenGL提供的内容(顺序):
链接:What I'm giving to OpenGL 结果:
链接:The result. 编辑:正如Rabbid76所解释的那样,解决方案是在调用GL.TexImage3D之后插入以下内容:
    GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
    GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
    GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapR, (int)TextureParameterName.ClampToEdge);
1个回答

2
纹理环绕参数GL_TEXTURE_WRAP_SGL_TEXTURE_WRAP_TGL_TEXTURE_WRAP_R默认为GL_REPEAT
缩小函数(GL_TEXTURE_MIN_FILTER)和放大函数的默认参数(GL_TEXTURE_MAG_FILTER)分别为GL_NEAREST_MIPMAP_LINEARGL_LINEAR
请参见glTexParameter
当"REPEAT"和"LINEAR"组合在一起时,如果传递给查找函数的纹理坐标参数为0.0,则第一个体素将与行、列或深度层的最后一个体素混合(插值)。
如果使用包裹参数GL_CLAMP_TO_EDGE,则第一个和最后一个体素不会混合,因为纹理坐标被夹住了。
请注意,第一个体素(或像素)的纹理坐标为1 /(2 * N),最后一个体素的坐标为1-1 /(2 * N),其中N是行、列或层中的体素数。因此,坐标0.0恰好位于第一个和最后一个体素的中间。GL_REPEAT会将坐标0.0夹住1 /(2 * N)

完全正确。已将等效的openTK代码添加到问题中。谢谢。 - gunfulker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接