OpenGL ES 2.0 Tutorial for Android – Part I – Getting started

It has been a while since I was able to write any tutorials and continue on my last serie about OpenGL ES 1.x feels a bit out-dated so I start all over again but with OpenGL ES 2.0 but there are so many common things that I will be copy & pasting a lot. I really love all the comments I have gotten on my previous tutorials but I want to apologize in advance that I’m not able to answer all mail and comments.

I will try to keep the focus on simplicity and making it easy to understand the different parts rather then focusing on high performance and good architecture so what I am saying is that this is for learning not for production.

I don’t always remember where I found particular information so I might not always be able to give you the right reference. If you feel that I have borrowed stuff from you but have forgotten to add you as a reference, please e-mail me. I’m all about giving credit where it belongs.

Prerequisites

To be able to follow me in this tutorials all you need to know is how to setup an android project and are used to work with eclipse and java. I will try to keep the focus on simplicity and making it easy to understand. The android project needs to be at least on API level 11.

So let us start!

Setting up OpenGL ES 2.0 view

The first thing you need to do is getting the view up and running. The entry point for an android application is the Activity and this is where I start. Detecting if a device supports OpenGL ES 2.0 is quite straight forward you ask the activity manager about the device configuration information and read the OpenGL ES version from there.

You can also make sure no one install the application from Google Play on a device not supporting OpenGL ES 2.0 by adding a uses-feature in the AndroidManifest.xml.

When we are sure about the support for OpenGL ES 2.0 we can go ahead and setup the GLSurfaceView. The GLSurfaceView has a lot of functions and I will not go into them all and I will only go into a them when I need them.

The first function to look at is the setEGLContextClientVersion(int version) as it sound this is where we actually set the OpenGL ES version we want to work with, in this case 2.

The next function that is interesting at the moment is the setPreserveEGLContextOnPause(boolean preserveOnPause) this is by default set to false meaning that the OpenGL ES context is not preserved when the application is paused. Changing this to true will preserve the OpenGL ES context if the device support it. What this means is that even if we set it to true we need to handle the case then the device looses the context.

The last function for now is the setRenderer(GLSurfaceView.Renderer renderer). If we don’t set a renderer the application will crash, so we better set a renderer. The GLSurfaceView.Renderer is an interface that we need to implement.

To setup OpenGL ES 2.0 this is the code:

To work properly the GLSurfaceView need to get the onPause and onResume events from the Activity.

If you are doing a game you probably like to enter fullscreen mode you can go into fullscreen by adding the following lines before you set the content view.

Putting it all together and we get this:

At the moment you get an error because we are missing the GLES20Renderer class, we get to that one soon.

Lifecycle

One of the most important things to get right from the beginning in all application development is the lifecycle. Android has a lifecycle for the activity and for the view but for OpenGL ES we need to create our own within the activity lifecycle. First we need to know when the OpenGL context is up and running, we also need to know if the context is lost so we can recreate the resources on the GPU more on this later.

To know if OpenGL is up and running I will use an onCreate method.

We also need to know when to draw stuff.

Let us start by looking at the android.opengl.GLSurfaceView.Renderer interface, if you have worked with OpenGL ES 1.x you know about this. We have three methods we need to implement here:

The reason I have named the GL10 parameter to notUsed is because it is never used when working with OpenGL ES 2.0.

The method onSurfaceCreated is called every time the surface is created which means we have gotten a new gl context. So we set a flag to true to keep track of newly created context.

onSurfaceChanged is called direct after onSurfaceCreated or when the surface have changes properties like width and height. We also can determine here if the context have been lost by checking the mSurfaceCreated flag that we set in the onSurfaceCreated method if it is true the context is just created and we need to re-/create the resources on the gpu.

And finally onDrawFrame is called every frame, here we keep track of the frames per second counter and if it is the first drawn frame.

I made the GLRenderer class abstract for two reasons. First reason is that it separates the lifecycle code from the rendering code making it a bit easier to follow. The second reason is that it makes our class more reusable. So to make our example work we need to create a class that inherited the GLRenderer. This is a simple implementation just making the screen black.

This is pretty much all you need to get your view up and running. If you compile and run it you will see a nice black screen.

References

The info used in this tutorial is collected from:
Android Developers
OpenGL ES 2.0 Reference Pages

You can download the source for this tutorial here: tutorial_01.zip
You can also checkout the code from: github.com

