My OpenGL thematic learning directory, hope to learn with you exchange progress!

  • OpenGL Learning (I) – Terminology understanding
  • OpenGL learning (2) — Xcode build OpenGL environment
  • OpenGL learning (three) – OpenGL base rendering
  • OpenGL learning (4) – front & back culling and depth testing
  • OpenGL Learning (5) – Cropping and Blending
  • OpenGL Learning (6) – Base textures
  • OpenGL Learning (7) — Summary of basic change Comprehensive Exercise practice
  • OpenGL ES Learning (8)
  • OpenGL learning (nine) — OpenGL ES preliminary exploration (next) GLKit
  • OpenGL learning (10) – GLSL syntax introduction
  • OpenGL learning (11) – using GLSL to load pictures
  • OpenGL learning (12) — OpenGL ES texture flipping strategy comparison

First, texture overview

In the physical world, colors in the field of view change rapidly. You can see that a lot of surfaces have a lot of color and a lot of variation on a small area. Capturing color changes with this much detail is painstaking and meticulous work (you need to effectively identify every triangle in each linear color change area). It would be much easier to find an image and “glue” it to a surface, like wallpaper. That’s called texture mapping. Texture mapping (texture for short) is a picture taken or drawn, OpenGL supports one-dimensional, two-dimensional, three-dimensional, cube mapping texture. And cache textures, as well as array textures.

Second, recognize the function

Pixel packing

Image storage space = image height * image width * bytes per pixel

1. Change or restore the storage mode of pixels

We can change or restore the way pixels are stored using the following functions:

void glPixelStorei(GLenum pname,GLint param);

void glPixelStoref(GLenum pname,GLfloat param);

The two functions have the same purpose, except that one ends with I and the other with F. The difference is only the type of the second argument, GLint for I and GLfloat for f. For example, if we want to change to tightly packed pixel data, we call:

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
Copy the code

Parameter 1: GL_UNPACK_ALIGNMENT specifies how OpenGL unpacks image data from the data cache.

Parameter 2: Set the value for GL_UNPACK_ALIGNMENT Similarly, we can use GL_PACK_ALIGNMENT to tell OpenGL how to wrap data from the pixel buffer that is read and placed into a user-specified memory buffer.

2. Read the content of the color cache directly as a pixel map

We cannot draw a pixel map directly into the color buffer, but we can use the following function to read the contents of the color buffer directly as a pixel map: void glReadPixels(GLint x,GLint y,GLSizei width,GLSizei height, GLenum format, GLenum type,const void * pixels);

Parameters that

  • Parameter 1: x, the window coordinates in the lower left corner of the rectangle
  • Parameter 2: y, the window coordinates in the lower left corner of the rectangle
  • Parameter 3: width, the width of the rectangle, in pixels
  • Parameter 4: height, the height of the rectangle, in pixels
  • Parameter 5: format indicates the pixel format of OpenGL, as shown in Table 1-1
  • OpenGL specifies the data type in the cache to store the color component. See Table 1-2 for the data type of pixel data
  • Parameter 7: Pixels, a pointer to graphic data

void glReadBuffer(GLenum mode); – > Specify the cache to read

void glWriteBuffer(GLenum mode); – > Specify the cache for writes

Table 1-1 OpenGL pixel format

constant describe
GL_RGB Describes the colors in red, green, and blue order
GL_RGBA Colors in red, green, blue, Alpha order
GL_BGR Arrange colors in blue, green, and red order
GL_BGRA Arrange colors in blue, green, red, Alpha order
GL_RED Each pixel contains only one red component
GL_GREEN Each pixel contains only one green component
GL_BLUE Each pixel contains only one blue component
GL_RG Each pixel in turn contains a red and green component
GL_RED_INTEGER Each pixel contains a red component in integer form
GL_GREEN_INTEGER Each pixel contains a green component in integer form
GL_BLUE_INTEGER Each pixel contains a blue component in integer form
GL_RG_INTEGER Each pixel in turn contains an integer red and green component
GL_RGB_INTEGER Each pixel contains an integer red, blue, and green component
GL_RGBA_INTEGER Each pixel contains an integer red, blue, green, Alpha component
GL_BGR_INTEGER Each pixel contains an integer blue, green, and red component
GL_BGRA_INTEGER Each pixel contains an integer blue, green, red, Aplha component
GL_STENCIL_INDEX Each pixel contains only one template value
GL_DEPTH_COMPONENT Each pixel contains only one depth value
GL_DEPTH_STENCIL Each pixel contains a depth value and a template value

