What is texture?

Artists and programmers prefer to use textures. A texture is a 2D image (there are even 1D and 3D textures) that can be used to add detail to an object; You can imagine a texture being a piece of paper painted with bricks that folds seamlessly into your 3D house so that your house looks like it has a brick facade. Because we can insert so much detail into a single image, we can make things very fine without specifying extra vertices.

In addition to images, textures can also be used to store a lot of data that can be sent to shaders, but that’s not the subject for now.

To be able to Map a texture to a triangle, we need to specify which part of the texture corresponds to each vertex of the triangle. Each vertex is then associated with a Texture Coordinate that indicates which part of the Texture image to sample from. Then Fragment Interpolation is performed on other segments of the graph.

Texture coordinates are on the X and y axes, ranging from 0 to 1 (note that we are using 2D texture images). Using texture coordinates to get texture colors is calledThe sampling(Sampling). Texture coordinates start at (0, 0), which is the lower left corner of the texture image, and end at (1, 1), which is the upper right corner of the texture image. The image below shows how we map texture coordinates to triangles.

We specify three texture coordinate points for the triangle. As shown above, we want the lower left corner of the triangle to correspond to the lower left corner of the texture, so we set the texture coordinates of the lower left corner of the triangle to (0, 0); The upper vertex of the triangle corresponds to the upper middle position of the image so we set its texture coordinates to (0.5, 1.0); Similarly, the lower right vertex is set to (1, 0). We simply pass these three texture coordinates to the vertex shader, which then passes them to the fragment shader, which interpolates texture coordinates for each fragment.

Texture coordinates would look like this:

Float texCoords [] = {0.0 f, f, 0.0 1.0 f / / left corner, 0.0 f, / / the bottom right hand corner 0.5 f, f / 1.0 / high};Copy the code

Two, image storage

  • The size of an image is directly related to the image itself

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

  • Change and restore the pixel storage method

The API is as follows:

void glPixelStorei(GLenum pname,GLint param);
void glPixelStoref(GLenum pname,GLfloat param);
Copy the code

Parameters that

Pname: GL_UNPACK_ALIGNMENT Specifies how OpenGL unpacks images from the data cache. Param: Specifies the alignment value of the GL_UNPACK_ALIGNMENT parameter. The alignment value can be 1: byte alignment 2: Specifies the alignment of even byte alignment 4: specifies the alignment value of the GL_UNPACK_ALIGNMENT. Word word permutation 8: The line begins at a double-byte boundary

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.

  • Read directly from the color cache content as a pixel map

The API is as follows:

void glReadPixels(GLint x,GLint y,GLSizei width,GLSizei height, GLenum format, GLenum type,const void * pixels);
Copy the code

Parameters that

X: coordinates of the window in the lower left corner of the rectangle Y: coordinates of the window in the lower left corner of the rectangle Width: width of the rectangle in pixels Height: height of the rectangle in pixels Format: OpenGL Pixel format, see Table 2-1 type: Explain the data pointing to the pixels parameter. Tell OpenGL what data type to use in the cache to store the color component and the data type of pixel data. See Table 2-2. Pixels: Pointers to graphic data

3. Texture related API:

1. Load the texture

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

Related parameters:

  • Target: Texture dimensionGL_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 becauseOpenGLA requirement left over from an older version. 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.
  • Format parameter: data type of pixel data (GL_UNSIGNED_BYTE, each color component is an 8-bit unsigned integer.)
  • The type parameter:
  • Data parameter: pointer to texture image data

2. Update the texture

Updating 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 those 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.

3. 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.

4. Use the color cache to load data and form new textures for use

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

5. Texture objects

1) The glGenTextures function to allocate the texture object first needs to input the number of generated textures and then store them in the unsigned int array of the second argument.

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

2) Bind texture Once the texture is created, we need to bind it so that any subsequent texture instructions can configure the current bound texture.

void glBindTexture (GLenum target, GLuint texture);

Copy the code

Parameters that

  • Target:GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D
  • Texture: The texture object to bind to

3) Delete the bound texture object

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

Copy the code

Parameters that

  • N: Texture object
  • Textures: Texture object pointer (the pointer points to an unsigned integer array filled with texture object identifiers).

The function returns GL_TRUE if the texture is a texture with allocated space, GL_FALSE otherwise.

GLboolean glIsTexture(GLuint texture)

Copy the code

6. 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

