Nehe OpenGL Tutorial Lesson 43rd: FreeType Library

Source: Internet
Author: User
Tags blizzard

Go from "translation" Nehe OpenGL tutorial

Objective

Statement, this Nehe OpenGL tutorial series of articles by 51 blog yarin Translation (2010-08-19), this blog for reprint and a little collation and modification. Thank you for compiling Nehe's OpenGL pipeline tutorial, as well as yarn translation finishing.

Nehe OpenGL Lesson 43rd: FreeType Library

Using the FreeType library in OpenGL

Use the FreeType library to create very good-looking anti-aliasing fonts, remembering that Blizzard is using this library, which is the World of Warcraft. Try it, I only tell you the basic way to use, you can go farther.

Using the FreeType library in OpenGL

Here is a quick introduction that tells you how to render TrueType fonts using FreeType in OpenGL. Using this library we can render anti-aliasing text, it looks more beautiful.

Motivation

Here I will give you two examples, one is to use WGL bitmap font rendering text, the other is to use FreeType rendering text.

The text rendered with WGL is some images that look like this when you zoom in:


If you use the GNU FreeType Library (Blizzard also uses this library in their games), it will look prettier, as shown below, with anti-aliasing:


Create a program

The first step is to download the FreeType library from the following website:http://gnuwin32.sourceforge.net/packages/freetype.htm

Then when you use it to create a new program, you need to link the Libfreetype.lib library and include the FreeType header file.

Now that we've been able to create a FreeType-based program, we can't run it yet because we need freetype-6.dll files.
OK, now we can start writing our program, we start with 13 lesson code, we add two new files "Freetype.cpp" and "freetype.h". We put content related to FreeType in these two files.

Well, let's start with the freetype.h.

By convention we contain some of the required header files

#ifndef Free_nehe_h#define Free_nehe_h
FreeType header File
#include <ft2build.h>
#include <freetype/freetype.h>
#include <freetype/ftglyph.h>
#include <freetype/ftoutln.h>
#include <freetype/fttrigon.h>

OpenGL header File
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>

STL header File
#include <vector>
#include <string>

STL Exception Class
#include <stdexcept>
#pragma warning (disable:4786)

We will encapsulate the information needed for each character in a structure so that, like using WGL fonts, we can control the display state of each character separately.

Place all operations in the namespace FreeType, which avoids conflicts with other functions namespace FreeType
{
Using vector and String namespaces
Using Std::vector;
Using Std::string;

This structure holds the font information
struct Font_data
{
float h; Height of font
Gluint * TEXTURES; Textures to use
Gluint list_base; Display the value of a list

Initialize structure
void init (const char * fname, unsigned int h);

Clear all the resources
void Clean ();
};

The last thing is to define the prototype of our output string:

Output characters to screen void print (const font_data &ft_font, float x, float y, const char *fmt, ...);
}

#endif

Above is FreeType's header file, let's see how to implement it

