Texture Formats

The functions glTexStorage1D(), glTexStorage2D(), glTexStorage3D(), glTexImage1D(), glTexImage2D(), and glTexImage3D() and their corresponding multisample variants all take an internalformat parameter, which determines the format that OpenGL will use to store the internal texture data. They also take a format and type parameter indicating the format and type of the data supplied by the application.

Internal Formats

The internal format of a texture is the format that OpenGL will use to internally store the texture data you give it. Your data will be converted (if necessary) into this format at image specification time. There are a large number of internal formats that OpenGL can store image data in, and each comes with a size, performance, and quality tradeoff. It is up to you, the application writer, to determine the appropriate format for your needs. Table 6.2 lists all of the internal formats supported by OpenGL, along with their bit sizes for each component.

Table 6.2. Sized Internal Formats

Image
Image
Image

For each format listed in Table 6.2 the full format is made up of an identifier representing the base format, one or more size indicators, and an optional type. The base format essentially determines which components of the texture are present. Formats starting with GL_R have only the red component present, GL_RG formats have both red and green, GL_RGB formats contain red, green, and blue, and finally, GL_RGBA contain red, green, blue, and alpha.

The subsequent size indicator determines the number of bits that are used to store the texture data. In many cases, only a single size parameter is included. In such cases, all components present receive the same number of bits. By default, OpenGL stores textures in unsigned normalized format. When data is stored in unsigned normalized format, the values of the texels are stored in memory as an integer which when read into a shader is converted to floating point and divided by the maximum representable value for the corresponding size of integer. This results in data in the range 0.0 to 1.0 (i.e., normalized data) being presented to the shader. If the _SNORM modifier is present (as in GL_RGBA8_SNORM, for example) then the data is signed normalized. In this case, the data in memory is treated as a signed integer, and before it is returned to the shader, it is converted to floating point and divided by the maximum representable signed integer value, resulting in floating-point values in the range –1.0 to 1.0 being returned to the shader.

Type specifiers may be present in the internal format name. These type specifiers are I, UI, and F, indicating signed integer, unsigned integer, and floating-point data, respectively. The signed and unsigned integer internal formats are designed to be used with signed or unsigned integer sampler types in your shader (isampler2D or usampler2D, for example). The floating point internal formats are true floating-point formats in that the data is stored in memory in a floating-point representation and returned to the shader with the full precision supported by the OpenGL implementation. In such cases, the texels can represent floating-point values outside the range –1.0 to 1.0.

In some cases, a different size specifier is used for some or each of the channels. In these cases, OpenGL will use a different number of bits for each of the channels. For example, GL_RGB10_A2 textures are stored using a 32-bit quantity per texel with 10 bits allocated to each of the red, green, and blue channels, but only 2 bits allocated to the alpha channel. This format of texture is useful for representing higher dynamic range textures with only a few levels of opacity (or with the alpha channel used to store something other than traditional opacity). The GL_R11F_G11F_B10F uses 11 bits for each of red and green, and 10 bits for blue, but stores each channel in a special reduced-precision floating point format. The 11-bit components have no sign bit, a 5-bit exponent and a 6-bit mantissa.

The format GL_RGB9_E5 is special in that it is a shared exponent format. Each component is stored as an independent 9-bit mantissa but shares a single 5-bit exponent between all of the components. This allows textures to be stored with a fairly high dynamic range but to only consume 16 bits per texel.

The GL_SRGB8 and GL_SRGB8_ALPHA8 formats are RGB textures in the sRGB color space, the former without alpha and the latter including an alpha channel. The alpha channel in GL_SRGB8_ALPHA8 is represented separately because it is not part of the sRGB color space and is not subject to the (de)gamma calculations affecting the other components.

External Formats

The external format is the format that you use to supply data through the OpenGL API and is represented by the format and type parameters to functions such as glTexSubImage2D(). The format is made up of a part indicating which channels are present and an optional INTEGER format specifier. Additionally, there are a handful of packed integer formats that are used to represent prepacked texture data. Ideally, there would be no conversion required to take your texture data and place it into the texture with the requested internal format.

The possible values for the format parameter are given in Table 6.3, which lists the external format identifier, the components present, their order, and whether the data is comprised of integer values.

Table 6.3. External Texture Formats

Image

Again, notice that the format specifiers listed in Table 6.3 indicate which components are present (red, green, blue, and alpha), their order, and an optional _INTEGER suffix. If this suffix is present, then the values passed to OpenGL are treated as unnormalized integer data and used verbatim. If the internal format of the texture is a floating-point format, then the data is converted to floating point directly—that is, an integer value of 100 becomes 100.0 in floating point, regardless of the incoming data type. If you wish to receive integers in your shader, then you should use an integer sampler type, an integer internal format (e.g., GL_RGBA32UI), and an integer external format and type (e.g., GL_RGBA_INTEGER and GL_UNSIGNED_INT).

The format parameter is used in conjunction with a type parameter to describe the texture data in memory. type is normally one of GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_HALF_FLOAT, or GL_FLOAT to indicate signed or unsigned bytes, signed or unsigned shorts, signed or unsigned integers, or half-precision, or full-precision floating-point quantities. GL_DOUBLE may also be used to indicate double-precision quantities. These tokens correspond to the GLbyte, GLubyte, GLshort, GLushort, GLint, GLuint, GLhalf, GLfloat, and GLdouble types, respectively.

In addition to the tokens representing the native types, several special tokens are used to specify packed or mixed-type formats. These are used when data is packed into larger native types with the boundaries between components not necessarily lining up nicely on native byte, short, or integer boundaries. These type names are generally made up of a standard type specifier (such as GL_UNSIGNED_INT) followed by a suffix indicating how the data is laid out in memory. Table 6.4 shows a few examples of how components may be packed into native data types using packed format tokens.

Table 6.4. Example Component Layouts for Packed Pixel Formats

Image
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
44.200.194.255