Rendering Text in OpenGL 2.0 ES on Android

Hello all,

I have just finished porting fractious’s Rendering Text in OpenGL on Android to OpenGL ES 2.0 (this is the mobile version of OpenGL 3.0 and the main difference with the older versions OpenGL is having acces to the shaders, which allow us to run code on the GPU).

I had to do this because my project TheHunt uses, you guessed it, the newer version. Reason is that it would allow me to do some nifty shader tricks… some day 🙂

So here is my code – Feel free to use it for whatever you want as it is licensed under the CC0 1.0 public domain license.


The example application, Texample2

Some implementation details:

  • I firstly started by simply converting the OpenGL ES 1 commands to the newer version. The Model, View and Projection matrices were passed using a uniform variable to the shaders, i.e. all the letters used the same matrices. This was good enough to produce horizontal text
  • In TheHunt I use text to label events (fishbone flops, net snatches), and I need this text to be tilted (it would be somewhat boring otherwise). For this I needed to be able to assign individual model matrices to each word. A bit tricky, but using Sprite Batching in OpenGL ES 2.0 | Anton Holmquist as inspiration I managed to do it. In short, instead of an uniform Model-View-Projection matrix, the vertex shader has an uniform array of matrices. I fill this array with an individual matrix for each letter and also pass a matrix index attribute for each vertex (the exact same method suggested by Anton Holmquist.) The result is that each GLText::draw call can tilt the string drawn with a certain angle (it can now receive an angle argument, in degrees).
  • The last catch was drawing color text – at first, all text was coming out black for me. The reason turns out to be that the texture is defined as grayscale, so in the fragment shader we need to multiply the color we want for the text (passed as uniform u_Color) with the grayscale value (called W in OpenGL) of the texture (not with the whole texture color, because it is something like [0, 0, 0, grayscale] which was resulting in the all black text):

gl_FragColor = texture2D(u_Texture, v_TexCoordinate).w * u_Color

— from

That’s all I can think of, and the result is efficient text drawing in OpenGL ES 2.0, and more importantly in TheHunt, where you can expect a nice GUI to appear soon!


