8.26 OpenGL纹理和采样器:纹理图像加载和存储

本文详细介绍了如何在OpenGL中使用GL实现将纹理绑定到图像单元进行加载和存储,包括纹理级别、分层、格式、访问控制等关键概念,以及纹理坐标映射和格式转换规则。
摘要由CSDN通过智能技术生成

纹理图像加载和存储 Texture Image Loads and Store

通过将纹理绑定到一组图像单元之一,可以使纹理的内容可供着色器读取和写入。GL实现提供了从零开始编号的图像单元数组,图像单元的总数由实现相关的MAX_IMAGE_UNITS的值确定。与纹理图像单元不同,图像单元没有每个纹理目标的单独绑定点;每个图像单元一次只能绑定一个纹理。

将纹理绑定到图像单元以供图像加载和存储使用

void glBindImageTexture( uint unit, uint texture, int level, boolean layered, int layer, enum access, enum format );

其中,unit标识图像单元,texture是纹理的名称,level选择纹理的单个级别。如果texture为零,则会解除当前绑定到图像单元unit 上的任何纹理。

如果由texture标识的纹理是一维数组、二维数组、三维、立方体贴图、立方体贴图数组或二维多重采样数组纹理,则可以绑定整个纹理级别或纹理级别的单个层或面。如果layeredTRUE,则绑定整个级别。如果layeredFALSE,则只绑定由layer标识的单个层。当layeredFALSE时,单个绑定的层将被视为图像访问的不同纹理目标。

  • 一维数组纹理层被视为一维纹理;
  • 二维数组、三维、立方体贴图和立方体贴图数组纹理层被视为二维纹理;
  • 二维多重采样数组纹理被视为二维多重采样纹理。

对于layered为FALSE的立方体贴图纹理,通过将层编号映射到面,根据Table 9.3映射面。
对于layered为FALSE的立方体贴图数组纹理,通过以下方程和将面映射到面,根据Table 9.3映射面:

layer = floor(layerorig / 6)
face = layerorig − (layer × 6)

如果由texture标识的纹理没有多个层或面,无论layeredlayer指定的值如何,都将绑定整个纹理级别。

format指定在进行格式化存储时将图像元素视为的格式,稍后在本节中描述。这被称为图像单元格式。

access指定绑定到图像的纹理将被视为READ_ONLYWRITE_ONLY还是READ_WRITE。如果着色器从绑定为WRITE_ONLY的图像单元读取,或者向绑定为READ_ONLY的图像单元写入,则该着色器操作的结果是未定义的,可能导致应用程序终止。

如果一个绑定到一个或多个图像单元的纹理对象被DeleteTextures删除,它将从每个图像单元中分离,就像调用BindImageTextureunit标识的图像单元和texture设置为零一样。


将纹理绑定到多个图像单元

void glBindImageTextures(uint first, sizei count, const uint *textures);

count个现有纹理对象绑定到从firstfirst + count − 1编号的图像单元。如果textures不为NULL,则它指定了一个包含count个值的数组,每个值必须为零或现有纹理对象的名称。如果texturesNULL,则从firstfirst + count − 1的每个受影响的图像单元将重置为没有绑定的纹理对象。

当将非零纹理对象绑定到图像单元时,图像单元的级别(level)、分层(layered)、层(layer)和访问(access)参数分别设置为零、TRUE、零和READ_WRITE。图像单元的格式参数取自由textures标识的纹理对象的级别零的纹理图像的内部格式。对于立方体贴图纹理,使用级别零的TEXTURE_CUBE_MAP_POSITIVE_X图像的内部格式。对于多重采样、多重采样数组、缓冲区和矩形纹理,使用单个纹理级别的内部格式。当从图像单元解绑纹理对象时,图像单元参数级别、分层、层和格式将重置为它们的默认值,分别为零、FALSE、0和R8

void glBindImageTextures(uint first, sizei count, const uint *textures);

// 等价于