The last three formats, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, and GL_DEPTH_STENCIL, are used to read and write directly to the template buffer and depth buffer. The parameter Type explains the data pointed to by the parameter Pixels. It tells OpenGL what data type of the buffer to use to store the color component. Table 1-2 shows the following table. Table 1-2 Data types of pixel data

constant describe
GL_UNSIGNED_BYTE Each color has one component8There is nointeger
GL_BYTE 8There areinteger
GL_UNSIGNED_SHORT 16There is nointeger
GL_SHORT 16There areinteger
GL_UNSIGNED_INT 32There is nointeger
GL_INT 32There areinteger
GL_FLOAT singlePrecision floating point number
GL_HALF_FLOAT And a halfPrecision floating point number
GL_UNSIGNED_BYTE_3_2_2 The packing ofRGB
GL_UNSIGNED_BYTE_2_3_3_REV The packing ofRGB
GL_UNSIGNED_SHORT_5_6_5 The packing ofRGB
GL_UNSIGNED_SHORT_5_6_5_REV The packing ofRGB
GL_UNSIGNED_SHORT_4_4_4_4 The packing ofRGBA
GL_UNSIGNED_SHORT_4_4_4_4_REV The packing ofRGBA
GL_UNSIGNED_SHORT_5_5_5_1 The packing ofRGBA
GL_UNSIGNED_SHORT_5_5_5_1_REV The packing ofRGBA
GL_UNSIGNED_INT_8_8_8_8 The packing ofRGBA
GL_UNSIGNED_INT_8_8_8_8_REV The packing ofRGBA
GL_UNSIGNED_INT_10_10_10_2 The packing ofRGBA
GL_UNSIGNED_INT_2_10_10_10_REV The packing ofRGBA
GL_UNSIGNED_INT_24_8 The packing ofRGBA
GL_UNSIGNED_INT_10F_11F_11F_REV The packing ofRGBA
GL_FLOAT_32_UNSIGNED_INT_24_8_REV The packing ofRGBA

3. Load the texture

When applying texture mapping to a geometry, the first necessary step is to load the texture into memory. Once loaded, these textures become part of the current texture state. There are three OpenGL functions that are most often used to load texture data from a memory buffer (such as reading from a disk file).

void glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);

void glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);

void glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
Copy the code

These three functions are actually derived from the same function, glTexImage.

Parameters that

  • Target: texture dimensions GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D.
  • Level: Specifies the mIP map Level to load. We usually set this parameter to 0.
  • Internalformat: How many color components to store in each texture unit. (Obtained when reading the pixel image)
  • Width, height, depth: indicates the width, height, and depth of the loaded texture. = = attention! These values must be raised to an integer power of 2. (This is due to a requirement left over from older versions of OpenGL. Now, of course, it’s possible to support an integer power other than 2. But developers are still used to setting these parameters to the integer power of 2.
  • Border parameter: allows you to specify a border width for the texture map.
  • The format arguments:Data type of pixel data (GL_UNSIGNED_BYTEEach color component is one8Bit unsigned integer)
  • The type parameter:
  • Data parameter: pointer to texture image data

4. Use color buffers

One – and two-dimensional textures can also load data from the color buffer. We can read an image from the color buffer and use it as a new texture using the following two functions.

void glCopyTexImage1D(GLenum target,GLint level,GLenum internalformt,GLint x,GLint y,GLsizei width,GLint border);
void glCopyTexImage2D(GLenum target,GLint level,GLenum internalformt,GLint x,GLint y,GLsizei width,GLsizei height,GLint border);
Copy the code

These functions operate like glTexImage, except that x and y specify in the color buffer where to start reading the texture data. The source buffer is set by the glReadBuffer function. Note that there is no glCopyTexImage3D because we cannot get volume data from the 2D color buffer.

5. Update textures

Replacing a texture image is often much faster than simply reloading a new texture using glTexImage. The function used to do this is glTexSubImage, which also has three variants.

void glTexSubImage1D(GLenum target,GLint level,GLint xOffset,GLsizei width,GLenum
  format,GLenum type,const GLvoid *data);

void glTexSubImage2D(GLenum target,GLint level,GLint xOffset,GLint yOffset,GLsizei
  width,GLsizei height,GLenum format,GLenum type,const GLvoid *data);

void glTexSubImage3D(GLenum target,GLint level,GLint xOffset,GLint yOffset,GLint
  zOffset,GLsizei width,GLsizei height,GLsizei depth,Glenum type,const GLvoid * data);
Copy the code

Most of the parameters correspond exactly to the parameters of the glTexImage function. The xOffset, yOffset, and zOffset parameters specify the offset at which to start replacing texture data in the original texture map. The width, height, and depth parameters specify the width, height, and depth of the new texture to be “inserted” into the original texture.

6. Insert and replace textures

The following set of functions allows us to read the texture from the color buffer and insert or replace portions of the original texture. The following set of functions are variations of the glCopyTexSubImage function.

void glTexSubImage1D(GLenum target,GLint level,GLint xOffset,GLsizei width,GLenum
  format,GLenum type,const GLvoid *data);

void glTexSubImage2D(GLenum target,GLint level,GLint xOffset,GLint yOffset,GLsizei
  width,GLsizei height,GLenum format,GLenum type,const GLvoid *data);

void glTexSubImage3D(GLenum target,GLint level,GLint xOffset,GLint yOffset,GLint
  zOffset,GLsizei width,GLsizei height,GLsizei depth,Glenum type,const GLvoid * data);
Copy the code

Note: there is no glCopyTexImage function. This is because the color buffer is 2D and there is no corresponding way to use a 2D color image as a source for a 3D texture. However, we can use the glCopyTexSubImage3D function to set one of the texture unit planes in a 3D texture using the color buffer data.

7. Texture objects

1) Assign texture objects

