Home » Android » android – Draw text in OpenGL ES

android – Draw text in OpenGL ES

Posted by: admin March 11, 2020 Leave a comment


I’m currently developing a small OpenGL game for the Android platform and I wonder if there’s an easy way to render text on top of the rendered frame (like a HUD with the player´s score etc). The text would need to use a custom font also.

I’ve seen an example using a View as an overlay, but I don’t know if I want to do that since I might want to port the game to other platforms later.

Any ideas?

How to&Answers:

The Android SDK doesn’t come with any easy way to draw text on OpenGL views. Leaving you with the following options.

  1. Place a TextView over your SurfaceView. This is slow and bad, but the most direct approach.
  2. Render common strings to textures, and simply draw those textures. This is by far the simplest and fastest, but the least flexible.
  3. Roll-your-own text rendering code based on a sprite. Probably second best choice if 2 isn’t an option. A good way to get your feet wet but note that while it seems simple (and basic features are), it get’s harder and more challenging as you add more features (texture-alignment, dealing with line-breaks, variable-width fonts etc.) – if you take this route, make it as simple as you can get away with!
  4. Use an off-the-shelf/open-source library. There are a few around if you hunt on Google, the tricky bit is getting them integrated and running. But at least, once you do that, you’ll have all the flexibility and maturity they provide.


Rendering text to a texture is simpler than what the Sprite Text demo make it looks like, the basic idea is to use the Canvas class to render to a Bitmap and then pass the Bitmap to an OpenGL texture:

// Create an empty, mutable bitmap
Bitmap bitmap = Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_4444);
// get a canvas to paint over the bitmap
Canvas canvas = new Canvas(bitmap);

// get a background image from resources
// note the image format must match the bitmap format
Drawable background = context.getResources().getDrawable(R.drawable.background);
background.setBounds(0, 0, 256, 256);
background.draw(canvas); // draw the background to our bitmap

// Draw the text
Paint textPaint = new Paint();
textPaint.setARGB(0xff, 0x00, 0x00, 0x00);
// draw the text centered
canvas.drawText("Hello World", 16,112, textPaint);

//Generate one texture pointer...
gl.glGenTextures(1, textures, 0);
//...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

//Create Nearest Filtered Texture

//Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE

//Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

//Clean up


I’ve written a tutorial that expands on the answer posted by JVitela. Basically, it uses the same idea, but instead of rendering each string to a texture, it renders all characters from a font file to a texture and uses that to allow for full dynamic text rendering with no further slowdowns (once the initialization is complete).

The main advantage of my method, compared to the various font atlas generators, is that you can ship small font files (.ttf .otf) with your project instead of having to ship large bitmaps for every font variation and size. It can generate perfect quality fonts at any resolution using only a font file 🙂

The tutorial includes full code that can be used in any project 🙂


According to this link:


You can render any View to a bitmap. It’s probably worth assuming that you can layout a view as you require (including text, images etc.) and then render it to a Bitmap.

Using JVitela’s code above you should be able to use that Bitmap as an OpenGL texture.


Take a look at CBFG and the Android port of the loading/rendering code. You should be able to drop the code into your project and use it straight away.

CBFG – http://www.codehead.co.uk/cbfg

Android loader – http://www.codehead.co.uk/cbfg/TexFont.java


I looked at the sprite text example and it looks awfully complicated for such a task, I considered rendering to a texture too, but I’m worried about the performance hit that might cause.
I might just have to go with a view instead and worry about porting when it’s time to cross that bridge 🙂


Look at the “Sprite Text” sample in the GLSurfaceView samples.


IMHO there are three reasons to use OpenGL ES in a game:

  1. Avoid differences between mobile platforms by using an open standard;
  2. To have more control of the render process;
  3. To benefit from GPU parallel processing;

Drawing text is always a problem in game design, because you are drawing things, so you cannot have the look and feel of a common activity, with widgets and so on.

You can use a framework to generate Bitmap fonts from TrueType fonts and render them. All the frameworks I’ve seen operate the same way: generate the vertex and texture coordinates for the text in draw time. This is not the most efficient use of OpenGL.

The best way is to allocate remote buffers (vertex buffer objects – VBOs) for the vertices and textures early in code, avoiding the lazy memory transfer operations in draw time.