37 responses to “Rendering Text in OpenGL 2.0 ES on Android

    • I’m happy to hear this is useful for you, mike! Indeed, GUI will be a major leap for TheHunt, I will try to come up with something in a week or two =)

  1. I found this really useful and implemented it in to my project but only the first letter of each line renders properly. Any ideas?

    • Hey Simon. I will be happy to help you pinpoint the problem – who knows you might have stumbled in a bug =D

      Have you tried using the setSpace() method on your GLText instance before drawing? This controls the spacing between the characters, maybe yours is too big or too small for some reason?

      If not, please tell me more details of the configuration you’re using – font file and size you’re using in GLText.load() and the viewProjection matrix you’re using in GLText.begin and I will try to reproduce the behavior.

    • You’re welcome! Glad it works.

      BTW, what font size do you use? I’d like to look into it, the default calculated spacing must be off.

      • glText.load( “Roboto-Regular.ttf”, 16, 2, 2 ); // Create Font (Height: 14 Pixels / X+Y Padding 2 Pixels)

        Another suggestion, I basically have added Z position to the project so that a piece of text can follow a user in my game. What I found is that even using glText.DrawC, rotation did not happen to the center of the text but rotated around the first letter.

        I had to make some changes but not happy with them

        // create a model matrix based on x, y and angleDeg
        float[] modelMatrix = new float[16];
        Matrix.setIdentityM(modelMatrix, 0);
        Matrix.translateM(modelMatrix, 0, x – 1.0f, y, z + 2.0f);
        Matrix.rotateM(modelMatrix, 0, angleDeg, 0, 1, 0);
        // added by me lol
        Matrix.translateM(modelMatrix, 0, -2, 0, 0);

      • Simon, I’m sorry for the delay =)
        It will be nice to have it working in 3D. I will try to implement it in the next couple of days and let you know!

      • Sadly you have hit the same issues as I have if you rotate on the Y access
        Matrix.rotateM(modelMatrix, 0, angleDeg, 0, 1, 0);

        It does not rotate around the center of the word for the y access, thanks for trying though

      • You are right – have been trying all day to fix it, I give up for now, It rotates around the center of the word for y axis now when at (0, 0), but translating it around alters the rotation (only around x and y axis, z always works), which should not be happening. Any ideas?

  2. Thank you for your code! I really preciate it.
    Actually, I saw nothing on the sreen at first, but than with this lines
    it works just fine.
    I have been searching for about a 10 minutes to find such a way to render text in OpenGL ES 2.0.
    Again, thank you for porting fractious’s Rendering Text in OpenGL on Android to OpenGL ES 2.0! 🙂

  3. Hi!
    Thank you so much for the code!
    I’m trying to use this version, and although it works on device, it always crashes the emulator. Even running the example project provided, without modifications, the emulator still crash.
    Any idea?

      • Simon,

        This anyone should be me I suppose heh. I will work on it a little bit the next couple of days and let you know if I get anywhere.

      • Hi d3kod!

        I’m using Host GPU Emulation in the AVD, but it does crash the emulator. I have tried with differents Devices, Targets and CPU/ABI but to no avail.
        Can you run the example project on the emulator? Could you please show me your emulator configuration?

        Thank you!

      • I’m sorry it didn’t work out – I was supposed to try doing it today but I forgot… I will try it tomorrow and let you know ^_^

      • Hey fredluciano, it works!
        CPU: ARM
        Target: 4.0.3 (but should work with any 4+)
        Skin: Nexus 4
        hw.gpu.enabled = yes

        Everything else is the default values. Let me know if it works out for you, if not it will be very helpful if you can give me the logcat output (the exception that occurs would be nice)

  4. Hi, yes i’ve tried it too on various configs including the one you recommend above, but still crashes badly. badly as in no useful logcat output. Commenting out the glText.begin, …draw, …end statements does allow it to run (but no text shows obviously ). I guess logging various parts in the process as one form of initial debugging may help you pin point the location of the problem.

  5. First of all, thank you for this code. It is very handy.
    The code runs fine on my Samsung GS3. When I try to run the same code on my Droid X, I get a 1281 error on the line:
    I’ve determined that this is because the GL_MAX_VERTEX_ATTRIBS on my Droid X is only 8, and mColorHandle is set to 26. Any idea how to work around this for older devices?

    • More information:
      When I run my app on my Samsung GS3 (android 4.1.2), GL_MAX_VERTEX_ATTRIBS is 16, but mColorHandle is set to 0.
      When I run my app on my Motorola Droid X (android 2.3.4), GL_MAX_VERTEX_ATTRIBS is 8, but mColorHandle is set to 26.
      So since 26>8, the 1281 error gets thrown. I don’t understand why the Droid gets a handle value of 26 and the GS3 gets 8.

  6. Thanks for the GLES 2.0 port. BTW, I’m also getting a 1281 error for GLES20.glEnableVertexAttribArray(mColorHandle) on an Android 4.0.4 Onepad 940 tablet whereas it works flawlessly on a Samsung Galaxy Y with Gingerbread. Couldn’t find out what’s going wrong so far.

  7. hello, I found this tool very helpful, but unfortunately I can’t seem to make it adjust to different screen sizes. Can you help me please?

  8. Hi,
    First off, thanks so much for creating this OpenGL2.0 version.
    I am having some problems rendering the text into an existing surface. I have little to no OpenGL experience, and all the matrices confuse me.
    I want to draw the text into a surface that I render from the CameraPreview. I need it to be in the same surface so that the text gets “embedded” in the video that I render.

    In my attempts I just ended up making my existing surface green and not affecting it at all.

    Any help is greatly appreciated,

    • Hi Patrick – I cannot be certain without looking at your code, but is it possible that you are drawing the font too big and that’s why everything turns green (the color of the font)? You can quickly check that by changing the color of the font to something else – if the surface ends up in another color then this is the issue and you can simply specify a smaller font size.

      Let me know if this helps.

      • This is what I have currently, it leaves the surface untouched (at least seemingly):

        In surfaceCreated() I do the same as was written in Texample2Renderer.

        What confuses me is “Matrix.multiplyMM(mVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);”, what does it do? Do I need all these matrices?

        What I have done is simply change the matrix in the glText.begin(…) call.

        Best regards,

  9. Thank you for your code!
    I have a question in your code:
    GLES20.glViewport(0, 0, width, height);
    float ratio = (float) width / height;

    // Take into account device orientation
    if (width > height) {
    Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 1, 10);
    else {
    Matrix.frustumM(mProjMatrix, 0, -1, 1, -1/ratio, 1/ratio, 1, 10);

    // Save width and height
    this.width = width; // Save Current Width
    this.height = height; // Save Current Height

    int useForOrtho = Math.min(width, height);

    //TODO: Is this wrong?
    Matrix.orthoM(mVMatrix, 0,
    useForOrtho/2, 0.1f, 100f);

    Could you please to explain why using both frustum and ortho projection here?
    Regards 🙂

  10. Hi d3kod,

    I’m working with your ported version and I have several questions regarding integrating it in already working OpenGl ES app. Hope you’re still available on this blog.

    My main issues are:
    0) The text appears flipped and I see only halves of letters (I suppose my camera may be directed wrong)
    1) I cannot change color of the text (only white)

    I would be glad to get some help as I was struggling for a week with some success, but still need to fix those two issues.

    Really looking forward for your reply.

    Kindest regards, Greg.

      • WOW! Thanks! Should I post relevant parts of code here? Or send them via email?

        BTW, I found that color changing (item 2) is possible. I just misunderstood your API. Sorry. The first part is still relevant. I tried to tweak the code in particular, I changed the indices buffer so the letters appear correct (they were flipped twice (or rotated), also I changed increment X coordinate to decrement, so now the order is correct and letters appear from left to right. I’m sure it is something about my View Matrix calculation. The only problem now is that letter textures overlap one another and the background on these textures hides part of letters. I would attach a screenshot if I could.

        Thank you very much!


Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s