void glGenTextures (GLsizei n, GLuint *textures);
Copy the code

In this function, we can specify the number of texture objects n and a pointer * Textures that points to an array of unsigned integers (filled with texture object identifiers).

2) Bind texture state

We can think of them as handles to different available texture states. To “bind” one of the texture states, call the following function. After that, all texture loading and texture parameter Settings only affect the currently bound texture object.

void glBindTexture (GLenum target, GLuint texture);
Copy the code
  • Parameters target: GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D
  • Parameter texture: The texture object to bind to

3) Read texture bits and read pixels

// Load a .TGA file
GLbyte *gltReadTGABits(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat, GLbyte *pData = NULL);
Copy the code
  • Parameter szFileName: Texture file name
  • Parameter iWidth: file width address
  • Parameter iHeight: file height address
  • Parameter iComponents: address of the file component
  • Parameter eFormat: indicates the file format address
  • Return value: pointer to image data

4) Delete the bound texture object

void glDeleteTextures (GLsizei n, const GLuint *textures);
Copy the code

5) Test whether the texture object is valid

GLboolean glIsTexture(GLuint texture)
Copy the code

Return GL_TRUE if this is a previously allocated texture object name, GL_FALSE otherwise.

8. Set texture parameters

The application of many parameters affects the rules of rendering and the behavior of texture maps. These texture parameters are set as variables of the glTexParameter function.

void glTexParameterf (GLenum target, GLenum pname, GLfloat param);
void glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
void glTexParameteri (GLenum target, GLenum pname, GLint param);
void glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
Copy the code
  • Parameter 1: target specifies which texture mode these parameters will be applied to, such as GL_TEXTURE_1D, GL_TEXTURE_2D, and GL_TEXTURE_3D.
  • Parameter 2: pname specifies which texture parameter to set
  • Parameter 3: Param or params, used to set the value of a specific texture parameter

9. Set the filtering mode

The process of calculating color segments from a stretched or contracted Texture map is called Texture Filitering. Using OpenGL’s texture parameter function, you can set the zoom in and zoom out filters at the same time. The parameter names for these two filters are GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER. We can choose for them from two basic texture filters, GL_NEAREST and GL_LINEAR, which correspond to adjacent and linear filters respectively.

1) Adjacent filtration (GL_NEAREST) :

Proximity filtering is the application of the nearest texture unit to texture coordinates. As shown in Figure 1, the center of the texture pixel in the upper left corner is closest to the texture coordinates, so it will be selected as the sample color:

2) Linear filtering (GL_LINEAR) :

As shown in FIG. 2, linear filtering will apply the weighted average value of texture units around this texture coordinate to this texture coordinate (linear interpolation). The closer the center of a texture pixel is to the texture coordinate, the greater the contribution of the color of this texture pixel to the final sample color. In the image below you can see that the returned color is a blend of adjacent pixels:

The visual effects of the two texture filters when applying a low-resolution texture to a large object (the texture is magnified and visible to every texture pixel) :

We can use the following function to filter:

void glTexParameteri (GLenum target, GLenum pname, GLint param);
Copy the code

Four combination methods of filtering:

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_HEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_HEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
Copy the code

10. Set the surround mode

Normally, we specify texture coordinates in the range 0.0 to 1.0 to map them to the texture units in the texture map. If the texture coordinates fall outside this range, OpenGL handles the problem according to the current Wrapping Mode.