Keep in mind that game players don’t like to read text, so you won’t write a long dynamically generated text. For labels, you can use static textures, leaving dynamic text for time and score, and both are numeric with a few characters long.

So, my solution is simple:

  1. Create texture for common labels and warnings;
  2. Create texture for numbers 0-9, “:”, “+”, and “-“. One texture for each character;
  3. Generate remote VBOs for all positions in the screen. I can render static or dynamic text in that positions, but the VBOs are static;
  4. Generate just one Texture VBO, as text is always rendered one way;
  5. In draw time, I render the static text;
  6. For dynamic text, I can peek at the position VBO, get the character texture and draw it, a character at a time.

Draw operations are fast, if you use remote static buffers.

I create an XML file with screen positions (based on screen’s diagonal percentage) and textures (static and characters), and then I load this XML before rendering.

To get a high FPS rate, you should avoid generating VBOs at draw time.


If you insist on using GL, you could render the text on to textures. Assuming that most of the HUD is relatively static, you shouldn’t have to load the textures to texture memory too often.


Take a look at CBFG and the Android port of the loading/rendering
code. You should be able to drop the code into your project and use it
straight away.

  1. CBFG

  2. Android loader

I have problems with this implementation. It displays only one character, when I try do change size of the font’s bitmap (I need special letters) whole draw fails 🙁


I have been looking for this for a few hours, this was the first article i came accross and although it has the best answer, the most popular answers i think are off the mark. Certainly for what i needed.
weichsel’s and shakazed’s answers were right on the button but a bit obscured in the articles.
To put you right to the project. Here:
Just create a new Android project based on existing sample. Choose ApiDemos:

Look under the source folder


And you will find everything you need.


For static text:

  • Generate an image with all words used on your PC (For example with GIMP).
  • Load this as a texture and use it as material for a plane.

For long text that needs to be updated once in a while:

  • Let android draw on a bitmap canvas (JVitela’s solution).
  • Load this as material for a plane.
  • Use different texture coordinates for each word.

For a number (formatted 00.0):

  • Generate an image with all numbers and a dot.
  • Load this as material for a plane.
  • Use below shader.
  • In your onDraw event only update the value variable sent to the shader.

    precision highp float;
    precision highp sampler2D;
    uniform float uTime;
    uniform float uValue;
    uniform vec3 iResolution;
    varying vec4 v_Color;
    varying vec2 vTextureCoord;
    uniform sampler2D s_texture;
    void main() {
    vec4 fragColor = vec4(1.0, 0.5, 0.2, 0.5);
    vec2 uv = vTextureCoord;
    float devisor = 10.75;
    float digit;
    float i;
    float uCol;
    float uRow;
    if (uv.y < 0.45) {
        if (uv.x > 0.75) {
            digit = floor(uValue*10.0);
            digit = digit - floor(digit/10.0)*10.0;
            i = 48.0 - 32.0 + digit;
            uRow = floor(i / 10.0);
            uCol = i - 10.0 * uRow;
            fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-1.5) / devisor, uRow / devisor) );
        } else if (uv.x > 0.5) {
            uCol = 4.0;
            uRow = 1.0;
            fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-1.0) / devisor, uRow / devisor) );
        } else if (uv.x > 0.25) {
            digit = floor(uValue);
            digit = digit - floor(digit/10.0)*10.0;
            i = 48.0 - 32.0 + digit;
            uRow = floor(i / 10.0);
            uCol = i - 10.0 * uRow;
            fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-0.5) / devisor, uRow / devisor) );
        } else if (uValue >= 10.0) {
            digit = floor(uValue/10.0);
            digit = digit - floor(digit/10.0)*10.0;
            i = 48.0 - 32.0 + digit;
            uRow = floor(i / 10.0);
            uCol = i - 10.0 * uRow;
            fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-0.0) / devisor, uRow / devisor) );
        } else {
            fragColor = vec4(0.0, 0.0, 0.0, 0.0);
    } else {
        fragColor = vec4(0.0, 0.0, 0.0, 0.0);
    gl_FragColor = fragColor;

Above code works for a texture atlas where numbers start from 0 at the 7th column of the 2nd row of the font atlas (texture).

Refer to https://www.shadertoy.com/view/Xl23Dw for demonstration (with wrong texture though)