#include "freetype.h"
Namespace FreeType {

We use textures to display characters, and in OpenGL the texture size must be 2, which is the function used to approximate the size of the character to this value. So we have the following equation:

This function returns the number of times greater than a and is the nearest 2 of a to the NEXT_P2 (int a) {int rval=1;///rval<<=1 is a prettier means of Writing rval*=  2; while (Rval<a) rval<<=1; return rval;}

The following function is Make_dlist, which is the core of this code. It contains the Ft_face object, which is the class that FreeType uses to hold the font information, and then creates a display list.

Creates a display list for the given character void Make_dlist (ft_face face, Char ch, gluint list_base, Gluint * tex_base) {
Load the outline of a given character
if (Ft_load_glyph (Face, Ft_get_char_index (face, ch), Ft_load_default))
Throw Std::runtime_error ("Ft_load_glyph failed");

Saving Outline Objects
Ft_glyph Glyph;
if (Ft_get_glyph (Face->glyph, &glyph))
Throw Std::runtime_error ("Ft_get_glyph failed");

Turn the contour into a bitmap
Ft_glyph_to_bitmap (&glyph, Ft_render_mode_normal, 0, 1);
Ft_bitmapglyph bitmap_glyph = (ft_bitmapglyph) glyph;

Save Bitmap
ft_bitmap& bitmap=bitmap_glyph->bitmap;

}

Now that we've got the bitmap from the FreeType, we need to convert it to a bitmap that satisfies the OpenGL texture requirements. You have to know that in OpenGL, bitmaps represent black-and-white data, whereas in FreeType we use 8-bit colors to represent bitmaps, so freetype bitmaps can hold luminance information.

Convert to OpenGL can be used for size int width = NEXT_P2 (bitmap.width); int height = NEXT_P2 (bitmap.rows);
Saving Bitmap data
glubyte* expanded_data = new glubyte[2 * width * height];

Here we use a 8-bit representation of the luminance 8-bit to represent the alpha value
for (int j=0; J for (int i=0; i < width; i++) {
expanded_data[2* (i+j*width)]= expanded_data[2* (i+j*width) +1] =
(I>=bitmap.width | | j>=bitmap.rows)?
0:bitmap.buffer[i + bitmap.width*j];
}
}

Next we select the font texture, and generate the texture of the font map

Texture filter Setting Font texture glbindtexture (gl_texture_2d, tex_base[ch]); Gltexparameteri (gl_texture_2d,gl_texture_mag_filter,gl_linear); Gltexparameteri (gl_texture_2d,gl_texture_min_filter,gl_linear);
Bonding Textures
Glteximage2d (gl_texture_2d, 0, Gl_rgba, width, height, 0,
Gl_luminance_alpha, Gl_unsigned_byte, Expanded_data);

To release allocated memory
delete [] expanded_data;

Then create a display list, which is used to draw a character

Create a display list glnewlist (list_base+ch,gl_compile);
Glbindtexture (Gl_texture_2d,tex_base[ch]);

First we move a little to the left.
Gltranslatef (bitmap_glyph->left,0,0);

Then we move down a little bit, this team ' G ', ' Y ' characters are useful
It makes all the characters have a baseline
Glpushmatrix ();
Gltranslatef (0,bitmap_glyph->top-bitmap.rows,0);

Calculate the width of a character image in a bitmap
float x= (float) bitmap.width/(float) width,
y= (float) bitmap.rows/(float) height;

Draw a square that displays characters
Glbegin (gl_quads);
GLTEXCOORD2D (0,0); GLVERTEX2F (0,bitmap.rows);
GLTEXCOORD2D (0,y); GLVERTEX2F (0,0);
Gltexcoord2d (x, y); GLVERTEX2F (bitmap.width,0);
GLTEXCOORD2D (x,0); GLVERTEX2F (bitmap.width,bitmap.rows);
Glend ();
Glpopmatrix ();
Gltranslatef (face->glyph->advance.x >> 6, 0,0);

End drawing of the display list
Glendlist ();
}

The following function will use Make_dlist to create a display list of a character set, fname the FreeType character file you want to use.

void Font_data::init (const char * fname, unsigned int h) {//Save texture ID. Textures = new gluint[128];
this->h=h;

Create a FreeType Library
Ft_library Library;
if (Ft_init_freetype (&library))
Throw Std::runtime_error ("Ft_init_freetype failed");

The class that holds the font information in the FreeType library is called face
Ft_face face;

Initialize the face class with the FreeType character file you entered
if (Ft_new_face (library, fname, 0, &face))
Throw Std::runtime_error ("Ft_new_face failed (there is probably a problem with your font file)");

Using 1/64 as the height of a pixel in freetype so we need to scale H to meet this requirement
Ft_set_char_size (Face, H << 6, H << 6, 96, 96);

Create 128 Display lists
List_base=glgenlists (128);
Glgentextures (textures);
Make_dlist (Face,i,list_base,textures);

Release Face class
Ft_done_face (face);

Releasing the FreeType library
Ft_done_freetype (library);
}

The following function completes the work of releasing the resource  
  
void Font_data::clean () {  gldeletelists (list_base,128);  gldeletetextures (128,textures);  delete [] textures;}

To use the following two equations in the print function, the Pushscreencoordinatematrix function holds the current matrix and sets the viewport to match the current window size. The Pop_projection_matrix function is used to return the Pushscreencoordinatematrix saved matrix. Reference Manual.

Saves the current matrix and sets the viewport to match the current window size inline void Pushscreencoordinatematrix () {glpushattrib (gl_transform_bit); Glint Viewport[4]; Glgetintegerv (Gl_viewport, VIEWPORT); Glmatrixmode (gl_projection); Glpushmatrix (); Glloadidentity (); Gluortho2d (Viewport[0],viewport[2],viewport[1],viewport[3]); Glpopattrib ();}
Returns the Pushscreencoordinatematrix saved matrix
inline void Pop_projection_matrix () {
Glpushattrib (Gl_transform_bit);
Glmatrixmode (gl_projection);
Glpopmatrix ();
Glpopattrib ();

Our print function is very similar to the 13 lesson function, but there are some differences in implementation. We're actually using a 2-channel texture instead of an image.

Output text void print (const font_data &ft_font, float x, float y, const char *fmt, ...)                                            {//Save current Matrix Pushscreencoordinatematrix (); Gluint font=ft_font.list_base;                                                  float h=ft_font.h/.63f;          Char text[256]; Va_list ap;
if (FMT = = NULL)
*text=0;
else {
Va_start (AP, FMT);
vsprintf (text, FMT, AP);
Va_end (AP);
}

Split the input string into a carriage return
const char *start_line=text;
Vector<string> lines;
for (const char *c=text;*c;c++) {
if (*c== ' \ n ') {
String line;
for (const char *n=start_line;n<c;n++) line.append (1,*n);
Lines.push_back (line);
start_line=c+1;
}
}
if (start_line) {
String line;
for (const char *n=start_line;n<c;n++) line.append (1,*n);
Lines.push_back (line);
}

Glpushattrib (Gl_list_bit | Gl_current_bit | Gl_enable_bit | Gl_transform_bit);
Glmatrixmode (Gl_modelview);
Gldisable (gl_lighting);
Glenable (gl_texture_2d);
Gldisable (gl_depth_test);
Glenable (Gl_blend);
Glblendfunc (Gl_src_alpha, Gl_one_minus_src_alpha);

Gllistbase (font);

float MODELVIEW_MATRIX[16]; GLGETFLOATV (Gl_modelview_matrix, Modelview_matrix);
The following code completes the specific drawing process
for (int i=0;i<lines.size (); i++) {
Glpushmatrix ();
Glloadidentity ();
Gltranslatef (x,y-h*i,0);
GLMULTMATRIXF (Modelview_matrix);

Call Display list drawing
Glcalllists (Lines[i].length (), Gl_unsigned_byte, Lines[i].c_str ());

Glpopmatrix ();
}

Glpopattrib ();

Pop_projection_matrix ();
}

}

}