Parameters that

  • Target, which specifies which texture mode these parameters will be applied to, for exampleGL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D.
  • Pname, which specifies which texture parameter to set
  • Param or params, used to set the value of a specific texture parameter

7. Texture surround mode

Texture coordinates usually range from **(0, 0) to (1, 1)**, so what happens if we set texture coordinates outside the range? OpenGL’s default behavior is to repeat the texture image (we basically ignore the integer part of the floating-point texture coordinates), but OpenGL offers more options:

Around the way 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 visual output when texture coordinates are outside the default range. Let’s look at some examples of texture images:

Each of the options mentioned above can be set to a separate coordinate axis (s, t (and r if using a 3D texture) using the glTexParameter function:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

Copy the code

The first parameter specifies the texture target; We are using a 2D texture, so the texture target is GL_TEXTURE_2D. The second parameter requires us to specify the setting options and the applied texture axis. What we are going to configure is the WRAP option and specify the S and T axes. The final wrap parameter requires us to pass a wrap. In this case OpenGL assigns GL_MIRRORED_REPEAT to the currently active texture.

If we select the GL_CLAMP_TO_BORDER option, we also need to specify an edge color. This requires using the fV suffix form of the glTexParameter function, with GL_TEXTURE_BORDER_COLOR as its option, and passing a float array as the color value for the edge:

Float borderColor[] = {1.0f, 1.0f, 0.0f, 1.0f}; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);Copy the code

8. Texture filtering

Texture coordinates are resolution-independent and can be any floating point value, so OpenGL needs to know how to map Texture pixels to Texture coordinates. This becomes important when you have a large object with a low resolution texture. As you might have guessed, OpenGL also has an option for Texture Filtering. There are many options for texture filtering, but for now we will discuss only the two most important ones: GL_NEAREST and GL_LINEAR.

GL_NEAREST (also called Nearest Neighbor Filtering) is OpenGL’s default texture Filtering mode. When set to GL_NEAREST, OpenGL will select the pixel whose center point is closest to the texture coordinates. In the image below you can see four pixels with the plus sign representing texture coordinates. 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:

GL_LINEAR(also calledLinear filterIt computes an interpolation based on texture pixels near texture coordinates that approximates the colors between those texture pixels. The closer the center of a texture pixel is to the texture coordinates, the more the color of the texture pixel contributes to the final sample color. In the image below you can see that the returned color is a blend of adjacent pixels:

So what are the visual effects of these two texture filters? Let’s see what happens when you apply a low-resolution texture to a very large object (the texture is magnified so that every texture pixel can see it) :

GL_NEAREST generates a grainy pattern and we can clearly see the pixels that compose the texture, while GL_LINEAR produces a smoother pattern and it is difficult to see individual texture pixels. GL_LINEAR produces more realistic output, but some developers prefer the 8-bit style, so they use the GL_NEAREST option.

You can set texture filtering options when Magnify and Minify, for example you can use neighborhood filtering when the texture is zoomed in and linear filtering when the texture is zoomed in. We need to use the glTexParameter function to specify the filter for zooming in and out. This code will look similar to the texture surround setup:

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

9. Multi-level fade texture (Mipmap)

Imagine that we have a large room with thousands of objects, each with a texture. Some objects will be far away, but their textures will have the same high resolution as nearby objects. Since distant objects may produce only a few fragments, It is difficult for OpenGL to get the correct color value for these fragments from a high-resolution texture, because it needs to pick up only one texture color for a fragment that spans a large portion of the texture. This creates an unreal feeling on small objects, not to mention the memory waste of using high-resolution textures on them.

OpenGLUsing something calledMulti-level fade texture(Mipmap), which is simply a series of texture images, the latter one is one half of the previous one. The idea behind multistage receding textures is simple: the distance from the viewer exceeds a certain threshold,OpenGLDifferent multi-level fade textures are used, the one that best fits the distance of the object. Due to the distance, the resolution is not high and will not be noticed by the user. At the same time, the multi-stage fade texture is another plus that it is very good performance. Let’s take a look at what a multi-level fade texture looks like:

Manually creating a series of multilevel asymptote textures for each texture image is cumbersome. Fortunately, OpenGL has a glGenerateMipmaps function that calls it after creating a texture and OpenGL does all the work. You’ll see how to use it later in the tutorial.

When switching multi-level fade texture levels (levels) in a rendering, OpenGL creates an unreal hard boundary between two different levels of multi-level fade texture layers. Like normal texture filtering, you can also use NEAREST and LINEAR filtering between two different multilevel asymptotic texture levels when switching between them. To specify the filter method between different levels of fade texture, you can use one of the following four options instead of the original filter method:

Filtering way describe
GL_NEAREST Nearest neighbor filtering is performed at the Mip base
GL_LINEAR Perform linear filtering at the Mip base
GL_NEAREST_MIPMAP_NEAREST The nearest multilevel asymptotic texture is used to match pixel size, and adjacent interpolation is used for texture sampling
GL_LINEAR_MIPMAP_NEAREST The nearest multistage asymptotic texture level is used, and linear interpolation is used for sampling
GL_NEAREST_MIPMAP_LINEAR Linear interpolation is performed between two multilevel asymptotic textures that best match pixel size, and adjacent interpolation is used for sampling
GL_LINEAR_MIPMAP_LINEAR Linear interpolation is used between two adjacent multi-level asymptotic textures, and linear interpolation is used for sampling

Just like texture filtering, we can use glTexParameteri to set the filtering to one of the four methods mentioned above:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

Copy the code

A common mistake is to set the zoom filter option to one of the multi-level fade texture filters. This has no effect, because multistage fade textures are mostly used when the texture is scaled down: Texture magnification does not use multistage fade textures, and setting multistage fade textures for magnification filters generates a GL_INVALID_ENUM error code.

10. Compress textures

  • General compressed texture format:
Compressed format Basic internal format
GL_COMPRESSED_RGB GL_RGB
GL_COMPRESSED_RGBA GL_RGBA
GL_COMPRESSED_SRGB GL_RGB
GL_COMPRESSED_SRGB_ALPHA GL_RGBA
GL_COMPRESSED_RED GL_RED
GL_COMPRESSED_RG GL_RG
  • Determine compression and select compression mode
// According to the selected compression texture format, select the fastest, best, self-selecting algorithm to select the compression format. glHint(GL_TEXTURE_COMPRESSION_HINT,GL_FASTEST); glHint(GL_TEXTURE_COMPRESSION_HINT,GL_NICEST); glHint(GL_TEXTURE_COMPRESSION_HINT,GL_DONT_CARE);Copy the code
  • Loading compressed texture
void glCompressedTexImage1D(GLenum target,GLint level,GLenum internalFormat,GLsizei
 width,GLint border,GLsizei imageSize,void *data);
void glCompressedTexImage2D(GLenum target,GLint level,GLenum internalFormat,GLsizei
 width,GLint heigth,GLint border,GLsizei imageSize,void *data);
void glCompressedTexImage3D(GLenum target,GLint level,GLenum internalFormat,GLsizei
 width,GLsizei heigth,GLsizei depth,GLint border,GLsizei imageSize,void *data);
Copy the code

Parameters that

  • target: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.
  • Width, height, depth: indicates the width, height, and depth of the loaded texture. = = attention! These values have to be 2 to the whole power. (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 adding arguments to the power of 2.)
  • Border parameter: allows you to specify a border width for the texture map.
  • The format, type, and data parameters are the same as those used in the glDrawPixels function
  • glGetTexLevelParameterFunction to extract compressed texture format
parameter return
GL_TEXTURE_COMPRESSED Returns 1 if the texture is compressed, 0 otherwise
GL_TEXTURE_COMPRESSED_IMAGE_SIZE The size of the compressed texture, in bytes
GL_TEXTURE_INTERNAL_FORMAT The compression format used
GL_NUM_COMPRESSED_TEXTURE_FORMATS Number of supported compressed texture formats
GL_COMPRESSED_TEXTURE_FORMATS An array of constant values corresponding to one of the supported compressed texture formats
GL_TEXTURE_COMPRESSION_HINT Compress the value of the texture hint (GL/NICEST/GL_FASTEST)
  • GL_EXT_texture_compression_s3tcCompressed format
format describe
GL_COMPRESSED_RGB_S3TC_DXT1 RGB data is compressed and the alpha value is always 1.0
GL_COMPRESSED_RGBA_S3TC_DXT1 RGBA data is compressed and alpha returns 1.0 or 0.0
GL_COMPRESSED_RGAB_S3TC_DXT3 RGB values are compressed and alpha values are stored in 4 bits
GL_COMPRESSED_RGBA_SETC_DXT5 RGB data is compressed and the alpha value is a weighted average of a number of 8-bit values

Remember to like it if you think it’s good! I heard that the people who read the praise will meet the test, meet the prize will be in. ღ(´ · ᴗ · ‘)