for (i = 0; i < count; i++) {
    if (textures == NULL || textures[i] = 0) {
        glBindImageTexture(first + i, 0, 0, FALSE, 0, READ_ONLY, R8);
    } else {
        glBindImageTexture(first + i, textures[i], 0, TRUE, 0, READ_WRITE, lookupInternalFormat(textures[i]));
    }
}
// lookupInternalFormat 返回指定纹理对象的内部格式。

textures中指定的值将针对每个图像单元分别进行检查。当特定图像单元的值无效时,该图像单元的状态将保持不变,并生成一个错误。但是,如果其他图像单元的相应值有效,则它们的状态仍将发生变化。


当着色器使用内置图像加载、存储或原子函数访问绑定到图像单元的纹理时,它通过提供一维、二维或三维坐标来标识单个纹素。多重采样纹理访问还会指定采样编号。根据绑定到图像单元的纹理的目标,坐标向量将映射到单个纹素τiτijτijk,使用Table 8.25。如上所述,数组或立方图纹理的单层绑定被认为使用与绑定图层对应的纹理目标,而不是整个纹理的目标。

如果纹理目标具有图层或立方体贴图面,则图层或面编号将从BindImageTexturelayer参数中获取,如果纹理绑定为layeredFALSE,则从Table 8.25识别的坐标获取。对于将layered设置为TRUE的立方体贴图和立方体贴图数组纹理,坐标将以与描述的相同方式映射到图层和面。

如果为图像加载、存储或原子操作识别的单个纹素不存在,则将访问视为无效。无效的图像加载将返回零。无效的图像存储将不产生影响。无效的图像原子将不会更新绑定到图像单元的任何纹理,并将返回零。如果:

  • 没有纹理绑定到所选图像单元;
  • 绑定到所选图像单元的纹理是不完整的;
  • 绑定到图像单元的纹理级别小于基本级别或大于纹理的最大级别;
  • 绑定到图像单元的纹理的内部格式在Table 8.26中找不到;
  • 绑定到图像单元的纹理的内部格式与指定的格式不兼容,如下所述;
  • 绑定到图像单元的纹理具有图层,并且所选图层或立方体贴图面不存在;
  • 所选纹素τiτijτijk不存在;
  • 图像具有的采样数超过了MAX_IMAGE_SAMPLES的值,这是与实现相关的。

此外,在许多情况下,图像加载、存储或原子操作被视为涉及格式不匹配。在这种情况下,图像加载和原子操作将返回未定义值,并且存储和原子操作将写入未定义值。如果:

  • 用于访问图像单元的图像变量类型与layered设置为TRUE的图像单元绑定到的纹理的目标不匹配;
  • 用于访问图像单元的图像变量类型与layered设置为FALSE的多层纹理目标的单个层次对应的目标不匹配;
  • 用于访问图像单元的图像变量类型具有与图像单元格式不兼容的组件数据类型(浮点、有符号整数、无符号整数);
  • 用于图像加载或原子操作的图像变量的格式布局限定符与图像单元的格式不匹配,根据Table 8.26
  • 用于图像存储的图像变量具有格式布局限定符,并且该限定符与图像单元的格式不匹配,根据Table 8.26

对于每个纹素具有多个样本的纹理,如果样本坐标为负数或大于等于纹理中的样本数,则图像加载、存储或原子操作所选的样本将未定义。

如果着色器使用声明为数组的图像变量执行图像加载、存储或原子操作,并且用于选择单个元素的索引为负数或大于等于数组大小,则操作的结果是未定义的,但可能不会导致终止。

绑定到图像单元的纹理的访问根据绑定图像时指定的格式参数进行格式转换。加载始终作为vec4ivec4uvec4返回值返回,存储始终将源数据作为vec4ivec4uvec4接收。数据根据以下过程转换为/自指定格式:

  • 对于vec4数据,使用格式和类型参数为RGBAFLOATTexImage2DGetTexImage命令,数据将转换为RGBA
  • 对于ivec4数据,使用格式和类型参数为RGBA_INTEGERINTTexImage2DGetTexImage命令,数据将转换为INT
  • 对于uvec4数据,使用格式和类型参数为RGBA_INTEGERUNSIGNED_INTTexImage2DGetTexImage命令,数据将转换为UNSIGNED_INT

