Setting up an Android project for OpenGL ES 2.0 on-screen graphics rendering is quite easy using GLSurfaceView
. However, if you want to do off-screen rendering (like rendering to a texture), you need to go the long the way by manually setting up an EGL context and creating an EGL pixelbuffer (“pbuffer”) surface to render to. By this, OpenGL runs completely in the background without any visible surface or view, and will render to a pixelbuffer which you can later read back to main memory, for example by using glReadPixels()
. This is the fundament for OpenGL-driven GPGPU experiments on Android devices. This small posts explains how to do that.
I’ll explain it using native C code and the Android NDK, because that’s how I’ve implemented it in a recent project. However, EGL wrapper classes for the SDK are also available and the interface is almost the same. See this anddev.org forum post for an example on how to use the EGL SDK classes. Notice that this forum post is from 2010 and sets up the EGL context to use legacy OpenGL ES 1.x. I will show how to set up an OpenGL ES 2.0 context.
To access the EGL interface in native code, you need to include its C headers from EGL/egl.h
and link to the EGL library by adding -lEGL
to your LOCAL_LDLIBS
makefile variable. Then specify some global state variables:
We can then implement a setup function that takes the size of the pixelbuffer surface as parameters as follows:
It is absolutely necessary to set the EGL_RENDERABLE_TYPE
and EGL_CONTEXT_CLIENT_VERSION
to use OpenGL ES 2.0, otherwise you will notice that calling glCompileShader()
and other ES 2.0 functions will fail. Furthermore, you should check for errors after each egl...()
call. I just omitted here it so the example code is not too bloated.
You should also create a shutdown function to release the EGL objects again:
Call these functions at the beginning and end of your activity life-cycle, respectively. During application run-time you can now use the gl...()
rendering functions to render some graphics off-screen into the pixelbuffer. You might use glReadPixels()
to copy the rendered image data to a ByteBuffer. You can then construct an Android Bitmap from it by using Bitmap.copyPixelsFromBuffer()
.
Notice that it is very important that all calls to egl...()
or gl...()
functions happen in the same thread! When you called setupEGL()
from the main thread, then all your texture handling, graphics rendering, etc. should also be executed in the main thread.