Lesson 1
Expansion, cropping, and loading of TGA image files:
In this lesson, you will learn how to read OpenGL extensions supported by your graphics card and display them in your specified cropping area.
This tutorial is difficult, but it will help you learn a lot. I heard a lot of friends ask me about extensions and how to find them. This tutorial will be handed over to you
Everything.
I will teach you how to scroll part of the screen and how to draw straight lines. The most important thing is that from this lesson we will not use the aux library, as well as the *. BMP file. I will show you how to use the Targa (TGA) image file. Because it is simple and supports Alpha channels, it makes it easier for you to create cool effects.
The first thing we need to do next is not to include the Glaux. h header file and the Glaux. Lib library. In addition, some suspicious warnings often occur when using the Glaux library. Now we can determine to say goodbye to it.
# Include <stdarg. h> // header file for processing variable parameter functions
# Include <string. h> // process string header files
Next we will add some variables. The first one is the rolling parameter. The second is the number of extended variable records. The swidth and sheight records cut the size of the rectangle. Base is the start value of the font display list.
Int scroll; // used to scroll the screen
Int maxtokens; // Save the number of extensions
Int swidth; // cropping width
Int sheight; // crop height
Gluint base; // start value of the character display list
Now we create a data structure to save the TGA file, and then we use this structure to load the texture.
Typedef struct // create a file structure for loading TGA images
{
Glubyte * imagedata; // Image Data Pointer
Gluint BPP; // The number of BITs occupied by each data (24 or 32 required)
Gluint width; // The image width.
Gluint height; // Image Height
Gluint texid; // texture ID
} Textureimage; // structure name
Textureimage textures [1]; // save a texture
This part of the code will load a TGA file and convert it to a texture. Note that this part of code can only load 24/32-bit, non-compressed TGA files.
This function contains two parameters: one for storing the loaded image and the other for the file name to be loaded.
The TGA file contains a 12-byte file header. After loading the image, we use type to set the corresponding pixel format in the image in OpenGL. For 24-bit images, we use gl_rgb. For 32-bit images, we use gl_rgba.
Bool loadtga (textureimage * texture, char * filename) // load the TGA file to the memory.
{
Glubyte tgaheader [12] = {0, 0, 0, 0, 0, 0}; // non-compressed TGA file header
Glubyte tgacompare [12]; // Save the header information
Glubyte header [6]; // save the most useful image information, width, height, and depth
Gluint bytesperpixel; // records the number of bytes occupied by each color.
Gluint imagesize; // record the file size
Gluint temp; // Temporary Variable
Gluint type = gl_rgba; // set the default format to gl_rgba, which is a 32-bit image.
The following function reads the TGA file and records the file information. The format of the TGA file is as follows:
TGA image format
Colorless table RGB image
Offset length description the values of each byte in 32-bit common image files
0 1 indicates the length of the image information field. Its value ranges from 0 to 255. When it is 0, it indicates that there is no image information field. 0
1. Whether to use a color table. 0 indicates no color table. 1 indicates that the color table has 0.
2 1 this field is always 2. Image type code, TGA has a total of 6 formats, 2 indicates that there is no color table RGB image 2
3 5 color table specifications, total 0. 0
4 0
5 0
6 0
7 0
8 10 image specifications
8 2 start position of the image X coordinate, usually 0 0
9
10 2 start position of the Y coordinate of the image, usually 0 0
11
256 image width, in pixels
13
14 2. Image Height, in pixels: 256
15
16 1 image storage space per pixel (BIT) 32
17 1 Image Descriptor bytes
Bits 3-0-the number of BITs corresponding to each pixel. For TGA 24, this value is 0.
Bit 4-reserved, must be 0
Bit 5-indicates the start position of the screen. 0 = the origin is in the lower left corner, and 1 = the origin is in the upper left corner.
Generally, set this byte to 0x00.
00100000 (2)
18 variable image data domains
Here (width) x (height) pixels are stored. The RGB color value in each pixel contains an integer Byte...
If everything goes well, close the file after reading the file.
File * file = fopen (filename, "rb"); // open a TGA file
If (file = NULL | // does the file exist?
Fread (tgacompare, 1, sizeof (tgacompare), file )! = Sizeof (tgacompare) | // does it contain 12-byte file headers?
Memcmp (tgaheader, tgacompare, sizeof (tgaheader ))! = 0 | // is the required format?
Fread (header, 1, sizeof (header), file )! = Sizeof (header) // if it is to read the following six Image Information
{
If (file = NULL) // if the file does not exist, an error is returned.
Return false;
Else
{
Fclose (File); // an error is returned when the file is closed.
Return false;
}
}
The following code records the width and height of the file and determines whether the file is a 24-bit/32-bit TGA file.
Texture-> width = header [1] * 256 + header [0]; // record file height
Texture-> Height = header [3] * 256 + header [2]; // record file width
If (texture-> width <= 0 | // whether the width is smaller than 0
Texture-> height <= 0 | // whether the height is smaller than 0
(Header [4]! = 24 & header [4]! = 32) // What is the 24/32-bit TGA file?
{
Fclose (File); // if the file fails to be closed, an error is returned.
Return false;
}
The following code records the depth of the file and the memory size required to load it
Texture-> bpp = header [4]; // record the depth of the file
Bytesperpixel = texture-> BPP/8; // records the bytes occupied by each pixel
Imagesize = texture-> width * texture-> height * bytesperpixel; // calculate the memory size required for loading the TGA file
The following code allocates memory for image data and loads it
Texture-> imagedata = (glubyte *) malloc (imagesize); // allocate memory to save TGA data
If (texture-> imagedata = NULL | // does the system allocate enough memory?
Fread (texture-> imagedata, 1, imagesize, file )! = Imagesize) // is the memory read successfully?
{
If (texture-> imagedata! = NULL) // whether data is loaded
Free (texture-> imagedata); // If yes, the loaded data will be released
Fclose (File); // close the file
Return false; // an error is returned.
}
In the TGA file, the color storage order is BGR, while in OpenGL the color order is RGB, so we need to swap the R and B values in each pixel. If everything goes well, the image data in the TGA file will be stored in the memory as required by OpenGL.
For (gluint I = 0; I <int (imagesize); I + = bytesperpixel) // loop all pixels
{// Exchange R and B values
Temp = texture-> imagedata [I];
Texture-> imagedata [I] = texture-> imagedata [I + 2];
Texture-> imagedata [I + 2] = temp;
}
Fclose (File); // close the file
The following code creates a texture and sets the filtering method to linear.
// Create a texture
Glgentextures (1, & texture [0]. texid); // creates a texture and records the texture ID.
Glbindtexture (gl_texture_2d, texture [0]. texid); // bind the texture
Gltexparameterf (gl_texture_2d, gl_texture_min_filter, gl_linear); // set the filter to linear filter.
Gltexparameterf (gl_texture_2d, gl_texture_mag_filter, gl_linear );
Determines whether the number of digits of the image is 24. If yes, set the type to gl_rgb.
If (texture [0]. bpp = 24) // is the 24-bit image?
{
Type = gl_rgb; // if it is set to gl_rgb
}
The following code creates a texture in OpenGL
Glteximage2d (gl_texture_2d, 0, type, texture [0]. Width, texture [0]. Height, 0, type, gl_unsigned_byte, texture [0]. imagedata );
Return true; // After texture binding is completed, a success is returned.
}
The following code is a typical method for creating fonts from images. The Code will be included in subsequent courses to display text.
There is only one difference. Texture 0 is used to save Character Images.
Glvoid buildfont (glvoid) // create a font display list
{
Base = glgenlists (256); // create 256 display lists
Glbindtexture (gl_texture_2d, textures [0]. texid); // bind the texture
For (INT loop1 = 0; loop1 <256; loop1 ++) // create 256 display lists in a loop
{
Float Cx = float (loop1% 16)/16.0f; // The X position of the current character
Float Cy = float (loop1/16)/16.0f; // y position of the current character
Glnewlist (base + loop1, gl_compile); // start to create a display list
Glbegin (gl_quads); // creates a quadrilateral to contain Character Images
Gltexcoord2f (CX, 1.0f-cy-0.0625f); // texture coordinate at the bottom left
Glvertex2d (); // coordinates at the bottom left
Gltexcoord2f (cx + 0.0625f, 1.0f-cy-0.0625f); // right bottom texture coordinate
Glvertex2i (); // coordinates at the bottom right of the page
Gltexcoord2f (cx + 0.0625f, 1.0f-cy-0.001f); // texture coordinate in the upper right corner
Glvertex2i (16, 0); // coordinates in the upper right corner
Gltexcoord2f (CX, 1.0f-cy-0.001f); // texture coordinate in the upper left corner
Glvertex2i (); // coordinates in the upper left corner
Glend (); // The quadrilateral is created.
Gltranslated (, 0); // move 14 units to the right
Glendlist (); // display list of end Creation
}
}
The following function is used to delete the display list of display characters.
Glvoid killfont (glvoid)
{
Gldeletelists (base, 256); // Delete 256 display lists from memory
}
The glprint function has only one change. We double the length of Characters in the Y axis.
Glvoid glprint (glint X, glint y, int set, const char * FMT ,...)
{
Char text [1024]; // save our characters
Va_list AP; // point to the first parameter
If (FMt = NULL) // if the character to be displayed is null, return
Return;
Va_start (AP, FMT); // start the analysis parameters and write the results to text.
Vsprintf (text, FMT, AP );
Va_end (AP );
If (set> 1) // if the character set is greater than 1, the second character set is used.
{
Set = 1;
}
Glable (gl_texture_2d); // use texture ing
Glloadidentity (); // resets the view matrix.
Gltranslated (X, Y, 0); // pan to (x, y, 0)
Gllistbase (base-32 + (128 * Set); // select the character set
Glscalef (1.0f, 2.0f, 1.0f); // double the value along the Y axis.
Glcalllists (strlen (text), gl_unsigned_byte, text); // write characters to the screen
Gldisable (gl_texture_2d); // disable texture ing
}
Use a forward projection to change the window size. Set the window range to (0, 0)-(640,480)
Glvoid resizeglscene (glsizei width, glsizei height)
{
Swidth = width; // set the cut rectangle to the window size.
Sheight = height;
If (Height = 0) // prevent division by 0 when the height is 0
{
Height = 1;
}
Glviewport (, width, height); // you can specify the visible area of the window.
Glmatrixmode (gl_projection );
Glloadidentity ();
Glortho (0.0f, 640,480, 0.0f,-1.0f, 1.0f); // you can specify a 640x480
Glmatrixmode (gl_modelview );
Glloadidentity ();
}
Initialization is very simple. We load the font texture and create a character display list. If it succeeds, the system returns the result.
Int initgl (glvoid)
{
If (! Loadtga (& textures [0], "Data/font. TGA") // load the font texture
{
Return false; // If loading fails, return
}
Buildfont (); // create a font
Glshademodel (gl_smooth); // Use smooth coloring
Glclearcolor (0.0f, 0.0f, 0.0f, 0.5f); // sets the black background.
Glcleardepth (1.0f); // set the value in the deep cache to 1.
Glbindtexture (gl_texture_2d, textures [0]. texid); // bind the font texture
Return true; // success
}
The drawing code is almost brand new :). Token is a pointer to a string, which saves all OpenGL extended strings and records the extended number of CNT records.
Next we will clarify the background and display the vendors of OpenGL to implement its company and current version.
Int drawglscene (glvoid)
{
Char * token; // Save the extended string
Int CNT = 0; // record the number of extended strings
Glclear (gl_color_buffer_bit | gl_depth_buffer_bit); // clear the background and depth Cache
Glcolor3f (1.0f, 0.5f, 0.5f); // set it to red.
Glprint (50, 16, 1, "Renderer ");
Glprint (80, 48, 1, "vendor ");
Glprint (66,80, 1, "version ");
The following code displays information about OpenGL implementation. After completion, we use blue to write "nehe productions" at the bottom of the screen. Of course, you can use any character you want, for example, "dancingwind translate ".
Glcolor3f (1.0f, 0.7f, 0.4f); // set it to orange
Glprint (, 1, (char *) glgetstring (gl_renderer); // display the implementation organization of OpenGL
Glprint (, 48, 1, (char *) glgetstring (gl_vendor); // display the seller
Glprint (, 80, 1, (char *) glgetstring (gl_version); // display the current version
Glcolor3f (0.5f, 0.5f, 1.0f); // set it to blue.
Glprint (192,432, 1, "nehe productions"); // write the nehe productions string at the bottom of the screen
Now we draw a white box with a display extension and enclose all the content with a larger white box.
Glloadidentity (); // reset the model transformation matrix
Glcolor3f (1.0f, 1.0f, 1.0f); // set it to white.
Glbegin (gl_line_strip );
Glvertex2d (639,417 );
Glvertex2d (0,417 );
Glvertex2d (0,480 );
Glvertex2d (639,480 );
Glvertex2d (639,128 );
Glend ();
Glbegin (gl_line_strip );
Glvertex2d (0,128 );
Glvertex2d (639,128 );
Glvertex2d (639, 1 );
Glvertex2d (0, 1 );
Glvertex2d (0,417 );
Glend ();
The glscissor function is used to set the cropping area. If gl_scissor_test is enabled, the drawn content can only be displayed in the cropping area.
The following code sets the middle of the window as the cropping area and obtains the extension string.
Glscissor (1, INT (0.135416f * sheight), swidth-2, INT (0.597916f * sheight); // defines the Cropping Area
Glable (gl_scissor_test); // use the cropping test.
Char * text = (char *) malloc (strlen (char *) glgetstring (gl_extensions) + 1); // allocate memory space for saving OpenGL extended strings
Strcpy (text, (char *) glgetstring (gl_extensions); // returns the OpenGL extension string
Next we create a loop to show each extension and record the number of extensions.
Token = strtok (text, ""); // split the text string by space and save the string to the token.
While (Token! = NULL) // If token is not null
{
CNT ++; // Add counter
If (CNT> maxtokens) // record the maximum number of extensions
{
Maxtokens = CNT;
}
Now we have obtained the first extension. Next we will display it on the screen.
We have displayed three lines of text, which occupy 3*32 = 96 pixels of width on the Y axis, so the position of the first line of text displayed is ), similarly, the position of line I text is (+ (CNT * 32), but we need to consider the current scrolling position. The default value is to scroll up, therefore, the position of the text displayed in line I is (0, 96 + (CNT * 32) = scroll ).
Of course, they will not all be displayed. Remember that we used the cropping function to display only the text between ()-(+ 32*9), and all others were cropped.
The first line shown in the above explanation is as follows:
1 gl_arb_multitexture
Glcolor3f (0.5f, 1.0f, 0.5f); // set the color to green.
Glprint (+ (CNT * 32)-scroll, 0, "% I", CNT); // plot the extensions
Glcolor3f (1.0f, 1.0f, 0.5f); // set the color to yellow.
Glprint (50, 96 + (CNT * 32)-scroll, 0, token); // output the I-th Extension
When all the extensions are displayed, check whether all strings have been analyzed. We use the strtok (null, "") function to replace the strtok (text, "") function, setting the first parameter to null will check whether the current pointer position contains the "" character at the end of the string. if it contains the character, return its position; otherwise, return null.
The preceding process is illustrated as an example. For example, the string "gl_arb_multitexture gl_ext_abgr gl_ext_bgra" is used to split the string by spaces. The first time strtok ("text", "") is called, add a null value to the space. After each call, delete null, return the next location of the space, search for the location of the next space, and add a null to the location of the space. The return value is null.
If the return value is null, the loop is stopped, indicating that all extensions have been displayed.
Token = strtok (null, ""); // find the next extension
}
The following code returns OpenGL to the default rendering state and releases the allocated memory resources.
Gldisable (gl_scissor_test); // disable the cropping test.
Free (text); // release the allocated memory
The following code enables OpenGL to complete all tasks and returns true
Glflush (); // execute all rendering commands
Return true; // success
}
The killglwindow function remains unchanged. The only change is to delete the font we created.
Killfont (); // Delete the font
Createglwindow (), and wndproc () functions remain unchanged
In the winmain () function, we need to add a new key control.
The following code checks whether the up arrow is pressed. If scroll is greater than 0, we will reduce it by 2.
If (Keys [vk_up] & (scroll> 0) // is the up arrow pressed?
{
Scroll-= 2; // If yes, reduce the value of scroll.
}
If the downward arrow is held down and scroll is smaller than 32 * (maxtoken-9), the scroll value is increased, 32 is the height of each character, and 9 is the number of rows that can be displayed.
If (Keys [vk_down] & (scroll <32 * (maxtokens-9) // whether the downward arrow is held down
{
Scroll + = 2; // If yes, increase the value of scroll.
}
I hope you will find this tutorial interesting. After learning this tutorial, you should know how to get the name of your video card dealer, implement OpenGL organization and the OpenGL version used by your graphics card. Further, you should know the extensions supported by your video card, and skillfully use cut Rectangles and load TGA images.