glTexStorage2D 详解

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* 形式的函数。调用哪个函数取决于您尝试为其分配存储的纹理类型。每个函数仅适用于一组特定的目标。

void glTexStorage1D( GLenum target, GLint 水平, GLint 内部格式, GLsizei 宽度 );

有效目标GL_TEXTURE_1D

void GlTexStorage2D( GLenum target, GLint 水平, GLint 内部格式, GLsizei 宽度, GLsizei 高度 );

有效目标GL_TEXTURE_2DGL_TEXTURE_RECTANGLEGL_TEXTURE_CUBE_MAPGL_TEXTURE_1D_ARRAY

对于 1D 数组纹理,每个 mipmap 级别中的数组层数是高度值。对于矩形纹理,mipmap 级别数必须为 1。

void glTexStorage3D( GLenum target, GLint 水平, GLint 内部格式, GLsizei 宽度, GLizei 高度, GLizei 深度 );

有效目标GL_TEXTURE_3DGL_TEXTURE_2D_ARRAY GL_TEXTURE_CUBE_MAP_ARRAY(这需要 GL 4.0 或 ARB_texture_cube_map_array)

对于 2D 数组纹理,每个 mipmap 级别中的数组层数是深度值。

对于 2D 立方体贴图数组纹理,立方体贴图图层面数是深度,其必须是 6 的倍数。因此,数组中单个立方体贴图的数量由深度 / 6 给出。

空隙glTexStorage2D多样本( GLenum target, GLsizei样本, GLint内部格式, GLizei宽度, GLizei高度, GL布尔固定样本位置 );

有效目标GL_TEXTURE_2D_MULTISAMPLE

空隙glTexStorage3D多样本( GLenum target, GLsizei样本, GLint 内部格式, GLsizei 宽度, GLizei 高度, GLizei 深度, GL布尔固定样本定位 );

有效目标GL_TEXTURE_2D_MULTISAMPLE_ARRAY

这些函数分配具有给定大小(宽度高度深度,如果适用)的图像,以及按级别给出的 mipmap 数。存储在此处创建,但该存储的内容未定义。这很像打电话给马洛克;你得到记忆,但里面还没有任何东西。

内部格式参数定义要用于纹理的图像格式。在大多数情况下,任何纹理类型都可以使用任何图像格式。包括压缩格式。请注意,这些函数明确要求使用大小较大的图像格式。因此,GL_RGBA是不够的,你必须要求一个尺寸,比如GL_RGBA8

对于多样本函数,样本定义纹理中每个纹素将使用的样本数。如果将固定采样位置设置为GL_TRUE,则可以确保以下情况:

  1. 图像中的纹素将全部使用相同的示例位置。
  2. 图像中的纹素都将使用相同数量的样本位置(通常,实现可能会提供比样本少的某些纹素,而其他纹素会获得更多)。
  3. 具有固定采样位置的所有纹理都将使用同一组示例位置,而不考虑图像格式。

纹理视图

纹理视图
核心版本 4.6
核心自版本以来 4.3
核心 ARB 扩展 ARB_texture_view

除了无限干净的纹理规范语法和错误机会的一般减少之外,为纹理创建不可变存储还有另一个优点:可以在纹理对象之间共享不可变存储。

可变存储绑定到单个纹理对象。不可变存储可以在多个对象之间共享,这样它们都引用相同的内存。可以把它想象成传递一个引用计数的智能指针。每个对象都有自己的智能指针,在引用共享内存的所有对象被销毁之前,内存不会消失。

glTex存储*功能都创建新的不可变存储,阿拉马洛克。为了共享以前创建的不可变存储,我们必须使用不同的函数:

void glTextureView(GLuint 纹理, GLenum 目标, GLuint 原始纹理, GLenum 内部格式, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers)

此函数采用两个纹理。原始纹理是当前具有不可变存储的纹理。纹理是一种没有不可变存储的新纹理。目标是纹理的类型。当此功能完成时,它将与原始纹理共享不可变存储。这称为“视图纹理”,因为新纹理表示原始纹理存储中的“视图”。

视图纹理不必查看完全相同大小的存储。它只能引用原始纹理的一部分。例如,如果您有一个具有 6 个 mipmap 级别的不可变纹理,则可以创建一个仅使用 3 个 mipmap 级别的视图。

这是最小级别数字级别参数的责任最小级别指定原始纹理中的 mipmap 级别,该级别将成为视图纹理的基本级别。数字级别指定要查看的 mipmap 数。如果原始纹理不是具有 mipmap 的纹理类型(多采样或矩形纹理),则最小级别必须为 0,而数字级别必须为 1。对于可能具有 mipmap 的纹理,则最小级别数字级别将被固定到源纹理中实际可用的 mipmap 数(尽管如果最小级别超出 mipmap 的范围,则会出现错误)。

对于具有图层或面(GL_TEXTURE_1D_ARRAYGL_TEXTURE_2D_ARRAYGL_TEXTURE_CUBE_MAPGL_TEXTURE_CUBE_MAP_ARRAY)的纹理,可以使用“最小图层”“数字”指定要获取的图层范围。与 mipmap 级别范围参数一样,图层范围被固定到可用的图层范围,并且 minlayer 必须是图像中的可用图层。立方体贴图被视为具有 6 个图层的数组纹理。此处的立方体贴图数组图层是图层面。

摘自:https://www.khronos.org/opengl/wiki/Texture_Storage

你可能感兴趣的:(C++,opengl,开发语言)