opengl:为纹理添加更高分辨率的mipmap

时间:2014-12-08 00:26:48

标签: opengl

每当我想在opengl中使用mipmap时,我需要将最高分辨率的位图上传为mipmap level 0,然后在较高的mipmap级别上传较低分辨率的位图。

我希望能够添加更高分辨率的mipmap以及更低分辨率的mipmap。目前我所知道的唯一硬件方法是启动一个新的mipmap-ed纹理并重新上传所有以前上传的位图。

还有其他硬件方法吗?

编辑:
 GL_TEXTURE_BASE_LEVEL和GL_TEXTURE_MAX_LEVEL似乎没有改变opengl在纹理创建时为所有纹理mipmap级别分配内存的事实,因此在这种情况下不能使用它,因为它不可能知道哪些纹理需要更高分辨率mipmaps并且不会消耗,因此会导致极端的内存浪费。

看起来在硬件中执行此操作的唯一方法是使用mipmap级别0处新生成的更高分辨率mipmap重新创建新纹理,然后在较低的mipmap级别复制所有先前的较低分辨率mipmap。

据我所知,唯一的方法是将所有先前生成的mipmap级别保留在内存中,以防我需要重新加载它们(宁愿不浪费这么多内存),重新生成所有mipmap级别(赢得' t,方式太慢),使用gltexsubimage2d将以前的纹理mipmap级别复制到系统内存,然后将它们上传到新纹理(这样做慢),或者将它们从前一个纹理直接复制到新纹理

那么,有没有办法将纹理的选定mipmap复制到不同纹理的mipmap,例如" glcopytexture(texture_id_1,texture_mipmap_1,texture_id_2,texture_mipmap_2);"

EDIT2:
 似乎有一个近期的延伸(延伸〜2009年成为〜2012年的核心)完全这样做(https://www.opengl.org/wiki/Texture_Storage#Texture_copy),但该合同的要求之一是支持10年前的计算机。

1 个答案:

答案 0 :(得分:1)

无需上传完整的mipmap链以使用纹理。您可以通过设置GL_TEXTURE_BASE_LEVELGL_TEXTURE_MAX_LEVEL来控制所使用的级别范围。

最初创建纹理时,您必须确定基本级别的大小[1]。但是你可以推迟加载最低级别的数据,或者根本不加载它们。

例如,假设您希望纹理在全分辨率下最多为1024x1024,但您知道不需要0级和1级,因为它所用的对象远离相机。您可以使用以下命令从级别2开始创建纹理:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 2);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);

然后,如果你以后决定现在需要纹理一直到0级:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);

我不认为设置GL_TEXTURE_MIN_LOD是必要的,但它不会受到伤害。在这两个代码序列中,您当然可以逐个提供自己的mipmap,而不是调用glGenerateMipmap()

主要需要注意的是,您需要能够指定大于0的级别的数据。因此,您需要在运行时生成自己的mipmap,或者预先烘焙包含mipmap的资源。

此外,即使您没有为这些级别指定数据,实现也可能决定将完整纹理分配到级别0。所以你可能会或可能不会以这种方式节省内存。你唯一可以指望的是它加速了初始纹理上传。

[1]这不是严格意义上的,因为对于给定大小的更高级别,基本级别有多个有效大小。例如,如果级别2的大小为16,级别1的大小可以是32或33,级别0可以是64,65,66或67.