为 2D 纹理数组生成 mip 级别

Posted

技术标签:

【中文标题】为 2D 纹理数组生成 mip 级别【英文标题】:Generating mip levels for a 2D texture array 【发布时间】:2011-09-30 22:17:18 【问题描述】:

我有一个关于 OpenGL 纹理数组的简单(我认为)问题。我使用以下内容创建纹理数组:

glTexImage3D(   GL_TEXTURE_2D_ARRAY,
        0,
        formatGL,
        width,
        height,
        slices,
        0,
        GL_RGBA, 
        GL_UNSIGNED_BYTE, 
        nullptr);

请注意,我还不想实际将任何图像加载到其中。我只是在创建稍后将填充数据的结构。

所以我的问题是:

    如何为纹理数组的每个“切片”生成 mip 链?我不想物理生成mip,我只想通过告诉它mip来完成纹理。我可以用 2D 纹理简单地通过调用 glTexImage2D 函数和 mip 级别、大小并传入一个 nullptr 来实现。鉴于没有“切片”参数,我看不到如何使用 glTexImage3D 函数执行此操作。 OpenGL 超级示例仅将 .bmp 加载到数组中每个纹理的第一个 mip 级别。说使用 glTexSubImage3D 并传入 nullptr 将为数组中的给定纹理创建我想要的 mip 级别是否正确?

    khronos.org 上关于 glGenerateMipMap 的文档仅指定 GL_TEXTURE_2D 或 GL_TEXTURE_CUBE_MAP。那么说我不能将这种方法用于 2D 纹理数组是否正确?

以下是我使用 2D 纹理创建 mip 链的方法:

    size_t i = 0, mipSizeX = width, mipSizeY = height;

    while(mipSizeX >= 1 || mipSizeY >= 1)
    
        // Generate image for this mip level

        glTexImage2D(   GL_TEXTURE_2D,
                        i,
                        formatGL,
                        mipSizeX,
                        mipSizeY,
                        0,
                        GL_RGBA, 
                        GL_UNSIGNED_BYTE, 
                        nullptr);

        // Go to the next mip size.

        mipSizeX >>= 1;
        mipSizeY >>= 1;

        // and the next mipmap level.

        i++;
    

【问题讨论】:

【参考方案1】:

我可以简单地通过调用 glTexImage2D 函数和 mip 级别、大小并传入一个 nullptr 来处理 2D 纹理。鉴于没有“切片”参数,我看不到如何使用 glTexImage3D 函数执行此操作。

为什么不呢? glTexImage3D 采用 mipmap 级别,就像 glTexImage2D 一样。它需要一个大小,在 2D 中是二维,但在 3D 中是三个维度。

确实,两个函数之间的唯一区别在于它们采用的维数(以及可能的target 参数)。并且有一个“切片”参数;您在向我们展示的通话中将其与 glTexImage3D 一起使用。在那里,它被称为depth

3D 纹理和 2D 数组纹理之间的区别在于,depth 在 2D 数组的较低 mipmap 中不会改变。数组的每个 mipmap 与其他每个 mipmap 具有相同数量的“切片”。

khronos.org 上的文档

如果它是在“khronos.org”而不是“opengl.org”,那么几乎可以肯定是在谈论 OpenGL ES,它没有数组纹理(稍后说明: strong> ES 3.0 添加了数组纹理)。


如果不实际为您编写代码,我真的不知道如何变得更清晰。

size_t i = 0, mipSizeX = width, mipSizeY = height;

while(mipSizeX >= 1 || mipSizeY >= 1)

    // Generate image for this mip level

    glTexImage3D(   GL_TEXTURE_2D_ARRAY,
                    i,
                    formatGL,
                    mipSizeX,
                    mipSizeY,
                    arrayCount,
                    0,
                    GL_RGBA, 
                    GL_UNSIGNED_BYTE, 
                    nullptr);

    // Go to the next mip size.

    mipSizeX >>= 1;
    mipSizeY >>= 1;

    // and the next mipmap level.

    i++;

另外,您需要检查 mipmap 大小的最小值是否为 1。因为 (1 >> 1) == 0

【讨论】:

我不确定在这种情况下将什么放入“切片”参数中。零?这里的问题是我正在构建一个 2d 纹理,通过 3d 界面并没有真正用我的大脑计算:p。 @Robinson:问题在于您没有制作 2D 纹理。您正在制作 2D 纹理的 array。该数组中元素的数量是 depth (我不知道你从哪里得到“切片”,因为the documentation 清楚地使用了“深度”这个词。 抱歉,slices 在其他地方是这样称呼的!所以我迭代mip级别迭代“深度”,调用glTextImage3D,GL会随着深度的增加自动扩展数组?我假设深度是“我想要数组中有多少图像”,而不是“索引到数组中”,主要是因为当我第一次调用它时,数组还不存在。 @Robinson:深度“我想要数组中有多少图像”;这就是我在写“该数组中元素的数量是深度”时所说的。 @Robinson:把它想象成用new[] 分配一个对象数组。 depth 是您放入 [] 的内容。

以上是关于为 2D 纹理数组生成 mip 级别的主要内容,如果未能解决你的问题,请参考以下文章

CCTexture2D CCSpriteBatchNode CCTextureCache CCSpriteFrameCache 分析

CCTexture2D CCSpriteBatchNode CCTextureCache CCSpriteFrameCache 分析

无法手动设置每个纹理 mipmap 级别

如何在 glTexImage2D 中使用动态大小的纹理数组?

手把手教会OpenGL之纹理贴图包含纹理载入纹理过滤边界处理纹理参数设置(入门级别案例,棋盘)

手把手教会OpenGL之纹理贴图包含纹理载入纹理过滤边界处理纹理参数设置(入门级别案例,棋盘)