问题描述
每当我想在opengl中使用mipmap时,我都需要将最高分辨率的位图上传为mipmap级别0,然后在更高的mipmap级别上上传分辨率较低的位图.
Whenever I want to use mipmaps in opengl, i need to upload the highest resolution bitmap as mipmap level 0, and then upload lower resolutions bitmaps at higher mipmap levels.
我希望能够添加更高分辨率的Mipmap和更低分辨率的Mipmap.目前,我所知道的唯一硬件方法是启动一个新的mipmap-ed纹理并重新上传所有以前上传的位图.
I would have liked to be able to add higher resolution mipmaps as well as lower resolution mipmaps. Presently the only hardware way I know is to start a new mipmap-ed texture and reupload all previously uploaded bitmaps.
还有其他硬件方式可以做到这一点吗?
Any other hardware way to do this?
看来GL_TEXTURE_BASE_LEVEL和GL_TEXTURE_MAX_LEVEL并没有改变opengl将在创建纹理时为所有纹理mipmap级别分配内存的事实,因此在这种情况下无法使用它,因为无法知道哪些纹理将需要更高分辨率的mipmap,而不会知道哪些纹理会t,这将导致极端的内存浪费.
edit:
It appears GL_TEXTURE_BASE_LEVEL and GL_TEXTURE_MAX_LEVEL do not change the fact that opengl will allocate memory for all texture mipmap levels at texture creation, therefore it can't be used in this case since it's impossible to know which textures will need higher resolution mipmaps and which won't, so it would lead to extreme memory waste.
看来,在硬件中执行此操作的唯一方法是使用新生成的分辨率为0的mipmap重新生成新的纹理,然后复制较低级别的mipmap的所有先前的较低分辨率的mipmap.
It looks that the only way to do this in hardware would be to re-create a new texture with the newly generated higher resolution mipmap at mipmap level 0, and then copy all previous lower resolution mipmaps at lower mipmap levels.
据我所知,唯一的方法是将所有先前生成的mipmap级别保留在内存中,以防万一我需要重新上传它们(宁愿不要浪费这么多的内存),重新生成所有mipmap级别(不会这样做) ,太慢了),使用gltexsubimage2d将以前的纹理mipmap级别复制到系统内存中,然后将其上载到新纹理(这一定很慢),或者直接将它们从以前的纹理复制到新纹理.
As far as I know, the only ways would be either to keep all previously generated mipmap levels in memory in case I need to reupload them (would rather not waste this much memory), regenerate all mipmap levels (won't do, way too slow), copy the previous textures mipmap levels to system memory using gltexsubimage2d and then uploading them to the new texture (that's gotta be slow), or copying them straight from the previous texture to the new texture.
因此,有一种方法可以将纹理的选定mipmap复制到其他纹理的mipmap,例如"glcopytexture(texture_id_1,texture_mipmap_1,texture_id_2,texture_mipmap_2);"
So, is there a way to copy a texture's selected mipmap to a different texture's mipmap, something like "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年以下的旧计算机.
edit2:
It seems there is a somewhat recent extension (extension ~2009 became core in ~2012) that does this exactly (https://www.opengl.org/wiki/Texture_Storage#Texture_copy) but one of the requirements of this contract is support of computers up to 10 years old.
推荐答案
为了使用纹理,不需要上传完整的mipmap链.您可以通过设置GL_TEXTURE_BASE_LEVEL
和GL_TEXTURE_MAX_LEVEL
来控制使用的级别范围.
There is no requirement to upload the complete mipmap chain in order to use a texture. You can control the range of levels that are used by setting GL_TEXTURE_BASE_LEVEL
and GL_TEXTURE_MAX_LEVEL
.
在最初创建纹理时,您必须确定基本级别的大小是[1].但是,您可以推迟加载最低级别的数据,或者根本不加载它们.
You do have to decide what the size of the base level is [1] when you initially create the texture. But you can defer loading the data for the lowest levels, or never load them at all.
例如,假设您想要一个最大分辨率为全分辨率的1024x1024的纹理,但是您知道不需要0和1级,因为它所使用的对象距离相机很远.您可以从2级开始创建纹理:
For example, say you want a texture that will at most be size 1024x1024 at full resolution, but you know that you don't need levels 0 and 1 because the object it is used for is far from the camera. You can create the texture starting at level 2 with:
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级:
Then, if you later decide that you need the texture all the way to level 0 now:
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()
.
I don't think setting GL_TEXTURE_MIN_LOD
is necessary, but it can't hurt. In both code sequences, you can of course provide your own mipmaps one by one instead of calling glGenerateMipmap()
.
主要警告是,您需要能够指定级别大于0的数据.因此,您要么需要在运行时生成自己的mipmap,要么需要包含mipmap的预烘焙资源.
The main caveat is that you need to be able to specify data of levels larger than 0. So you either need to generate your own mipmaps at runtime, or have pre-baked resources that include mipmaps.
此外,即使您没有为这些级别指定数据,实现也可能会决定将整个纹理分配到0级.因此,您可能会或可能不会以这种方式节省内存.您唯一可以依靠的是它可以加快初始纹理的上传速度.
Also, the implementation might decide to allocate the full texture up to level 0 even if you don't specify data for those levels. So you may or may not save memory this way. The only thing you can count on is that it accelerates the initial texture upload.
[1]严格来说,这不是正确的,因为对于给定的更高级别的大小,基本级别有多个有效大小.例如,如果级别2是16,级别1可以是32或33,级别0可以是64、65、66或67.
[1] This is not strictly true, because there are multiple valid sizes for the base level for a given size of a higher level. For example, if level 2 is size 16, level 1 can be size 32 or 33, and level 0 can be 64, 65, 66, or 67.
这篇关于opengl:将更高分辨率的mipmap添加到纹理中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!