FreeType Library We have written, now we are in the 13 lesson code to make some changes, of course, first we need to include freetype.h header file

#include "freetype.h"

Now we can call the FreeType library to draw the string.

Save information on the fonts we created Freetype::font_data Our_font;

Next use the Test.ttf file to initialize the font

Our_font.init ("Test.ttf", 16);

Remember to release memory resources at the end of the program

Our_font.clean ();

Here is our specific drawing function.

int Drawglscene (glvoid) {glclear (Gl_color_buffer_bit |      Gl_depth_buffer_bit);          Glloadidentity (); Gltranslatef (0.0f,0.0f,-1.0f);
Blue text
Glcolor3ub (0,0,0XFF);

Draw WGL Text
GLRASTERPOS2F ( -0.40f, 0.35f);
Glprint ("Active WGL Bitmap Text with Nehe-%7.2f", cnt1);

Red text
Glcolor3ub (0xff,0,0);

Glpushmatrix ();
Glloadidentity ();
Glrotatef (cnt1,0,0,1);
Glscalef (1,.8+.3*cos (CNT1/5), 1);
Gltranslatef ( -180,0,0);
Draw FreeType Text
FreeType::p rint (Our_font, +, +, "Active freetype Text-%7.2f", cnt1);
Glpopmatrix ();

cnt1+=0.051f;
cnt2+=0.005f;
return TRUE; Successful return
}

Original source code and version of the download:

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=43

Nehe OpenGL Tutorial Lesson 43rd: FreeType Library

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.