未使用的分量将填充为(0,0,0,1)(其中0和1是浮点或整数值,取决于格式)。

用于着色器加载或原子内存操作的任何图像变量必须使用格式布局限定符声明,与其关联的图像单元的格式匹配,如Table 8.26所列。否则,将认为访问涉及格式不匹配,如上所述。专用于图像存储的图像变量不需要包括格式布局限定符,但任何声明的限定符必须与图像单元格式匹配,以避免格式不匹配。

当纹理绑定到图像单元时,图像单元的格式参数不需要与纹理的内部格式完全匹配,只要这些格式被认为是兼容的即可。如果一对格式在Table 8.27Size列中的相应条目相同,则认为它们在大小上匹配。如果一对格式在Table 8.27Class列中的相应条目相同,则认为它们在类别上匹配。对于由GL分配的纹理,如果它们按大小匹配,则图像单元格式与纹理内部格式兼容。对于在GL外部分配的纹理,格式的兼容性是通过按大小或按类别匹配来确定的,以实现相关的方式。针对特定纹理使用的匹配标准可以通过调用GetTexParameter,并将pname设置为IMAGE_FORMAT_COMPATIBILITY_TYPE来确定,返回值为IMAGE_FORMAT_COMPATIBILITY_BY_SIZEIMAGE_FORMAT_COMPATIBILITY_BY_CLASS,分别指定按大小和类别匹配。

当与图像单元关联的格式与绑定到图像单元的兼容纹理的内部格式不完全匹配时,图像加载、存储和原子操作将重新解释保存访问的纹素组件的内存,根据图像单元的格式。对于图像加载和原子操作的读取部分,重新解释是作为从绑定纹理的纹素复制到格式化为图像单元格式的类似纹素的数据执行的。类似地,对于图像存储和原子操作的写入部分,重新解释是作为从格式化为图像单元格式的纹素到绑定纹理中的纹素执行的。在这两种情况下,此复制操作将通过以下方式执行:

  • 根据GetTexImage的描述(参见8.11节)将纹素从源格式读取到临时存储器中,使用与Table 8.27中源格式相对应的默认像素存储模式和格式和类型参数;
  • 根据TexSubImage3D的描述(参见8.6节)将纹素从临时存储器写入目标格式,使用与Table 8.27中目标格式相对应的默认像素存储模式和格式和类型参数。

如果图像单元、着色器存储块和活动片段着色器输出的组合数量超出了MAX_COMBINED_SHADER_OUTPUT_RESOURCES的实现相关值,则会生成链接错误。

图像单元查询 Image Unit Queries

每个图像单元所需的状态总结在Table 23.45中,可以使用该表中的索引查询命令进行查询。图像单元状态的初始值如上所述为BindImageTexture


Texture targetijkFace / layer
TEXTURE_1Dx---
TEXTURE_2Dxy--
TEXTURE_3Dxyz-
TEXTURE_RECTANGLExy--
TEXTURE_CUBE_MAPxy-z
TEXTURE_BUFFERx---
TEXTURE_1D_ARRAYx--y
TEXTURE_2D_ARRAYxy-z
TEXTURE_CUBE_MAP_ARRAYxy-z
TEXTURE_2D_MULTISAMPLExy--
TEXTURE_2D_MULTISAMPLE_ARRAYxy-z

Table 8.25: Mapping of image load, store, and atomic texel coordinate components to texel numbers


