【问题标题】:OpenGL 3D Texture mip mapsOpenGL 3D 纹理贴图
【发布时间】:2015-08-29 22:01:33
【问题描述】:

我正在尝试实现 3D 纹理来替代纹理图集。我想将它用于地形表面。在我尝试使用 mip 贴图之前,3D 纹理效果很好(输出颜色始终为黑色)。

世代:

int glTexture;
glTarget = TextureTarget.Texture3D;

GL.GenTextures(1, out glTexture);
GL.BindTexture(glTarget, glTexture);

for (int level = 0; level < LevelCount; level++){
    GL.TexImage3D(glTarget, level, glInternalFormat, width, height, depth, 0, glFormat, glType, IntPtr.Zero);

    width = width >> 1;
    height = height >> 1;
}

为每个人脸和mip图设置数据:

GL.BindTexture(glTarget, glTexture);
GL.TexSubImage3D(glTarget, level, 0, 0, depth, width, height, 1, glFormat, glType, dataPtr);

我敢肯定,所有 mip 贴图都已设置(Apitrace 将它们全部显示为从 512 到 1)。知道发生了什么吗?

【问题讨论】:

标签: c# opengl opentk


【解决方案1】:

3D 纹理不能很好地替代纹理图集。它们应该被视为体积纹理,尤其是在涉及到它们的 mipchain 时,因为以任何其他方式来考虑它们都非常不直观。

这些数字来自微软的Direct3D 11 documentation,但它们也适用于 GL。

2D Array Texture Mipchain (cubemap):

   

3D 纹理 Mipchain:

   

用于将数据上传到 2D 数组纹理中的图层的 API 与 3D 纹理相同,但数据的表示方式截然不同(尤其是您在 mipmap 中看到的)。

【讨论】:

    【解决方案2】:

    要为 3D 纹理指定正确的 mipmap,您需要在所有 3 个方向上减小每个级别的大小:

    for (int level = 0; level < LevelCount; level++){
        GL.TexImage3D(glTarget, level, glInternalFormat, width, height, depth, 0,
                      glFormat, glType, IntPtr.Zero);
    
        width = width >> 1;
        height = height >> 1;
        depth = depth >> 1;
    }
    

    您可以将 3D 纹理描绘为 2D 纹理到 3 维的完整概括。每个 mipmap 在所有 3 个维度上都是前一个 mipmap 大小的一半。 3D 纹理的典型用途是用于可以通过 3D 纹理像素网格描述的体积数据,然后使用 3 个纹理坐标对其进行采样。

    正如评论中已经建议的那样,您尝试使用的听起来更像是 2D 纹理数组。顾名思义,这是一个单独的 2D 纹理数组,其中深度指定了数组中 2D 纹理的数量。

    现在,如果您将纹理数组想象成一堆堆叠在一起的 2D 纹理,它看起来与 3D 纹理非常相似。在这两种情况下,您最终都会得到一个 3D 纹素网格。事实上,只要您不使用 mipmap,这些差异就相当微妙。

    在使用 mipmap 时,存在非常大的差异:

    • 在 3D 纹理中,每个 mipmap 用于整个 3D 纹理。它的形状是一个盒子,每个方向都有一半大小。
    • 在 2D 纹理数组中,数组中的每个纹理都有自己的 mipmap。如果您将整个数组的给定 mipmap 级别的图像再次堆叠在一起,结果仍然具有与原始纹理数组相同数量的图像(即与原始纹理数据相同的深度),但是每个图像的大小(即它的宽度和高度)是上一级大小的一半。

    很明显,您要处理第二种情况。您真正需要做的就是更改纹理目标。在 C 绑定中,纹理目标是 GL_TEXTURE_2D_ARRAY。如果 C# 绑定遵循相同的模式,则应该是:

    glTarget = TextureTarget.Texture2DArray;
    

    由于 3D 纹理和 2D 纹理数组之间的 mipmap 大小不同,它们的采样方式也存在差异。对于 3D 纹理,所有 3 个方向都有 mipmapping。所以线性采样可以使用来自两个不同mipmap级别的8个纹素。对于 2D 纹理数组,采样将始终仅使用来自单层的纹素,这意味着使用来自 2 个 mipmap 级别的 4 个纹素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-15
      • 2012-06-26
      • 2011-07-26
      • 1970-01-01
      • 1970-01-01
      • 2012-11-20
      • 2014-03-04
      • 2018-07-13
      相关资源
      最近更新 更多