Nehe OpenGL tutorial (13)

Source: Internet
Author: User
Tags cos

Lesson 1

Image Font:

In this lesson, we will create some fonts Based on 2D images that can be scaled but cannot be rotated and always oriented to the front, but as a basic display, I think it is enough.

Welcome to another tutorial. This time I will teach you how to use bitmap fonts. Maybe you will say to yourself, "What is the difficulty of displaying text on the screen ?". But once you try it, you will know that it is really not that easy.

Of course, you can load an art program, write the text on an image, load the image into your OpenGL program, open the mixed options, and display the text on the screen. However, this approach is time-consuming. Based on the filter type you choose, the final result is often blurred or contains many mosaics. In addition, unless your image contains an alpha channel, the text that is drawn on the screen will be opaque (mixed with other objects in the screen ).

If you have used notepad, Microsoft Word, or other word processing software, you will notice that all different fonts are available. This lesson will teach you how to use the same font as the original in your OpenGL program. In fact, any font installed on your computer can be used in the demo (Chinese cannot work ).

The bitmap font looks more than 100 times better than the graphic font (texture. You can change the text displayed on the screen at any time without having to make textures for them one by one. You only need to locate the text, and then use my latest GL command to display the text on the screen.

I try to make the command as simple as possible. You only need to input glprint ("hello "). It is so simple. In any case, we can see from this long introduction how satisfied I am with this course. It took me about one and a half hours to write this code. Why is it so long? This is because there is no available information in the use of Bitmap fonts, unless you are willing to use the code in MFC. To make the code simple, I think it will be better if I rewrite it all to a C language code that is easy to understand.

A small comment. This code is specially written for windows. It uses the WGL function of windows to create fonts. Obviously, the Apple system has AGL, the X system has Glx to support the same operation. Unfortunately, I cannot guarantee that the Code is also easy to use. If the code that can display text on the screen and is independent from the platform, please let me know, I will rewrite a tutorial on font.

We started from the typical code of Lesson 1 and added the stdio. h header file for standard input/output operations. In addition, the stdarg. h header file is used to parse text and convert variables into text. Add the math. h header file so that we can use the sin and cos functions to move text on the screen.

# Include <stdarg. h> // header file used to define variable parameters

In addition, we need to add three variables. Base will save the number of the first display list we created. Each character must have its own display list. For example, the character 'a' is 65 in the display list, 'B' is 66, and 'C' is 67. Therefore, the character 'a' should be saved to the base + 65 position in the display list.

Then, two counters (cnt1 and cnt2) are added. They use the unused accumulative speed and use the sin and cos functions to change the position of the text on the screen. Create a method that looks like a semi-random movement on the screen. At the same time, we use these two counters to change the color of the text (which will be further explained later ).

Gluint base; // the starting position of the display list for the font.
Glfloat cnt1; // font mobile COUNTER 1
Glfloat cnt2; // font mobile Counter 2

The following code is used to build a real font, which is also the most difficult part of the code to write. 'Hfont font' tells windows that we will use a Windows Font. Oldfont is used to store fonts.
Next, we created a group of 96 display lists using glgenlists (96) while defining the base.

Glvoid buildfont (glvoid) // create a bitmap font
{
Hfont font; // font handle
Hfont oldfont; // old font handle

Base = glgenlists (96); // create 96 display lists

Next, we will create our own fonts. Starting from the specified font size, you will notice that it is a negative number. We add a negative number to tell windows to find a character-based font. If we use a positive number, we are looking for a font that matches the cell-based height.

Font = createfont (-24, // font height

Then we specify the width of each unit, and you will notice that I define it as 0, so that Windows will use the default value. If you want to, you can change its value, for example, a wider value.

0, // font width

Angle of escapement will rotate the font. It is not a common attribute. Except for the angle 0, 90 and 180,270, because the font itself needs to adapt to its invisible square border, the cropping error is often displayed. In the msdn help, orientation angle is used to specify the angle between the bottom edge of each word and the X axis of the display device. Each unit is a tenth angle. Unfortunately, I have no idea about this.
 
0, // The Rotation Angle of the font angle of escapement
0, // orientation angle of the font bottom line
 
Font weight is an important parameter. You can set a value between 0 and or use a defined value. Fw_dontcare is 0, fw_normal is 400, fw_bold is 700 and fw_black is 900. There are many pre-defined values, but these four values have better results. The larger the value, the thicker the font.

Fw_bold, // font weight

Italic (italic), underline (underline), and strikeout (strikeout) can be true or false. If you set underline to true, the font is underlined. Otherwise, it is very simple.

False, // whether italics are used
False, // whether to use underline
False, // whether to use strikethrough
 
Character Set Identifier (character set identifier) is used to describe the character set (internal code) type you want to use. There are too many types to be explained. Chinesebig5_charset, greek_charset, russian_charset, default_charset, and so on. I use ANSI, although default is also very useful.
If you are interested in using webdings or wingdings fonts, you must use symbol_charset instead of ansi_charset.

Ansi_charset, // sets the character set
 
Output precision is very important. It tells windows which character sets are used when there are multiple character sets. Out_tt_precis tells windows to select the TrueType type of the font if a name corresponds to multiple fonts. TrueType fonts usually look better, especially when you enlarge them. You can also use out_tt_only_precis, which will always try to use a TrueType type font
 
Out_tt_precis, // output precision

Cropping accuracy is a type of editing that is used when the font falls out of the cropping range. You just need to set it to default.

Clip_default_precis, // cropping Accuracy

Output quality is very important. You can use proof, draft, nonantialiased, default, or antialised.
As we all know, the antialiased font looks good, And the Antialiasing font can achieve the same effect when the font is smooth in Windows, it makes everything look less jagged, that is, it is smoother.

Antialiased_quality, // Output Quality

The following are settings for family and pitch. The pitch attributes include default_pitch, fixed_pitch, and variable_pitch. Family attributes include ff_decorative, delimiter, ff_roman, ff_script, ff_swiss, and ff_dontcare. Try these values and you will know what functions they have. I set them to the default values.

Ff_dontcare | default_pitch, // family and pitch

Finally, it is the exact name of the font we need. Open Microsoft Word or any other text processing software and click the font drop-down menu to find a font you like. Replace 'courier new' with the name of the font you want to use. (Chinese is not good yet. Other methods are required)

"Courier New"); // font name

Now, select the font we just created. Oldfont points to the selected object. Then we create 96 display lists starting from 32nd characters (spaces. If you want to, you can also create all 256 characters, as long as you make sure to use glgenlists to create 256 display lists. Then we select the oldfont object pointer to HDC and delete the font object.

Oldfont = (hfont) SelectObject (HDC, font); // select the font we need
Wglusefontbitmaps (HDC, 32, 96, base); // create 96 display lists, draw characters from the ASCII code of 32-
SelectObject (HDC, oldfont); // select the original font
Deleteobject (font); // Delete the font
}

The following code is very simple. It deletes 96 display lists from the base in the memory. I don't know if windows will do these jobs, but it is better to be safe.

Glvoid killfont (glvoid) // Delete the display list
{
Gldeletelists (base, 96); // Delete 96 display lists
}

Below is my excellent GL text program. You can call this code by calling glprint ("the text to be written. The text is stored in the string * FMT.

Glvoid glprint (const char * FMT,...) // customize the GL output font Function
{

The first line below creates an array of 256 characters, which stores the desired text string. The second row creates a pointer to a variable list. We passed the Variable list while passing the string. If variables are also passed when we pass the text, this Pointer Points to them.

Char text [256]; // Save the text string
Va_list AP; // pointer to a variable list

The following two lines of code check whether there is any content to be displayed. If there is nothing, FMT is equal to null, and there is nothing on the screen.

If (FMt = NULL) // if there is no input, return
Return;

The next three lines of code convert all characters in the text into their character numbers. Finally, the text and conversion symbols are stored in a string called text. I will explain more details about the characters in the future.
 
Va_start (AP, FMT); // analyze variable parameters
Vsprintf (text, FMT, AP); // write the parameter value to the string
Va_end (AP); // end analysis

Then we press gl_list_bit into the attribute stack, which will prevent gllistbase from affecting other display lists in our program.
Gllistbase (base-32) is a command that is hard to explain. For example, to write the letter 'A', the corresponding number is 65. Without the gllistbase (base-32) command, OpenGL does not know where to find the letter. It will find it at the 65th position in the display list. However, if the base value is equal to 1000, the actual storage location of 'A' is 1065. So when we set a starting point through base, OpenGL will know where to find the correct display list. Minus 32 because we have not constructed the first 32 display lists, we can skip them. So we have to subtract 32 from the base value to let OpenGL know this. I hope this makes sense.

Glpushattrib (gl_list_bit); // press the display list attribute into the attribute stack.
Gllistbase (base-32); // sets the basic value of the displayed list.

Now that OpenGL knows where letters are stored, We can display the text on the screen. Glcalllists is an interesting command. It can display the content of Multiple display lists on the screen at the same time.
The following code is used for subsequent work. First, it tells OpenGL that we will display the content in the display list on the screen. The strlen (text) function is used to calculate the length of the text we want to display on the screen. Then OpenGL needs to know the maximum value of the list that we can send to it. We cannot send strings with a length greater than 255. The parameters in this character list are processed as an array of unsigned characters, and their values are between 0 and 255. Finally, we can tell OpenGL the displayed content by passing text (which points to our string.

Maybe you want to know why the characters do not overlap with each other. At that time, because the display list of each character knows that the right side of the character is there, after writing a character, OpenGL automatically moves to the right of the character you just wrote, when you write a word or draw an object, it starts from the last position of GL to the right of the last character.

Finally, we will bring up the stack of the gl_list_bit attribute and restore GL to the State at that time when we set the base using gllistbase (base-32.

Glcalllists (strlen (text), gl_unsigned_byte, text); // call the display list to draw a string
Glpopattrib (); // The property stack is displayed.
}

The only change in the initialization code is buildfont (). It calls the previous code to create a font, And Then OpenGL can use this font.

Buildfont (); // create a font

The following is the drawing code. We start by clearing the screen and deep cache. We call glloadidentity () to reset everything. Then we move the coordinate system to a unit on the screen. Text cannot be displayed if it is not moved. The bitmap font performs better when you use Perspective Projection instead of ortho projection. Since ortho looks bad, I use perspective projection and move the coordinate system ..
You will notice that if you place a more profound Coordinate System in the screen, the font will not shrink as you think, but you can have more options when controlling the text position. If you move the coordinate system to a unit on the screen, you can adjust the text position in the range from-0.5 to + 0.5 on the X axis. If there are 10 units in depth, the moving range is from-5 to + 5. It gives you more options to replace the exact position of the specified text with decimals. Nothing can change the text size, even if you want to change the font size by calling the glscale (x, y, z) function.

Int drawglscene (glvoid) // This process includes all the drawing code
{
Glclear (gl_color_buffer_bit | gl_depth_buffer_bit); // clear the screen and depth Cache
Glloadidentity (); // reset the current model observation matrix
Gltranslatef (0.0f, 0.0f,-1.0f); // move the screen into one unit.

Next we use some wonderful mathematical methods to produce color change pulses. You don't have to worry if you don't know what I'm doing. I like to use many variables and simple methods to achieve my goal.
In this way, I use the two counters used to change the text position on the screen to change the red, green, and blue colors. The red value uses COs and counter 1 to change between-1.0 and 1.0. The green value uses sin and counter 2 and also changes between-1.0 and 1.0. The blue value varies between 0.5 and 1.5 using COs and counter 1 and 2. Therefore, the blue value will never be equal to 0, and the color of the text will never disappear. Stupid, but very useful.

// Set the color based on the font position
Glcolor3f (1.0f * float (COS (cnt1), 1.0f * float (sin (cnt2), 1.0f-0.5f * float (COS (cnt1 + cnt2 )));

The following is a new command. Glrasterpos2f (X, Y) is used to locate the bitmap font on the screen. The center of the screen is still (0, 0). Note that there is no Z axis position here. The bitmap font only uses the X axis (left/right) and Y axis (top/bottom ). Because we move the coordinate system to a unit on the screen, the maximum value to the left is-0.5, and the maximum value to the right is + 0.5. You will notice that I moved 0.45 pixels to the left on the X axis. It moves the text to the center of the screen. Otherwise, because the starting point of the text is the center of the screen, the overall right of the text will be caused.
The algorithm used to calculate the text location is similar to the algorithm used to set the text color. It moves the text within the range of-0.50 to-0.40 on the X axis (Remember, we reduced the value by 0.45 from the start point), which ensures that the text is always displayed on the screen. Because COs and counter 1 are used, the text swing is left and right, and sin and counter 2 are used to move between-0.35 and 0.35 on the Y axis.

// Set the grating location, that is, the font location
Glrasterpos2f (-0.45f + 0.05f * float (COS (cnt1), 0.35f * float (sin (cnt2 )));

Now it's my turn to be the most satisfied. Write real text to the screen. I tried to make it very simple and user-friendly. You will notice that it looks like calling an OpenGL function, a bit similar to the output statement style in C language. To output text on the screen, you only need to call glprint ("the text you want to write"). It is easy. The text will be exactly displayed on the screen at your specified position.
Shawn T. The modified code sent to me allows glprint to pass variables to the screen. This means you can add a counter and display the counter value on the screen. It works like this... In the next line, you can see the common text to be displayed. There is a space, a break, a space, and a "symbol" (% 7.2f) (The output format control word in C language ). now you will see % 7.2 saying what this means. It is actually very simple. % is a mark, indicating that 7.2f itself should not be displayed on the screen, because it represents a variable. 7 indicates a maximum of seven digits on the left of the decimal point. Then there is the decimal part. 2 on the right of the decimal point indicates that at most two decimal places can be reserved on the right of the decimal point. Finally, F indicates that the number type we want to display is floating point. We want to display the value of counter 1 on the screen. For example, if the value of counter 1 is 300.12345f, the number displayed on the screen is 300.12, and the numbers 3, 4, and 5 in the decimal part are removed. Because we only need to display two digits after the decimal point.

I know that if you are an experienced C programmer, this is a very basic problem. However, some people may not have used the pringf function. If you want to know more characters, buy a book or read msdn.

Glprint ("active OpenGL text with nehe-% 7.2f", cnt1); // output text to the screen

The last thing is to increase the counter value at different rates to generate a color pulse and move the text.

Cnt1 + = 0.051f; // increase the counter value
Cnt2 + = 0.005f; // increase the counter value
Return true; // continue running
}

Finally, add the killfont () function in the killglwindow () function, which is very important. It cleans up before we exit the program.

Killfont (); // Delete the font


Well, everything that uses bitmap fonts is in your OpenGL program. I have searched for articles similar to this tutorial on the Internet, but I have not found them. Maybe my website is the first website with C Code involving this topic. In any case, enjoy this tutorial, happy coding!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.