Texture Mapping in OpenGL

1.0 Introduction

Texture mapping is a process of stretching a texture onto a 3D object; the applied texture will follow the 3D object as it transforms. Texture mapping is fun and beneficial but it can be challenging for beginners. Texture can also be distorted for a visual effect. This blog introduces beginners with basic concepts of texture mapping. Hopefully, users can have a better understanding of the purpose of each step in the texture mapping process. 

2.0 Bitmap texture

OpenGL supports bitmap texture, which is a 2D array of unsigned char Texture[height][width][4]. Each value of the texture 2D array is called texel. The Bitmap file can be converted from other types of images such as PNG, JPEG, and GIF. Users should save the image as a 24-bit format and put it in the current working directory to load the image into the program. 

Users need to write a function to load the image into the program. There is some open source code to do that; users can download the .h file and include it in the .cpp file [1]. Another way is to write down the function by ourselves. I personally prefer to use the unsigned char *BmpToTexture( char *, int *, int * ) from OSU’s graphic design class [2]. 

2.1 Texture coordinates

Texture coordinates need to be specified for each vertex; otherwise, users can not map the bitmap texture onto the object. Texture coordinates (s, t) are  in range of (0,1) as shown below. (0,0) is at the lower left corner while (1,1) is at the upper right corner. Texture coordinates are looked up to decide the color for the a pixel as the pixel is drawn on screen. The function glTexCoord2f(s,t) is used to assign a texture coordinate for each vertex. Texture coordinates can be distorted using transformation techniques such as translation, rotation, and scaling.

Before drawing an object, users need to enable GL_TEXTURE_2D using glEnable(GL_TEXTURE_2D). After finishing the drawing, users can disable it using glDisable(GL_TEXTURE_2D).

Figure 1: Texture coordinate.
Source: http://barbic.usc.edu/cs420-s18/12-textures/12-textures.pdf [3]

2.2 Texture wrapping

When texture coordinates are out of the normal range [0,1], users need to specify their desired effects for the final texture mapping using the function  glTexParameteri(). If users want to repeat the texture, they can use the built-in GL_REPEAT feature. If users want to create a clamped texture, they can use the GL_CLAMP_TO_EDGE feature. Thoroughly studying the figure 2, learners can better understand how texture wrapping works [4]. 

Figure 2: Setting texture wrapping using glTexParameri() function
Source: http://web.cse.ohio-state.edu/~wang.3602/courses/cse5542-2013-spring/15-texture.pdf [4]

2.3 Texture filling

This step decides which textel’s color is as the texture is scaled up or down. With GL_NEAREST, the exact point sample of texture is used to make the decision. With GL_LINEAR, four nearby texels are linearly interpolated to decide the final result for the texel’s color. 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Figure 3: The GL_NEAREST yields different results than GL_LINEAR as shown in figure Source: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/#loading-bmp-images-yourself [5]

2.4 Texture environment

Once texel color is defined, users can choose ways to combine texel color and object color using the function glTexEnvf() as below: 

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) or

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) 

GL_REPLACE uses texture’s color to replace the object’s color; GL_MODULATE allows the object color to shine through the texture. GL_MODULATE is often used when objects are designed with both texture and lighting.

2.5 A choice to use either Texture object or display list

2.5.1 Display list

For static objects (objects that are not animated), (s,t) coordinates can be stored in the display list along with other parameters such as vertex coordinates and normal vectors. An example of using display list is shown below [6]

Figure 4: Using display list to store texture image.
Source: https://www.glprogramming.com/red/chapter07.html [6]

2.5.2 Texture object

Another way to store texture data is to use a texture object; texture will be stored on the graphic card and ready to be reused without the need to download the image from CPU to GPU again. Texture objects are useful when many texture images are intended to be used. Texture object is created using the glGenTextures() function. 

For example, the following code creates three texture images: Assume that the texture files are already loaded to the program. 

GLuint Texture_0, Texture_1;             // setting those as global variable

glGenTextures( 1, &Texture_0 ); 

glGenTextures( 1, &Tex_texture_1 );

To make Texture_0 the current texture, users can use the function glBindTexture(). One should keep in mind that  after the texture is bound, all subsequent operations will use that current texture until it is unbounded or deleted. 

glBindTexture( GL_TEXTURE_2D, Texture_0 );

Then, users can use glTexParameteri() function to set some features for the Texture_0. Next, the glTexImage2D() function is used to download texture from the CPU to the GPU each time the function is called. After the function is called, this texture becomes the current texture image. 

glTexImage2D( GL_TEXTURE_2D, level, ncomps, width_0, height_0, border_0, GL_RGB, GL_UNSIGNED_BYTE, Texture_0 );

Similarly, users can bind texture and set features for Texture_1 and glTexImage2D() to download texture from CPU to GPU. 

 2.6 Display texture image

To display texture images such asTexture_0, first of all, users need to enable GL_TEXTURE_2D. Then, users make Texture_0 current texture using glBindTexture(). Next, glTexEnvf() can be used to set the texture’s environment. Finally, users call a function to draw the object. After texture mapping is done, it can be disabled using the function glDisable(GL_TEXTURE_2D).

3.0 Conclusion 

Texture mapping could be challenging for beginners; it involves many essential steps. Texture adds values and meanings to the object.In order to map texture to a 3-D object using OpenGL, one needs to use a bitmap texture and properly load it into the program. Also, every vertex of the object needs to specify the texture coordinate. Texture coordinates can also be distorted, creating various visual effects.

Reference

[1] LearnOpenGL. Textures. [Online]. Available: https://learnopengl.com/Getting-started/Textures. Accessed Oct 10th, 2021.

[2] Mike Bailey. Texture Mapping. Oregon State University. [Online]. Available: http://web.engr.oregonstate.edu/~mjb/cs553/bmptotexture.cpp. Accessed Oct 10th, 2021.

[3] Jernej Barbic. Lecture 12 Texture Mapping. University of Southern California. [Online]. Available: http://barbic.usc.edu/cs420-s18/12-textures/12-textures.pdf. Accessed Oct 10th, 2021.

[4] Ohio State University. Texture Mapping. Ohio State University. [Online]. Available: http://web.cse.ohio-state.edu/~wang.3602/courses/cse5542-2013-spring/15-texture.pdf. Accessed Oct 10th, 2021.

[5] opengl_tutotial. Tutorial 5: A Textured Cube. [Online]. Available: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/#loading-bmp-images-yourself. Accessed Oct 10th, 2021.

[6] OpenGL Programming Guide. Display Lists. [Online]. Available: https://www.glprogramming.com/red/chapter07.html. Accessed Oct 10th, 2021.

Print Friendly, PDF & Email

Leave a comment

Your email address will not be published.