Tuesday, March 14, 2017

GT Racing 2 The Real Car Experience v1 0 2 UnlimitedGoldMoney

GT Racing 2 The Real Car Experience v1 0 2 UnlimitedGoldMoney


Screen01

If youre familiar with OpenGL, you know that it does not provide any native font/text support. On the PC, developers have access to wglUseFontBitmaps Windows extension to easily create Bitmap fonts for them; but unfortunately this is not available on Windows Mobile. However, a font is essentially just a texture, so all the tools necessary to draw text are available.

There are traditionally two approaches to drawing text on the screen:

  • Using GDI, draw the string to a Bitmap and load it into OpenGL for blitting.
    • Pros:
      • Easy to do.
      • Really fast if your text isnt changing. (2 triangles)
    • Cons:
      • You need a texture per string, which can be costly.
      • The texture objects are basically immutable and not reusable.
  • Using GDI, draw every printable character to a Bitmap, and then draw a series of quads that reference the specific texture coordinates you want to draw the corresponding letter. (creating dynamic Bitmap fonts)
    • Pros:
      • This is very efficient with memory, since any new string is simply just a new set of vertex and texture coordinates that reference a single texture.
      • Since the text is simply just a series of quads, you can do per vertex tweaking to do some really cool effects.
    • Cons:
      • More work on the GPU
      • Harder to set up and do "right".

Heres the resulting textures from both methods:

Foo

temp

1 Texture for a single blittable string

1 texture that contains all printable characters. Strings are drawn by drawing a series of rects.

 

The optimal approach to this problem would be a hybrid solution that would hinge on the nature of the text: static/dynamic, large/small, special effects/vanilla? But in this article, Im going to describe how to do it the better of the two ways when on a mobile platform: the single texture lookup.

Lets take a look at the sample image again:

Screen01 BitmapBrush

This sample is demonstrates a couple of the unique capabilities of the Bitmap font method:

  • The FPS and "this is" text is just standard text rendering. Notice that their geometry can overlap and not interfere with each others rendering. This is because the Bitmap font is actually just a GL_ALPHA texture. The visible portions of a letter have a non zero alpha.
  • The "a test" text is per character coloring. The top half is red, while the bottom left is green, and the bottom right is blue.
  • The "hello world" text is a multitextured font. The Bitmap font texture was merged with the flame texture on the right to create a cool textured string effect!

So, there are two challenges to creating a proper Bitmap font:

  • Determining the width/height of each character in a given font, and generating the resultant texture and character lookup position/dimension.
  • Creating vertex array and texture coordinate array from a given string (ie, "hello world").

Text is not as trivial to render as you may think at first glance. Characters are not just a series of identical sized quads that are lined up left to right. Each character has its own width, and one characters quad can actually overlap into another character. For example, look at these "foos". Notice how the "f" somewhat falls into the area over the first "o".

Foo

Foo2

Foo3

Rendered

Incorrect quads

Correct quads

This is a significant factor we need to account for when Bitmap fonts. Primitive approaches will often use the incorrect way since it is very easy to implement. The leading and trailing space font properties can be retrieved from GDI through the GetFontMetrics function. And another GDI call, GetCharWidth32, can be used to determine the width of a given character. With that, one can generate the Bitmap texture, and also compute the dimensions and overlap of each character.
 
Using this information, you can generate the following texture:
temp
This is a good start, but this Bitmap is still just an RGBA image. Although this bitmap works, all we really need is a texture that consists of only alpha components, ie, GL_ALPHA. (Using only alpha components allows the GPU to optimize the pipeline and save memory). I say alpha, because this bitmap is not a simple "mask". If it were a mask, the text would be quite pixelated like the left X:
TextAlpha
 
So, to convert from an RGB image to an Alpha image, we must loop through the Bitmap memory and add the R, G, and B components and divide it by 3 to determine the Alpha value. And with that youll have a valid Alpha texture! (Note: You cant simply take a single R, G, or B component and use that for alpha because the color is gray; you must take the average. This is because ClearType actually sets pixels to non-gray values to achieve sub-pixel antialiasing. More info at the ClearType Wikipedia entry.)
 
The next difficult task is rendering a string by using the texture and character offsets/dimensions we computed earlier. Drawing a single line string is a straightforward loop through the characters. But in actual application, text can wrap when the end of the screen is reach, and be aligned to the center, right, or left. GDI (and by proxy the Graphics object) allow a developer to render string given a Font, a bounding box, and various formatting flags by way of the DrawText function. This function handles all the positioning and such transparently. For OpenGL, we need to recreate that functionality. And although that bit is difficult, it is also tedious and rather uninteresting, so I wont get into the implementation details.
 
Anyhow, you didnt read all the way to the end of this article and not get a code sample! Heres the updated Managed OpenGL ES SDK, along with the sample application demonstrated above.

Go to link for download