29 Responses to “OpenGL ES 2.0 Tutorial for Android – Part I – Getting started”

  1. […] OpenGL ES 2.0 Tutorial for Android […]

  2. Joel (France) says:

    Very nice, very comprehensive.
    Where is the part two ? no time to write it ?
    i am sad…
    Thanks very much

  3. Wyatt says:

    OK, I’m stumped. Eclipse simply will not let me compile the example, it doesn’t like GLES20Renderer methods.

    “The method onCreate(int, int, boolean) of type GLES20Renderer must override or implement a supertype method”

    I can’t find it, I’ve tried everything google comes up with. I thought that’s what we’re DOING, is implementing a supertype method. Even when I let Eclipse auto-generate the class, it comes up with this. Both methods raise this error. If I auto-generate one of the other methods in GLRenderer, it doesn’t complain, but apparently those are methods of javax.microedition.khronos.opengles.GL10, and the ones included in the example are not (I think, because if I comment out @override, then javax.microedition.khronos.opengles.GL10 is unused).

  4. Rohit says:

    Very clean and clear tutorial. Thanks for posting. More tutorial will be appreciated. :)

  5. krishna says:

    Great set of tutorials on ES1.0, A well intro to the ES2.0; badly looking forward for the next set of tutorials… when can i see?

  6. Daniel says:

    I have a little question, i don’t know where to search any more… tried the official Tutorial for OpenGLES2, tried to run the BasicGLSurface-Project from the Examples(Api 11) and much more.. he ever says “The source attachement does not contain the source for the file GLSurfaceView.class”.
    Is there anything needed to install additionally? Having the Android SDK up to date and working on Eclipse.
    Tried with minSDK 8 and 11.

  7. zachary says:

    5/5
    Please write a part two.

  8. Jake says:

    The compiler returns an error with

    setRenderer( new GLES20Renderer());

    saying that GLES20Renderer does not fit the type Renderer for the setRenderer method. What can I do to fix this?

  9. Sundar BN says:

    The above proj compiled but gave me this run-time error:
    Wd be mighty grateful if I could get any pointers on how to get around this. Am trying to print some real time
    plots on android and it takes 13 secs for one sweep & this
    is not good. I hoped openGLES would help me out.
    Thanks in advance.
    #### Logcat error #####

    08-08 11:56:02.694: E/AndroidRuntime(2244): FATAL EXCEPTION: main
    08-08 11:56:02.694: E/AndroidRuntime(2244): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.gles20/com.example.gles20.GLES20Activity}: java.lang.NullPointerException
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.app.ActivityThread.access$600(ActivityThread.java:141)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.os.Handler.dispatchMessage(Handler.java:99)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.os.Looper.loop(Looper.java:137)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.app.ActivityThread.main(ActivityThread.java:5103)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at java.lang.reflect.Method.invokeNative(Native Method)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at java.lang.reflect.Method.invoke(Method.java:525)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at dalvik.system.NativeStart.main(Native Method)
    08-08 11:56:02.694: E/AndroidRuntime(2244): Caused by: java.lang.NullPointerException
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.view.ViewGroup.addViewInner(ViewGroup.java:3505)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.view.ViewGroup.addView(ViewGroup.java:3377)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.view.ViewGroup.addView(ViewGroup.java:3353)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:286)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:276)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.app.Activity.setContentView(Activity.java:1915)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at com.example.gles20.GLES20Activity.onCreate(GLES20Activity.java:36)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.app.Activity.performCreate(Activity.java:5133)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
    08-08 11:56:02.694: E/AndroidRuntime(2244): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)

  10. Andrea says:

    Great tutorial.

    There seems to be a typo though. It seems that you use mGLView throughout the main activity except for onPause() and onResume() where you use mSurfaceView. This however is true only for the larger code snippet. In the small code snippets you use mGLView() also for onResume() and onPause as it should be.

    When can we expect the next part(s) of this tutorial? I am interested in having a camera preview on an openGL surface so that I can manipulate it. :)

    Thanks again!

  11. Vamsi says:

    Hi, looking forward for next set of tutorials.

  12. HARI says:

    Hi Per-Erik ,

    you have written a great tutorial in opengl es2.0.. Really its very useful for me.

    now am doing a task for panning functionality in opengles2.0 in android. am struggle here. still i have not get any idea about panning. i reffered in stackoverflow also. this is the link..
    gamedev.stackexchange.com/questions/48372/all-of-my-matrix-functions-not-working-opengl-es-2-0

    but, i did not understand for this.. can u please give some panning functionality working programs in opengles2.0 in android..

    i am waiting for your reply.. i hope you will help us…

    Thanks Advance
    HARI

  13. Jason says:

    Ok ive gotten it working, thanks so much.

  14. Jason says:

    also mGLView.setPreserveEGLContextOnPause(true); comes back with an error when compiled. not sure how to fix this? There is very little online help with regards to OpenGL ES2.0. :(

    • Per-Erik Bergman says:

      The setPreserveEGLContextOnPause function is only available from API level 11. Check if you have at least that.

  15. Jason says:

    Im a little confused, as there is a Util class that is in the import for GLRenderer but you havent mentioned it. can you publish the util.class file contents?

  16. darrin says:

    Glad to have found this site…thank you!

  17. Christoph Brill says:

    Nice introduction! Only found two slight typos: The init() and draw() methods in GLES20Renderer should be named onCreate() and onDrawFrame().

  18. [...] I have started a new updated serie of tutorials on OpenGL ES 2.0 for android. Check them out at: OpenGL ES 2.0 [...]

  19. [...] I have started a new updated serie of tutorials on OpenGL ES 2.0 for android. Check them out at: OpenGL ES 2.0 [...]

  20. [...] I have started a new updated serie of tutorials on OpenGL ES 2.0 for android. Check them out at: OpenGL ES 2.0 [...]

  21. [...] I have started a new updated serie of tutorials on OpenGL ES 2.0 for android. Check them out at: OpenGL ES 2.0 [...]

  22. [...] I have started a new updated serie of tutorials on OpenGL ES 2.0 for android. Check them out at: OpenGL ES 2.0 [...]

  23. [...] I have started a new updated serie of tutorials on OpenGL ES 2.0 for android. Check them out at: OpenGL ES 2.0 [...]

    • Eric Yu says:

      Good stuff for OpenGL ES 2.0 on Android, thank you.
      When I run this smaple on android emulator, it failed.Because there’s a bug with the emulator such that this line: “final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0×20000;” does not work. It will always return false. You can add “|| Build.FINGERPRINT.startsWith(“generic”)” or simply comment out these checks and assume that OpenGL ES 2 is supported, when running on the emulator.
      refer to http://www.learnopengles.com/android-emulator-now-supports-native-opengl-es2-0/

Leave a Reply