Jeff Molofee (Nehe) OpenGL Tutorial The 6th lesson Translated by CKER Learn Texture Map Texture Mapping (texture) has a lot of benefits. For example, you want a missile to fly over the screen. According to the knowledge of the previous lessons, our best ways may be a lot of polygons to build the outline of the missile and add interesting colors. With texture mapping, you can use a real missile image and let it fly over the screen. Which one do you think is better? Is the photo or a large pile of triangles and quadrilates? The benefits of using texture maps are not better to see, and your program will run faster. Missile maps may be just a four-sided shape that flesh over the window. A missile constructed from polygons is likely to include hundreds of polygons. Obviously, the map greatly saves the CPU time. Now we will add five new codes at the beginning of the first lesson. The new first line is #include
Because LoadBMP () can be called without parameter, we have to check it. You don't want to load anything ..... :) if (! Filename) / / Make sure the file name is provided. {RETURN NULL; // If not provided, return null} then check if the file exists. Let's try to open the file below. File = fopen (filename, "r"); // Try Open File If we can open the file, it is obvious that the file exists. Use fclose (file) to close the file. AuxDibImageLoad (filename) reads image data and returns it. IF (file) // file exists? {fclose (file); // Close the handle return auxDibimageLoad (filename); / / Load bitmap and return pointer} If we cannot open the file, we will return NULL. This means that the file cannot be loaded. The program will check if the file is loaded. If not, we will exit the program and pop up the error message. Return null; // If load fails, return null} Next part of the code load bitmap (call the above code) and converted to the texture. INT loadGLTextures () // Load bitmap (call the code above) and convert to texture {then set a variable called STATUS. We use it to track whether you can load bitmaps and whether you can create textures. Status is set to False (indicating that there is no load or creation any stuff). INT status = false; // status status indicator Now we create image records for storage bitmaps. The subsistence containing the width, height, and data of the bitmap. AUX_RGBIMAGEREC * textureImage [1]; // Creating a textured storage space clearing image record, make sure its content is empty. Memset (TextureImage, 0, SIZEOF (VOID *) * 1); // Set the pointer to NULL now load bitmap and convert it to texture. TextureImage [0] = LoadBMP ("Data / Nehe.bmp") calls LoadBMP () code. Loading the Nehe.BMP bitmap file under the Data directory. If everything is normal, the image data will be stored in TextureImage [0], and Status is set to True, and then we started to create textures. // Load bitmap, check if there is any error, if the bitmap is not found, exit. IF (TextureImage ["" DATA / Nehe.bmp ")) {status = true; // Setting Status True Now uses data for TextureImage [0] to create textures. The first line of Glgentextures (1, & texture [0]) tells OpenGL We want to generate a texture name (if you want to load multiple textures, increase the number). It is worth noting that we started using Gluint Texture [1] to create a textured storage, you might think that the first texture is stored in & texture [1], but this is wrong. The correct address should be & texture [0]. Also, if you use Gluint Texture [2], the second texture is stored in Texture [1]. "Translator Note: Learning C, there should be no obstacles here, the array is from zero. "The second line of glbindtexture (GL_Texture_2D, Texture [0]) tells OpenGL to bind the texture name Texture [0] to the texture target. 2D texture is only height (on the Y-axis) and width (on the x-axis). The main function assigns the texture name to the texture data. In this example, we inform OpenGL, the memory at & texture [0] is available.
The texture we created will store the point to the pointer of & texture [0]. GlGentextures (1, & texture [0]); // Create texture // Use typical texture generated from bitmap data GlbindTexture (GL_Texture_2D, Texture [0]); let's create a real texture. The following line tells OpenGL this texture is a 2D texture (GL_Texture_2D). Digital zero represents the level of detail, usually it is zero. Number three is the number of components of the data. Because the image consists of three components of red data, green data, blue data. TextureImage [0] -> SIZEX is the width of the texture. If you know the width, you can fill it here, but your computer can easily point out this value. TextureImage [0] -> Sizey is the height of the texture. Number zero is the value of the border, generally zero. GL_RGB tells OpenGL image data consisting of red, green, blue three-color data. Gl_unsigned_byte means that the data that makes up the image is an unsigned byte type. Finally ... TextureImage [0] -> DATA tells OpenGL texture data. This example points to data stored in the TextureImage [0] record. // Generate Texture Glteximage2D (GL_Texture_2D, 0, 3, TextureImage [0] -> Sizex, TextureImage [0] -> Sizey, 0, GL_RGB, GL_UNSIGNED_BYTE, TEXTUREIMAGE [0] -> DATA); The following two lines tell OpenGL When the image is displayed, when it is larger than the original texture large (GL_TEXTURE_MAG_FILTER, it is smaller than the original texture is small (GL_TEXTURE_MIN_FILTER), OpenGL is used. Usually in both cases I use GL_LINEAR. This makes the texture from far away from the screen very close to the screen. Use GL_LINEAR to need CPUs and graphics cards to do more operations. If your machine is slow, you may use GL_NEAREST. When the filtered texture is amplified, it looks high "Translator Note: Mosaic". You can also combine these two ways. Use GL_LINEAR when you are close to GL_NEAREST. Gltexparameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Line-shaped filter gltexparameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Line-shaped filter} Now we release the memory of the presence map data. We first check if the bitmap data is stored. If so, check whether the data has been stored. If you have already stored, delete it. Then then release the TextureImage [0] image structure to ensure that all memory can be released. IF (TextureImage [0]) // Whether the texture exists {if (TextureImage [0] -> DATA) // Whether the image is present {free (TextureImage [0] -> DATA); // Release the texture image occupied memory} Free (TextureImage [0]); // Release the image structure} Last returns state variable. If everything is OK, the value of the variable status is True. Otherwise, False. Return status; // Return Status} I only add a few lines of code in INITGL. But in order to facilitate you to see which lines have increased, I have a total of this code. If (! loadGltextures ()) This line code calls the sub-enrollment bitmap and generates texture. If the loadGlTextures () call failed because of any reason, the next line returns false.
If everything is OK, and the texture is created, we enable 2D texture mapping. If you have forgotten it, your object looks always pure white, this is not a good thing. INT INITGL (GLVOID) / / Start all settings {if (! loadGltextures () // call texture load subroutines (new) {return false; // If you fail, return false (New)} glenable (GL_TEXTURE_2D); // Enable texture mapping (new) Glshademodel (GL_SMOOTH); // Enable shadow smooth GlclearColor (0.0F, 0.0F, 0.0F, 0.5F); // Black background Glcleardepth ( 1.0F); // Set depth cache Glenable (GL_Depth_test); // Enable depth test GLDEPTHFUNC (GL_L_LEQUAL); // The type GLHINT (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Real fine perspective correction Return True; // Initialization OK} Now we draw textures "Translator Note: In fact, the map is texture mapping. In exchange for terms, I would like less. ^ _ ^ "Has passed cubes. This code was released by arsenic, it should be very well understood. Starting two lines of code Glclear () and gLloadIdentity () are code in the first lesson. GLCLEAR (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) Clears the screen and set it to our selected color in Initgl (), this example is black. The depth cache is also cleared. The model observation matrix also uses GLLoadIdentity () reset. INT Drawglscene (GLVOID) // Start all the drawing {GLCLEAR (GL_COLOR_BIFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the screen and depth cache GLLoadIdentity (); // Reset the current model observation matrix GLTranslateF (0.0F, 0.0F, -5.0F); // Move into the screen 5 units to rotate the cube around X, Y, Z axis. How much rotation depends on the value of the variables XROT, YROT, and ZROT. Glrotatef (XROT, 1.0F, 0.0F, 0.0F); // rotates GLROTATEF (YROT, 0.0F, 1.0F, 0.0F) around the X-axis; // Rotate Glrotatef around the Y-axis (Zrot, 0.0F, 0.0F, 1.0f); // Rotate the next line of code from the Z-axis to select the texture we use. If you use multiple textures in your scenario, you should use to GlbindTexture (GL_Texture_2D, Texture [Number of textures used]) Select the texture you want to bind. When you want to change the texture, you should bind a new texture. One thing is worth pointing out that you can't bind texture between glbegin () and glend (), you must bind before glbegin () () before (). Note that we are behind how to use GlbindTexture to specify and bind textures. GlbindTexture (GL_Texture_2D, Texture [0]); // Select Texture In order to map the texture to the quadrilateral, you must map the top right corner of the texture to the upper right corner of the quadrilate, the upper left corner of the texture map to the upper left corner of the quadrilateral, texture The lower right corner is mapped to the lower right corner of the quadrilateral, the left lower corner of the texture maps to the lower left corner of the quadrilateral. If the mapping is wrong, the image is displayed upside down, and the side or nothing is not. The first parameter of GLTEXCOORD2F is X coordinate. 0.0f is the left side of the texture. 0.5f is the midpoint of the texture, 1.0F is the right side of the texture. The second parameter of GLTEXCOORD2F is Y coordinate. 0.0f is the bottom of the texture.
0.5f is the midpoint of the texture, and 1.0F is the top of the texture. So the left upper left coordinates of the texture are x: 0.0f, y: 1.0F, the top left vertices of the quadrilateral are x: -1.0f, y: 1.0f. The remaining three points are pushed. Try to play the X, Y coordinate parameters of Gltexcoord2f. Change 1.0f to 0.5f will display only the left half of the texture, change 0.0F to 0.5F will display only the right half of the texture.
Glbegin (GL_QUADS); // Front GLTEXCOORD2F (0.0F, 0.0F); GLVERTEX3F (-1.0F, -1.0F, 1.0F); // Texture and quadrilateral top left gltexcoord2f (1.0F, 0.0F); GlvertEX3F (1.0 f, -1.0f, 1.0f); // Texture and quadrilateral upper right gltexcoord2f (1.0F, 1.0F); GlvertEX3F (1.0F, 1.0F, 1.0F); // Texture and quadrilateral upper right gltexcoord2f (0.0F , 1.0F); GlvertEX3F (-1.0F, 1.0F, 1.0F); // Texture and quadrilateral left // back GLTEXCOORD2F (1.0F, 0.0F); GlvertEX3F (-1.0F, -1.0F, -1.0F ); // Texture and quadrilateral upper right gltexcoord2f (1.0F, 1.0F); GlvertEX3F (-1.0F, 1.0F, -1.0F); // Texture and quadrilateral upper right gltexcorad2f (0.0F, 1.0F); GlvertEx3f (1.0F, 1.0F, -1.0F); // Texture and quadrilateral upper left gltexcoord2f (0.0F, 0.0F); GlvertEX3F (1.0F, -1.0F, -1.0F); // Texture and quadrilateral left / / Top GltexcoRD2F (0.0F, 1.0F); GlvertEX3F (-1.0F, 1.0F, -1.0F); // Texture and quadrilateral left GLTEXCOORD2F (0.0F, 0.0F); GLVERTEX3F (-1.0F, 1.0F , 1.0F); // Texture and quadrilateral upper left gltexcoord2f (1.0F, 0.0F); GlvertEX3F (1.0F, 1.0F, 1.0F); // Texture and quadrilateral upper right gltexcoord2f (1.0F, 1.0F); GlvertEX3F (1.0F, 1.0F, -1.0F); // Texture and quadrilateral right // bottom GLTEXCOORD2F (1.0F, 1.0F); GlvertEX3F (-1.0F, -1.0F, -1.0F); // Texture And quadrilateral upper right gltexcoord2f (0.0F, 1.0F); Glvertex 3F (1.0F, -1.0F, -1.0F); // Texture and quadrilateral left GLTEXCOORD2F (0.0F, 0.0F); GLVERTEX3F (1.0F, -1.0F, 1.0F); // Texture and quadrilateral left GLTEXCOORD2F (1.0F, 0.0F); GlvertEX3F (-1.0F, -1.0F, 1.0F); // Texture and quadrilateral right // right side gltexcoord2f (1.0F, 0.0F); GlvertEX3F (1.0F, -1.0 f, -1.0f); // Texture and quadrilateral upper right gltexcoord2f (1.0F, 1.0F); GlvertEX3F (1.0F, 1.0F, -1.0F); // Texture and quadrilateral upper right gltexcoord2f (0.0F, 1.0 f); GlvertEX3F (1.0F, 1.0F, 1.0F); // Texture and quadrangular upper left gltexcorad2f (0.0F, 0.0F); GlvertEX3F (1.0F, -1.0F, 1.0F); // Texture and quadrilateral The lower left // left GLTEXCOORD2F (0.0F, 0.0F); GlvertEX3F (-1.0F, -1.0F, -1.0F); // Texture and quadrilateral upper left gltexcoord2f (1.0F, 0.0F); GlvertEX3F (-1.0F, -1.0F, 1.0F); // Texture and quadrilateral upper right gltexcoord2f (1.0F, 1.0F); GlvertEX3F (-1.0F, 1.0F, 1.0F); // Texture and quadrilateral upper right gltexcoord2f (0.0F, 1.0F); GlvertEX3F (-1.0F, 1.0F, -1.0F);
// Texture and quadrilateral glend (); now add the value of XROT, YROT, and ZROT. Try the change value of each variable to regulate the rotation speed of the cube, or change the /- to adjust the direction of rotation of the cube. XROT = 0.3F; // X axis rotation YROT = 0.2F; // Y axis rotation Zrot = 0.4F; // Z axis rotation return true; // Continue operation} Now you should understand texture map (texture) . You should have the technology to post your image you love to any quadrilateral surface. Once you feel confidently on the 2D texture map, try the six faces of the cube to attach different textures. When you understand the concept of texture coordinates, the texture mapping is not difficult to understand. ! If you have any comments or suggestions, please give me email. If you think there is something wrong or improve, please tell me. "Translator: NEHE's document seems very simple, it seems very rushed. But if you want to come to such a master, have you seen a few? Or that sentence, I am not a master, I hope you are sincere. Here is the source code download link.