本文主要是介绍8.26 OpenGL纹理和采样器:纹理图像加载和存储,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
纹理图像加载和存储 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
标识的纹理是一维数组、二维数组、三维、立方体贴图、立方体贴图数组或二维多重采样数组纹理,则可以绑定整个纹理级别或纹理级别的单个层或面。如果layered
为TRUE
,则绑定整个级别。如果layered
为FALSE
,则只绑定由layer
标识的单个层。当layered
为FALSE
时,单个绑定的层将被视为图像访问的不同纹理目标。
- 一维数组纹理层被视为一维纹理;
- 二维数组、三维、立方体贴图和立方体贴图数组纹理层被视为二维纹理;
- 二维多重采样数组纹理被视为二维多重采样纹理。
对于layered为FALSE的立方体贴图纹理,通过将层编号映射到面,根据Table 9.3
映射面。
对于layered为FALSE的立方体贴图数组纹理,通过以下方程和将面映射到面,根据Table 9.3
映射面:
layer = floor(layerorig / 6)
face = layerorig − (layer × 6)
如果由texture
标识的纹理没有多个层或面,无论layered
和layer
指定的值如何,都将绑定整个纹理级别。
format
指定在进行格式化存储时将图像元素视为的格式,稍后在本节中描述。这被称为图像单元格式。
access
指定绑定到图像的纹理将被视为READ_ONLY
、WRITE_ONLY
还是READ_WRITE
。如果着色器从绑定为WRITE_ONLY
的图像单元读取,或者向绑定为READ_ONLY
的图像单元写入,则该着色器操作的结果是未定义的,可能导致应用程序终止。
如果一个绑定到一个或多个图像单元的纹理对象被DeleteTextures
删除,它将从每个图像单元中分离,就像调用BindImageTexture
将unit
标识的图像单元和texture
设置为零一样。
将纹理绑定到多个图像单元
void glBindImageTextures(uint first, sizei count, const uint *textures);
将count
个现有纹理对象绑定到从first
到first + count − 1
编号的图像单元。如果textures
不为NULL
,则它指定了一个包含count
个值的数组,每个值必须为零或现有纹理对象的名称。如果textures
为NULL
,则从first
到first + 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
。如上所述,数组或立方图纹理的单层绑定被认为使用与绑定图层对应的纹理目标,而不是整个纹理的目标。
如果纹理目标具有图层或立方体贴图面,则图层或面编号将从BindImageTexture
的layer
参数中获取,如果纹理绑定为layered
为FALSE
,则从Table 8.25
识别的坐标获取。对于将layered
设置为TRUE
的立方体贴图和立方体贴图数组纹理,坐标将以与描述的相同方式映射到图层和面。
如果为图像加载、存储或原子操作识别的单个纹素不存在,则将访问视为无效。无效的图像加载将返回零。无效的图像存储将不产生影响。无效的图像原子将不会更新绑定到图像单元的任何纹理,并将返回零。如果:
- 没有纹理绑定到所选图像单元;
- 绑定到所选图像单元的纹理是不完整的;
- 绑定到图像单元的纹理级别小于基本级别或大于纹理的最大级别;
- 绑定到图像单元的纹理的内部格式在
Table 8.26
中找不到; - 绑定到图像单元的纹理的内部格式与指定的格式不兼容,如下所述;
- 绑定到图像单元的纹理具有图层,并且所选图层或立方体贴图面不存在;
- 所选纹素
τi
,τij
或τijk
不存在; - 图像具有的采样数超过了
MAX_IMAGE_SAMPLES
的值,这是与实现相关的。
此外,在许多情况下,图像加载、存储或原子操作被视为涉及格式不匹配。在这种情况下,图像加载和原子操作将返回未定义值,并且存储和原子操作将写入未定义值。如果:
- 用于访问图像单元的图像变量类型与
layered
设置为TRUE
的图像单元绑定到的纹理的目标不匹配; - 用于访问图像单元的图像变量类型与
layered
设置为FALSE
的多层纹理目标的单个层次对应的目标不匹配; - 用于访问图像单元的图像变量类型具有与图像单元格式不兼容的组件数据类型(浮点、有符号整数、无符号整数);
- 用于图像加载或原子操作的图像变量的格式布局限定符与图像单元的格式不匹配,根据
Table 8.26
; - 用于图像存储的图像变量具有格式布局限定符,并且该限定符与图像单元的格式不匹配,根据
Table 8.26
。
对于每个纹素具有多个样本的纹理,如果样本坐标为负数或大于等于纹理中的样本数,则图像加载、存储或原子操作所选的样本将未定义。
如果着色器使用声明为数组的图像变量执行图像加载、存储或原子操作,并且用于选择单个元素的索引为负数或大于等于数组大小,则操作的结果是未定义的,但可能不会导致终止。
绑定到图像单元的纹理的访问根据绑定图像时指定的格式参数进行格式转换。加载始终作为vec4
、ivec4
或uvec4
返回值返回,存储始终将源数据作为vec4
、ivec4
或uvec4
接收。数据根据以下过程转换为/自指定格式:
- 对于
vec4
数据,使用格式和类型参数为RGBA
和FLOAT
的TexImage2D
或GetTexImage
命令,数据将转换为RGBA
; - 对于
ivec4
数据,使用格式和类型参数为RGBA_INTEGER
和INT
的TexImage2D
或GetTexImage
命令,数据将转换为INT
; - 对于
uvec4
数据,使用格式和类型参数为RGBA_INTEGER
和UNSIGNED_INT
的TexImage2D
或GetTexImage
命令,数据将转换为UNSIGNED_INT
。
未使用的分量将填充为(0,0,0,1)(其中0和1是浮点或整数值,取决于格式)。
用于着色器加载或原子内存操作的任何图像变量必须使用格式布局限定符声明,与其关联的图像单元的格式匹配,如Table 8.26
所列。否则,将认为访问涉及格式不匹配,如上所述。专用于图像存储的图像变量不需要包括格式布局限定符,但任何声明的限定符必须与图像单元格式匹配,以避免格式不匹配。
当纹理绑定到图像单元时,图像单元的格式参数不需要与纹理的内部格式完全匹配,只要这些格式被认为是兼容的即可。如果一对格式在Table 8.27
的Size
列中的相应条目相同,则认为它们在大小上匹配。如果一对格式在Table 8.27
的Class
列中的相应条目相同,则认为它们在类别上匹配。对于由GL分配的纹理,如果它们按大小匹配,则图像单元格式与纹理内部格式兼容。对于在GL外部分配的纹理,格式的兼容性是通过按大小或按类别匹配来确定的,以实现相关的方式。针对特定纹理使用的匹配标准可以通过调用GetTexParameter
,并将pname
设置为IMAGE_FORMAT_COMPATIBILITY_TYPE
来确定,返回值为IMAGE_FORMAT_COMPATIBILITY_BY_SIZE
和IMAGE_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 target | i | j | k | Face / layer |
---|---|---|---|---|
TEXTURE_1D | x | - | - | - |
TEXTURE_2D | x | y | - | - |
TEXTURE_3D | x | y | z | - |
TEXTURE_RECTANGLE | x | y | - | - |
TEXTURE_CUBE_MAP | x | y | - | z |
TEXTURE_BUFFER | x | - | - | - |
TEXTURE_1D_ARRAY | x | - | - | y |
TEXTURE_2D_ARRAY | x | y | - | z |
TEXTURE_CUBE_MAP_ARRAY | x | y | - | z |
TEXTURE_2D_MULTISAMPLE | x | y | - | - |
TEXTURE_2D_MULTISAMPLE_ARRAY | x | y | - | 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 Format | Size | Class | Pixel format | Pixel type |
---|---|---|---|---|
RGBA32F | 128 | 4x32 | RGBA | FLOAT |
RGBA16F | 64 | 4x16 | RGBA | HALF_FLOAT |
RG32F | 64 | 2x32 | RG | FLOAT |
RG16F | 32 | 2x16 | RG | HALF_FLOAT |
R11F_G11F_B10F | 32 | (a) | RGB | UNSIGNED_INT_10F_11F_11F_REV |
R32F | 32 | 1x32 | RED | FLOAT |
R16F | 16 | 1x16 | RED | HALF_FLOAT |
RGBA32UI | 128 | 4x32 | RGBA_INTEGER | UNSIGNED_INT |
RGBA16UI | 64 | 4x16 | RGBA_INTEGER | UNSIGNED_SHORT |
RGB10_A2UI | 32 | (b) | RGBA_INTEGER | UNSIGNED_INT_2_10_10_10_REV |
RGBA8UI | 32 | 4x8 | RGBA_INTEGER | UNSIGNED_BYTE |
RG32UI | 64 | 2x32 | RG_INTEGER | UNSIGNED_INT |
RG16UI | 32 | 2x16 | RG_INTEGER | UNSIGNED_SHORT |
RG8UI | 16 | 2x8 | RG_INTEGER | UNSIGNED_BYTE |
R32UI | 32 | 1x32 | RED_INTEGER | UNSIGNED_INT |
R16UI | 16 | 1x16 | RED_INTEGER | UNSIGNED_SHORT |
R8UI | 8 | 1x8 | RED_INTEGER | UNSIGNED_BYTE |
RGBA32I | 128 | 4x32 | RGBA_INTEGER | INT |
RGBA16I | 64 | 4x16 | RGBA_INTEGER | SHORT |
RGBA8I | 32 | 4x8 | RGBA_INTEGER | BYTE |
RG32I | 64 | 2x32 | RG_INTEGER | INT |
RG16I | 32 | 2x16 | RG_INTEGER | SHORT |
RG8I | 16 | 2x8 | RG_INTEGER | BYTE |
R32I | 32 | 1x32 | RED_INTEGER | INT |
R16I | 16 | 1x16 | RED_INTEGER | SHORT |
R8I | 8 | 1x8 | RED_INTEGER | BYTE |
RGBA16 | 64 | 4x16 | RGBA | UNSIGNED_SHORT |
RGB10_A2 | 32 | (b) | RGBA | UNSIGNED_INT_2_10_10_10_REV |
RGBA8 | 32 | 4x8 | RGBA | UNSIGNED_BYTE |
RG16 | 32 | 2x16 | RG | UNSIGNED_SHORT |
RG8 | 16 | 2x8 | RG | UNSIGNED_BYTE |
R16 | 16 | 1x16 | RED | UNSIGNED_SHORT |
R8 | 8 | 1x8 | RED | UNSIGNED_BYTE |
RGBA16_SNORM | 64 | 4x16 | RGBA | SHORT |
RGBA8_SNORM | 32 | 4x8 | RGBA | BYTE |
RG16_SNORM | 32 | 2x16 | RG | SHORT |
RG8_SNORM | 16 | 2x8 | RG | BYTE |
R16_SNORM | 16 | 1x16 | RED | SHORT |
R8_SNORM | 8 | 1x8 | RED | BYTE |
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
这篇关于8.26 OpenGL纹理和采样器:纹理图像加载和存储的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!