| Image Unit Format | Format Qualifer |
| RGBA32F rgba32f |
| RGBA16F rgba16f |
| RG32F | rg32f |
| RG16F | rg16f |
| R11F_G11F_B10F | r11f_g11f_b10f |
| R32F | r32f |
| R16F | r16f |
| RGBA32UI | rgba32ui |
| RGBA16UI | rgba16ui |
| RGB10_A2UI | rgb10_a2ui |
| RGBA8UI | rgba8ui |
| RG32UI | rg32ui |
| RG16UI | rg16ui |
| RG8UI | rg8ui |
| R32UI | r32ui |
| R16UI | r16ui |
| R8UI | r8ui |
| RGBA32I | rgba32i |
| RGBA16I | rgba16i |
| RGBA8I | rgba8i |
| RG32I | rg32i |
| RG16I | rg16i |
| RG8I | rg8i |
| R32I | r32i |
| R16I | r16i |
| R8I | r8i |
| RGBA16 | rgba16 |
| RGB10_A2 | rgb10_a2 |
| RGBA8 | rgba8 |
| RG16 | rg16 |
| RG8 | rg8 |
| R16 | r16 |
| R8 | r8 |
| RGBA16_SNORM | rgba16_snorm |
| RGBA8_SNORM | rgba8_snorm |
| RG16_SNORM | rg16_snorm |
| RG8_SNORM | rg8_snorm |
| R16_SNORM | r16_snorm |
| R8_SNORM | r8_snorm |

Table 8.26: Supported image unit formats, with equivalent format layout qualifiers


Image FormatSizeClassPixel formatPixel type
RGBA32F1284x32RGBAFLOAT
RGBA16F644x16RGBAHALF_FLOAT
RG32F642x32RGFLOAT
RG16F322x16RGHALF_FLOAT
R11F_G11F_B10F32(a)RGBUNSIGNED_INT_10F_11F_11F_REV
R32F321x32REDFLOAT
R16F161x16REDHALF_FLOAT
RGBA32UI1284x32RGBA_INTEGERUNSIGNED_INT
RGBA16UI644x16RGBA_INTEGERUNSIGNED_SHORT
RGB10_A2UI32(b)RGBA_INTEGERUNSIGNED_INT_2_10_10_10_REV
RGBA8UI324x8RGBA_INTEGERUNSIGNED_BYTE
RG32UI642x32RG_INTEGERUNSIGNED_INT
RG16UI322x16RG_INTEGERUNSIGNED_SHORT
RG8UI162x8RG_INTEGERUNSIGNED_BYTE
R32UI321x32RED_INTEGERUNSIGNED_INT
R16UI161x16RED_INTEGERUNSIGNED_SHORT
R8UI81x8RED_INTEGERUNSIGNED_BYTE
RGBA32I1284x32RGBA_INTEGERINT
RGBA16I644x16RGBA_INTEGERSHORT
RGBA8I324x8RGBA_INTEGERBYTE
RG32I642x32RG_INTEGERINT
RG16I322x16RG_INTEGERSHORT
RG8I162x8RG_INTEGERBYTE
R32I321x32RED_INTEGERINT
R16I161x16RED_INTEGERSHORT
R8I81x8RED_INTEGERBYTE
RGBA16644x16RGBAUNSIGNED_SHORT
RGB10_A232(b)RGBAUNSIGNED_INT_2_10_10_10_REV
RGBA8324x8RGBAUNSIGNED_BYTE
RG16322x16RGUNSIGNED_SHORT
RG8162x8RGUNSIGNED_BYTE
R16161x16REDUNSIGNED_SHORT
R881x8REDUNSIGNED_BYTE
RGBA16_SNORM644x16RGBASHORT
RGBA8_SNORM324x8RGBABYTE
RG16_SNORM322x16RGSHORT
RG8_SNORM162x8RGBYTE
R16_SNORM161x16REDSHORT
R8_SNORM81x8REDBYTE

Table 8.27: Texel sizes, compatibility classes, and pixel format/type combinations for each image format. Class (a) is for 11/11/10 packed floating-point formats; class (b) is for 10/10/10/2 packed formats

  • 19
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值