Wrapping method describe
GL_REPEAT Default behavior for textures. Repeat texture image.
GL_MIRRORED_REPEAT Same as GL_REPEAT, but each repeat image is mirrored.
GL_CLAMP_TO_EDGE The texture coordinates are constrained between 0 and 1, and the excess portion repeats the edges of the texture coordinates, creating the effect of the edges being stretched.
GL_CLAMP_TO_BORDER The coordinate beyond is the user-specified edge color.

Each option has a different effect when texture coordinates are outside the default range. The diagram below:

Set texture parameters:

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAR_S,GL_CLAMP_TO_EDGE);
Copy the code
  • Parameter 1: texture dimension. GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D

  • Parameter 2: Sets the mode for the S/T coordinates. GL_TEXTURE_WRAP_S, GL_TEXTURE_T, GL_TEXTURE_R, for s, T,r coordinates

  • Parameter 3: wrapMode, surround mode. GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
  • (1) GL_REPEAT: OpenGL repeats the texture in the direction of texture coordinates exceeding 1.0;
  • GL_CLAMP: The required texture units are taken from the texture boundary or TEXTURE_BORDER_COLOR.
  • (3) GL_CLAMP_TO_EDGE: Surround mode forces texture coordinates out of range to be sampled along the last row or column of a valid texture unit.
  • (4) GL_CLAMP_TO_BORDER: only use border texture units where texture coordinates are outside the range of 0.0 to 1.0. Boundary texture units are loaded with the base texture image as additional rows and columns around the base image.

Here is an example of combining the previous functions:

// Load the TGA file as a 2D texture.
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
    GLbyte *pBits;
    int nWidth, nHeight, nComponents;
    GLenum eFormat;
    
    //1, read texture bit, read pixel
    // Parameter 1: texture file name
    // Parameter 2: file width address
    // Parameter 3: file height address
    // Parameter 4: address of the file component
    // Parameter 5: file format address
    // Return value: pBits, pointer to image data
    
    pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
    if(pBits == NULL)
        return false;
    
    //2. Set texture parameters
    // Parameter 1: texture dimension
    // Parameter 2: sets the mode for the S/T coordinates
    // Parameter 3: wrapMode, surround mode
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
    
    // Parameter 1: texture dimension
    // Parameter 2: linear filtering
    // Parameter 3: wrapMode, surround mode
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
    
    //3. Precision packaging of pixel data
    // Parameter 1: GL_UNPACK_ALIGNMENT specifies how OpenGL unpacks image data from the data cache
    // Parameter 2: specifies the GL_UNPACK_ALIGNMENT value
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    
    // Load the texture
    // Parameter 1: texture dimension
    // Parameter 2: MIP map level
    // Parameter 3: The color component stored in the texture unit (obtained from reading the pixel map)
    // Parameter 4: load texture width
    // Parameter 5: load texture high
    // Parameter 6: depth to load texture
    // Parameter 7: Data type of pixel data (GL_UNSIGNED_BYTE, each color component is an 8-bit unsigned integer)
    // Parameter 8: pointer to texture image data
    
    glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0,
                 eFormat, GL_UNSIGNED_BYTE, pBits);
    
    // Release pBits after use
    free(pBits);
    
    
    // Mip maps can be generated only if minFilter equals the following four modes
    //GL_NEAREST_MIPMAP_NEAREST has very good performance and very weak flicker
    //GL_LINEAR_MIPMAP_NEAREST is often used to speed up games with a high quality linear filter
    // The GL_LINEAR_MIPMAP_LINEAR and GL_NEAREST_MIPMAP_LINEAR filters perform some additional interpolation between the Mip layers to eliminate filtering traces between them.
    //GL_LINEAR_MIPMAP_LINEAR TRI-linear Mip map. The gold standard of texture filtering, with the highest accuracy.
    if(minFilter == GL_LINEAR_MIPMAP_LINEAR ||
       minFilter == GL_LINEAR_MIPMAP_NEAREST ||
       minFilter == GL_NEAREST_MIPMAP_LINEAR ||
       minFilter == GL_NEAREST_MIPMAP_NEAREST)
        
        // Load Mip, texture generates all Mip layers
        // Parameters: GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D
        glGenerateMipmap(GL_TEXTURE_2D);
    
    return true;
}
Copy the code

The above summary refers to and partly extracts from the following articles. Many thanks to the following authors for sharing:

OpenGl’s learnopengl-CN section on “Textures”

2. OpenGL Super Treasure Book 5th Edition

3. OpenGL Programming Guide (Original Book 9th Edition)

Reprint please note the original source, shall not be used for commercial communication – any more