glTexStorage* 为指定的纹理创建固定存储。也就是分配的存储空间不可改变,这样就可以让纹理对象停止跟踪纹理的某些方面。 而纹理中的内容可以使用glTexSubImage* 来改变。glTexStorage2D申请的纹理空间,可在后续glTexSubImage2D分割多个使用
glGenTextures(1, &m_sourceTexture );
glBindTexture(GL_TEXTURE_2D, m_sourceTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, intFormat, w, h );
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, m_sourceImage->getLevel(0));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glGenTextures(1, &m_resultTexture );
glBindTexture(GL_TEXTURE_2D, m_resultTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, intFormat, w, h );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
以上描述了存储在纹理中存在的方式。如何创建该存储是另一回事。
纹理存储有三种类型:可变存储、不可变存储和缓冲区存储。只有缓冲区纹理 Buffer Texture可以使用缓冲区存储,其中纹理从缓冲区对象 Buffer Object获取其存储。同样,缓冲区纹理不能使用可变或不可变的存储。任何其他类型的纹理都可以使用可变或不可变存储(好吧,缓冲区对象的存储可以是不可变的,但这是缓冲区对象的存储,而不是纹理的存储)。因此,除一节外,下面的讨论将侧重于可变和不可变存储。
可变存储分配和不可变存储分配之间的一个巨大区别是:不可变存储一次为纹理分配所有图像。每个 mipmap 级别、数组层和立方体贴图面都通过单个调用进行分配,从而为所有这些图像提供特定的图像格式。它被称为“不可变”,因为一旦分配了存储,就无法更改存储。纹理可以正常删除,但不能更改存储。具有 5 个 mipmap 图层且使用GL_RGBA8图像格式的 256x256 2D 纹理将*始终*为 256x256 2D 纹理,其中包含 5 个使用GL_RGBA8图像格式的 mipmap 图层。
请注意,不可变存储指的是内存的分配,而不是该内存的内容。您可以根据需要将不同的像素数据上传到不可变存储中。使用可变存储,您可以完全重新调整纹理对象的存储,将 256x256 纹理更改为 1024x1024 纹理。
不可变存储可以类比为“指针常量”C++概念:
char * const pData = new char[500];
pData 指针的值不能更改。不能在 pData 中存储新指针。但是,由于pData的内容不是恒定的,因此根据需要对其进行修改是完全有效的:
char * const pData = new char[500];
std::fill(pData, pData+500, 0); //Legal
std::strcpy(pData, "A String Literal"); //Also legal.
delete []pData; //Yes, this is legal too. You can delete pointer consts.
pData = new char[700]; //NOT LEGAL.
pData = "Foo"; //Also not legal.
核心版本 | 4.6 | |
---|---|---|
核心自版本以来 | 4.2, 4.3 | |
核心 ARB 扩展 | ARB_texture_storage_multisample ARB_texture_storage |
为纹理分配不可变存储需要将纹理绑定到其目标,然后调用 glTexStorage* 形式的函数。调用哪个函数取决于您尝试为其分配存储的纹理类型。每个函数仅适用于一组特定的目标。
有效目标:GL_TEXTURE_1D
有效目标:GL_TEXTURE_2D、GL_TEXTURE_RECTANGLE、GL_TEXTURE_CUBE_MAP或GL_TEXTURE_1D_ARRAY。
对于 1D 数组纹理,每个 mipmap 级别中的数组层数是高度值。对于矩形纹理,mipmap 级别数必须为 1。
有效目标:GL_TEXTURE_3D、GL_TEXTURE_2D_ARRAY GL_TEXTURE_CUBE_MAP_ARRAY(这需要 GL 4.0 或 ARB_texture_cube_map_array)
对于 2D 数组纹理,每个 mipmap 级别中的数组层数是深度值。
对于 2D 立方体贴图数组纹理,立方体贴图图层面数是深度,其必须是 6 的倍数。因此,数组中单个立方体贴图的数量由深度 / 6 给出。
有效目标:GL_TEXTURE_2D_MULTISAMPLE
有效目标:GL_TEXTURE_2D_MULTISAMPLE_ARRAY
这些函数分配具有给定大小(宽度、高度和深度,如果适用)的图像,以及按级别给出的 mipmap 数。存储在此处创建,但该存储的内容未定义。这很像打电话给马洛克;你得到记忆,但里面还没有任何东西。
内部格式参数定义要用于纹理的图像格式。在大多数情况下,任何纹理类型都可以使用任何图像格式。包括压缩格式。请注意,这些函数明确要求使用大小较大的图像格式。因此,GL_RGBA是不够的,你必须要求一个尺寸,比如GL_RGBA8。
对于多样本函数,样本定义纹理中每个纹素将使用的样本数。如果将固定采样位置设置为GL_TRUE,则可以确保以下情况:
核心版本 | 4.6 | |
---|---|---|
核心自版本以来 | 4.3 | |
核心 ARB 扩展 | ARB_texture_view |
除了无限干净的纹理规范语法和错误机会的一般减少之外,为纹理创建不可变存储还有另一个优点:可以在纹理对象之间共享不可变存储。
可变存储绑定到单个纹理对象。不可变存储可以在多个对象之间共享,这样它们都引用相同的内存。可以把它想象成传递一个引用计数的智能指针。每个对象都有自己的智能指针,在引用共享内存的所有对象被销毁之前,内存不会消失。
glTex存储*功能都创建新的不可变存储,阿拉马洛克。为了共享以前创建的不可变存储,我们必须使用不同的函数:
此函数采用两个纹理。原始纹理是当前具有不可变存储的纹理。纹理是一种没有不可变存储的新纹理。目标是纹理的类型。当此功能完成时,它将与原始纹理共享不可变存储。这称为“视图纹理”,因为新纹理表示原始纹理存储中的“视图”。
视图纹理不必查看完全相同大小的存储。它只能引用原始纹理的一部分。例如,如果您有一个具有 6 个 mipmap 级别的不可变纹理,则可以创建一个仅使用 3 个 mipmap 级别的视图。
这是最小级别和数字级别参数的责任。最小级别指定原始纹理中的 mipmap 级别,该级别将成为视图纹理的基本级别。数字级别指定要查看的 mipmap 数。如果原始纹理不是具有 mipmap 的纹理类型(多采样或矩形纹理),则最小级别必须为 0,而数字级别必须为 1。对于可能具有 mipmap 的纹理,则最小级别和数字级别将被固定到源纹理中实际可用的 mipmap 数(尽管如果最小级别超出 mipmap 的范围,则会出现错误)。
对于具有图层或面(GL_TEXTURE_1D_ARRAY、GL_TEXTURE_2D_ARRAY、GL_TEXTURE_CUBE_MAP或GL_TEXTURE_CUBE_MAP_ARRAY)的纹理,可以使用“最小图层”和“数字”指定要获取的图层范围。与 mipmap 级别范围参数一样,图层范围被固定到可用的图层范围,并且 minlayer 必须是图像中的可用图层。立方体贴图被视为具有 6 个图层的数组纹理。此处的立方体贴图数组图层是图层面。
摘自:https://www.khronos.org/opengl/wiki/Texture_Storage