NeHe Android Ports

NeHe Android PortsAs Android supports OpenGL ES, I wanted to provide the basic and probably most read OpenGL tutorials available for the Android platform. The NeHe OpenGL tutorials are what every OpenGL starter is beginning with or pointed at. The set of nearly 50 tutorials give an overview about OpenGL functions and principles and are easy to understand and to be converted to the own needs. They are already available in many versions, many different programming languages (e.g. C#, D, Java) as well as for many frameworks (e.g. JOGL, REALBasic).

I ported/am porting the original tutorials to the Android platform, adapted to the specifics and requirements and in a somehow more Object-Oriented way. Some specifics and requirements given from the OpenGL ES Android implementation require changes such as

  • glBegin/glEnd is a common way to immediately draw something to the OpenGL screen and permanently used in the NeHe tutorials. But as these are not supported on the Android platform, everything will be handled by Arrays (Vertex, Indices, Colors, Textures Coordinates). Anyway, we are still immediately drawing these, but for future tasks and buffer binding on GL11 supporting devices, this is the basic way to go, therefore the change should be seen as an advantage (Anyway, glBegin and End will drop out of the OpenGL Specification).
  • GL_QUADS are not available. Therefore, in correlation with the used Vertex and Index Arrays most things will be drawn with GL_TRIANGLES, which again is no direct disadvantage.

and some more things. Overall, I try to keep everything as near as possible to the NeHe source and comments, so that everybody can use these sources with the description of the original tutorials. Additional elements and structures added for a better utilization, visibility, style and organisation are commented by myself here on this page as well as in the source code itself. If questions occur, please comment to this page.

Please note that the source is a mere port and is not necessarily best practice or for best performance. It is just a plain port to show how to accomplish the original intend on the Android platform. This source has been developed and tested with the Android 1.5r3 SDK in an Eclipse 3.5 environment. All ran fine on the provided emulator.
Not every little aspect of Android or Java is explained. You should now how the basics work to understand the lessons.

The ports are now also available on GitHub.

In this very first tutorial you will get a quick overview where to get all you need (of course, depending on your personal preferences you have to adapt the tutorial) to start developing Android applications.

NeHe Android Lesson 02

In this first OpenGL tutorial you will see the basic structure to initiate an OpenGL View on an Android system. It contains four classes: One Runner, to base the activity on (will be nearly the same for each lesson), the OpenGL View and the two objects which are drawn. Both objects are properly separated but resemble the same structure to be drawn by vertex buffers. As mentioned, this should be the preferred way and could also be used as an initial idea for a later game entity design structure.
Note: As JoshuaFalken pointed out it is to note that by creating the GLSurfaceView and setting the renderer the drawing process is continously. This means you do not have to make any loop yourself. While in most cases this is what you want, to draw all the time. If you need or want to do it on your own you can set the render mode to RENDERMODE_WHEN_DIRTY. By that you would have to requestRender on the GLSurfaceView by yourself. You can read about it here.
Changes regarding NeHe: The biggest changes to the original tutorial come from the Android platform and classes structure. Everything is separated into its own classes (Renderer, Triangle and Square), as well as the objects are drawn by Vertex Buffers (see remark above). The init, resize and draw methods are nearly the same but they refer to the respective instanced objects of the Triangle and Square. In addition to fit the normal up-side screen layout I changed the location of both to be among each other.

Original Lesson 02

NeHe Android Lesson 03

In this lesson you add colors to the objects. The triangle gets colored with with a gradient and the Square is colored in blue.
Changes to previous: The changes are only made in both object classes, Triangle and Square. In only one line has been added to the draw method, which defines the color before drawing. The does not only draw one color but many. These are again defined by values in a buffer like the vertices. The values are based on RGB and luminance. In the draw method this buffer is also added like the vertex buffer and the mapped colors are drawn according to their order.

Original Lesson 03

NeHe Android Lesson 04

Now that we have colored Triangles and Squares we need to spin these round n’ round. Whoohi^^’!!! In this tutorial you will add rotation to both objects.
Changes to previous: Only the method onDrawFrame(GL10 gl) in has been altered. Before we draw the Triangle and Square we rotate the drawing matrix. A dynamic value, which is increased in each drawing round ensures that our objects start spinning. Between both drawing procedures we reset the matrix by calling gl.glLoadIdentity(). This is very important, otherwise the following translation and rotation is based on the position set through the previous translation and rotation. Just try and comment that line. Funny results ^^°!

Original Lesson 04

NeHe Android Lesson 05

In this tutorial you will enter another dimension: The THIRD! based on our Triangle and Square you will create the three-dimensional representation of these. Therefore, we change the Triangle to a Pyramid and the Square to a Cube.
Changes to previous: The biggest changes are done to our objects. We converted and extended both to three-dimensional representations. If you have a look at the Cube and Pyramid class you will notice that they resemble the structure of the Square and Triangle. We just added additional vertices and indices to the Cube. It is important to notice the difference between e.g. Square and Cube to understand how to draw and how to create objects. The Cube uses as mentioned indices to gl.glDrawElements itself. To understand the indices it is important to understand a cube. A cube has 8 vertices, 12 edges and 6 faces. All faces share different vertices and this is what we want to use to our advantage. If we draw a cube we would have to put every vertex in the array and so that the drawing function can follow the vertices to conclude in surfaces. Now, we just define the 8 vertices a cube has overall and put them in “drawing order” through our indices. The values in the index buffer are to be seen as pointer to the defined vertices. 0 for the first, 1 for the second and so on.
Note: Please note that the Pyramid has no “base”. In the original NeHe tutorial this was not needed because of the perspective. But as I altered the code to fit the normal screen layout you can see into the Pyramid. I was too lazy to add the floor but you could add it to test and see if you understood the lesson.

Original Lesson 05

NeHe Android Lesson 06

In this tutorial we will concentrate and continue with the Cube. We step away from the psychedelic colors and add a texture. In honour of the original tutorials I keep the original texture.
Changes to previous: Some small changes are in where there were some variables added, 2D textures are enabled (gl.glEnable(GL10.GL_TEXTURE_2D)) and the texture is loaded in the Cube class. The biggest change experience the First of all the color array was replaced by the texture array, which contains the texture mapping coordinates. Therefore, instead of the color array the texture array is enabled in the draw method (gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY)). You will notice much more vertices than before. This results from the fact that we do not want to color them but to texture them. Now, if we use vertices for more than one face the texture mapping becomes inconsistent. Therefore, each “real” face vertex has been defined and the according texture mapping with one mapping per vertex. There are possible cases where texture mapping with shared vertices can work but not with this cube. The biggest extension to the Cube class is the loadGLTexture method. It combines the OpenGL texture generation with the Android resource loading possibilities and shows best the advantages and possibilities Android can provide for such a development.

Original Lesson 06

NeHe Android Lesson 07

In this tutorial we change our texture, add texture filters, lighting AND controls.
Changes to previous: Several changes have been made to the Run, Cube and Lesson07 classes. The now defines light arrays for ambient, diffuse and position values and converts these into the buffers in the constructor. What can be noticed here also is that the constructor sets itself as renderer, what was done before in the Run class. If you look up in the class you will see that I changed the class from a Renderer to a full GLSurfaceView, Renderer and some InputListener. The Run class now only instances the Lesson07 and sets it as content view. I have changed this because of the input functionality in this lesson. It is quicker and easier to implement a change of values in the same class these are used and drawn. It is no best practice as you should really use a real input manager for yourself, but to keep it simple to understand and near to the original I chose this way. When the surface is created a OpenGL light is created. This can be enabled through input and a flag queried in the draw method. The Cube class is nearly the same but it got another array (yes, another one): Normals! Please refer to the Wikipedia entry for further information about normals. We need them, otherwise OpenGL would not know how to work with the light if it hits the surface. The buffer is enabled and added as the other ones. Everything common here. But the Texture loading method has changed a bit as different filters are now created: Nearest, Linear and Mipmapped. Nearest and Linear are just different in flags but the mipmapping needs some changes. Please refer to this post of me, where I described it in more detail. But overall the probably biggest change to the NeHe tutorial are the controls.
Controls: As first lesson this one has controls to control what should happen on the screen. The emulator has a keyboard but I wanted to also use this lesson to give away some InputHandler basics. Therefore, I converted all controls of the original tutorial to the Touchscreen and D+Pad. The controls are:

  • D+Pad: Acceleration in the respective direction
  • D+Pad Button: Change the filter
  • Touchscreen: Control the Box by spinning it according to your movement on the touchscreen
  • Upper Touchscreen: From left to right you can zoom in and out by moving on the screen
  • Lower Touchscreen: By clicking in the lower part you can enable and disable the lighting

The implementation is done in the Lesson07 class as mentioned. It is pretty straight forward if you know the listener principles in Java. We catch key and touch events and interpret these to set the according variables in our code (that is why I wanted to have Renderer and Listener in one class). It should be self-explanatory, but a very important point is done in the constructor. By setting it focusable in touchscreen mode and requesting the focus the D+Pad is catched for that Activity. Always ensure this.

Original Lesson 07

NeHe Android Lesson 08

In this tutorial we again change the texture and enable blending for the textures.
Changes to previous: There are not that many changes to this lesson as it only sets and enables blending in the Lesson08 class with the according flags and method to blend in-between textures.
Controls: The controls are the same as in the previous lesson but the lower touchscreen has been split into left and right

  • Lower Touchscreen LEFT: By clicking you can enable and disable the blending
  • Lower Touchscreen RIGHT: By clicking you can enable and disable the lighting

Original Lesson 08

NeHe Android Lesson 09

This tutorial slightly leaves the previous tutorials and shows how to move and blend textured objects in our 3D space.
Changes to previous: Basically, you will find much same code as before, as I kept the basic structure to have everything as clear as possible. Two bigger changes have been made: Now, there is a Stars and a Star class. The is basically the textured object class representation of one single star. It has the vertices and texture coordinates, handles to draw itself. The Stars class is instanced and called by our renderer and initiates the star texture once, sets random colors and iterates through all stars. This can show how a possible “world” representation could call its sub-objects. In the Lesson09 class you can change the number of stars or for example change glBlendFunc to see which effects occur. This may help to understand blending.
Controls: The controls are just:

  • Lower Touchscreen LEFT: By clicking you can enable and disable the blending (just looks funny ^^)
  • Lower Touchscreen RIGHT: By clicking you can enable and disable twinkling

Original Lesson 09

NeHe Android Lesson 10

This tutorial is different from the ones before as it does not only show a geometric object but allows you to move through a 3D world.
Changes: The changes here are basically additions. The drawing and rendering is pretty similar to the NeHe Android Port structure before. But this time, we do not define the vertices etc. by hand, but read these from a text file. Therefore, the World class is a representation of a World, based on what has been read from the world.txt file. The biggest additions are made here, in the World class. The text file is interpreted and the controls are moved here. The controls are similar to the original but converted to the Android platform.
Controls: The controls are moving by pressing the D-Pad or your arrow keys on the keyboard. In addition you can look up and down and turn around by scrolling on the touchscreen. The texture filter can be changed with the D-Pad Center button and by pressing

  • Lower Touchscreen LEFT: By clicking you can enable and disable the blending (just looks funny ^^)

Original Lesson 10

NeHe Android Lesson 16

This tutorial is based on tutorial 07 and adds fog.
Changes to lesson 07/08: The changes to Lesson 07/08 are minimal and are just in the Lesson16 class. In the beginning we define specific fog color, mode and filter variables. In onSurfaceCreated() we set the OpenGL Fog settings and in draw check which fog mode filter should be used. The listener onTouchEvent() now checks for presses in the lower left and changes the fog mode accordingly.
Controls: The controls are the same as in Lesson 07/08 but

  • Lower Touchscreen LEFT: By clicking you can switch the fog mode

Original Lesson 16

…more to come…

I hope these ports can help at least some people trying to figure out the platform. If you like it, have questions, are mad at me or you have ideas for improvement, please let me know. The comments are open!

181 thoughts on “NeHe Android Ports”

  1. Very nice! 🙂

    I was thinking of converting some of the NeHe tutorials myself (while learning OpenGL ES), but it seems you beat me to it. I dont complain, though…

    Now i can just learn from your code – *evil cackle*

    Keep it up!

  2. Hi!

    Must say that this is excellent. I’ve been looking for good OpenGL Android tutorials.

    I have one question regarding OpenGL and Android.

    how do you do to convert the screen touch coordinates to OpenGL coordinates?

    Could you maybe add an example of that to the list of tutorials?

  3. Thanks lot Ante.

    One question.

    I can see the the gluUnProject takes Offset parameter. What kind of values exactly do I put there. I have seen that it looks a bit different from the normal gluUnProject used.


  4. First of all, Hi ^^

    The thing with gluUnProject is tricky at the moment. It is THE method to use, BUT (the big butt) it awaits the current matrix, which actually cannot be read from OpenGL ES 1.0. This is actually a big problem also for other things…

    Again but, you could have a look in the Android SDK ApiDemos and the classes of MatrixTrackingGL and others. There is code which computes its own matrix in a GL Wrapper. It could be used for such things. It is a set of three classes I think.
    There are some tries from users, e.g. here:
    I would probably go with the MatrixTrackingGL. But you should always have in mind that the computation of the matrix does not necessarily resembles the original current matrix. There seems to be a difference between the computational and original. But anyways I tried it once and it worked fine for me. So you would have to test what does not work correctly.
    Anyway, another way would always be to just take the screen coordinates from a touchevent and convert it through a e.g. raycast to OpenGL coordinates and what it hits.


  5. Thanks a lot!

    What I can’t understand is why is gluUnProject included in the API’s if it is not working as it should?

    Maybe a simple example how to solve this would be perfect. I think lots of people would enjoy it.


  6. Hi

    As some of the GL11 methods it is just already there to prepare also the device manufacturers for what is coming. It WILL be someday fully used and supported, but not at the moment. The same with GL11, it is already there, some methods and flags even do work, but not all methods work (some throw NotImplemented Exceptions) and you cannot rely on these as the devices do not necessarily have to support them. That for example is a reason why I posted this two-way solution for mipmaps: One for GL11 and one for GL10.

    Now, for glUnProject there is no specific example possible and actually I would not use the method at the moment. The Matrix hack, which is needed as parameter, is not 100% correct and the “get” Functions needed from GL11 are not supported at the moment.
    I know this may not be a satisfying answer but that is the current state, Even if the method is there. Any “example” given would not be the same on any device, possibly even computer. Therefore, the method should not be used possibly until Android SDK 2.0. And even then it has to be seen how the devices integrate the functionality.
    It is just to understand that the API is just laid-out and not fully implemented yet. That’s how it is. Have a look at the .net Compact Framework and you will find a whole bunch of methods like that. I know its not great but unlike .netCF we can hope for Android and Google to constantly upgrade and better the API. The jump from 1.0 to 1.5 was already a very big one with many changes and additions.

    So, I try to motivate you by: Hold out on Android and the SDK and at the moment try some other things to solve your specific problem. That’s all I can offer at the moment. Sorry…


  7. Hello.

    In Lesson7, the mipmapped filtered cube is all white. I read your post about mip-mapping and tried the different methods. The GL11 implementation doesnt work for me and neither does the modified buildMipMap function. Still a white cube..

    Any ideas?

  8. Hi

    Do you tried the lesson with the emulator or on your phone? If, which phone do you have? You also tried the pixelation by hand, which was suggested in my post but is not on this lessons code?

    I have a HTC Magic and tried everything on that phone as well as the emulator. I also had problems with white cubes but I got around it with pixelating the bitmaps myself. Maybe this helps.

  9. Hi.

    I have a HTC Hero.

    I get a white cube with all three implementations:
    * GL11 (and i made sure it stepped to this code)
    * buildMipmap (GL11 commented out)
    * buildMipmap (with pixelation part added)

    In the emulator the GL11 implementation works, but not the original buildMipmap function (without the pixelation part).

    What to do ? 😛

  10. On another note.

    Is there any interest in starting an #android-opengl or #android-opengles channel on FreeNode?

  11. Hi Ante

    I am currently on a trip and will be home at saturday evening again. Therefore, I will have a look at the problem at sunday.

    Hope this is ok.


  12. Heya.

    I managed to fix the buildMipmap function (at least for me). It now works in the emulator and on my HTC Hero.

    A problem i noticed with Bitmap.createScaledBitmap is that it returns the new bitmap in RGB_565 format. The original bitmal was in ARGB_8888 format. I dont know if this is good or bad, but i added some code to make sure the scaled bitmaps are ARGB_8888 as well.

    The cube was rendered slightly blueish, so I converted each pixel in the bitmap from ARGB to RGBA, before storing them in the buffer. This solved the “blueish” problem for me and i got a lovely mip mapped cube without any flaky pixels 🙂

    Here’s the function:
    private void buildMipmap(GL10 gl, Bitmap bitmap)
    int level = 0;
    int height = bitmap.getHeight();
    int width = bitmap.getWidth();

    while(height >= 1 || width >= 1)
    ByteBuffer bytebuf = ByteBuffer.allocateDirect(height * width * 4);

    for(int y = 0; y < bitmap.getHeight(); y++)
    for(int x = 0; x > 16) & 0xFF);
    byte green = (byte) ((pixel >> 8) & 0xFF);
    byte blue = (byte) (pixel & 0xFF);
    bytebuf.put(new byte[] {red, green, blue, (byte) 255});


    gl.glTexImage2D(GL10.GL_TEXTURE_2D, level, GL10.GL_RGBA, width, height, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bytebuf);

    if(height == 1 || width == 1) {


    height /= 2;
    width /= 2;

    // Bitmap.createScaledBitmap creates RGB_565 bitmaps by default. Convert to ARGB_8888.
    Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, false).copy(Config.ARGB_8888, false);

    bitmap = bitmap2;

    Does it work on your device(s) ?

    Best regards

  13. Hi

    You are right with the ARGB problem. I actually read about it but totally forget/ignored the fact. I have of course the same effect on my Magic, maybe I justed started it when I was testing. I do not know anymore, as I made the lessons pretty in parallel.

    I will correct the lesson and upload the new version this week.

    Many many thanks for the remark!!!

    I am sorry I was a little quiet, but I will also upload another tutorial port soon which shows basic Shadowing, which I think is another rudimentary but nice to know feature.


  14. Wow, thanks, I think that your port of lesson 6 is great and very clean.

    I’ve tried many other OpenGL ES texture mapping snippets+tutorials, and am having flickering problems on Android.

    I believe this is because I issue many calls to glDrawElements(), whereas you call this method only once at every draw iteration.

    This may also come from the fact that I’m putting different, rather large, textures on each side of the cube.

    I would however like to try and use my 6 different textures, but do a single call to glDrawElements() as you do.

    How can I achieve this ? Your unique call to glBindTexture() before settings all coords makes it non-obvious to me… Whereas the original lesson 6 was very easy to adapt for multiple textures.

  15. Hi there

    First of all, flickering does not necessarily has to be connected to draw calls but to other elements like syncing or sometimes dithering etc. But overall you are right: draw calls should be a minimum. That’s a pratical OpenGL issue. draw calls, translations and bindings should be minimized in the code. Therefore, a good own scene management can help to achieve this and reduce the calls.
    Now if you already know what textures you want to use and on what object it could be ise to combine many textures to one and use offsets for the texture coordinates to map the different textures to the object. This is always a good way, also to reduce the amount of files and therefore loading.


  16. Thanks a lot for the amazing tutorial which is really helping me in learning Open Gl real quick. Just one help, I compiled the lesson 10 in the eclipse and i am getting an error for onKey & onTouch method in

    The error is that the above methods (onKey & onTouch) of type World must override a superclass method.

    However I could see the “@Override” keyword in the two methods.

    Could you please help with this.

  17. Hi baleshn

    This is normally an error of the compliance level set up in e.g. Eclipse. For Java5.0 it is that the @Override annotation may only indicate the override of a class method, whereas since Java6.0 compliance it may also be annotated for interfaces.

    Therefore, if you are using Eclipse: Have a look at the Project Properties -> Java Compiler -> Compiler compliance level. This should be 1.6. If you do not want to change this setting just remove the @Override Annotations in the source from me. They are not necessary to compile and run it.

    I hope this helps.


  18. Great ports!

    In the “Lesson 06: Texture Mapping”, when loading a Bitmap:

    InputStream is = context.getResources().openRawResource(R.drawable.nehe);
    Bitmap bitmap = null;
    try {
    bitmap = BitmapFactory.decodeStream(is);
    } finally {
    try {
    is = null;
    } catch (IOException e) {

    I prefer using:

    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.nehe);

  19. Hi juande

    That’s also a fine way. What I did is more of a larger chunk if anything more is wanted. For example, personally I have normally all my resources in the res/ folder and work with the resourceloader instead of R and drawables. Therefore, just personal preferences…

    …but I like one-liners ^^’


  20. Awesome suggestion NeA and yes it got fixed and I am amazed with your response !!!! You Rock !!!

  21. You rules! I’m starting learning OpenGL-ES and this is a great help. Thank you very much for your work.

  22. Thanks for putting up the tutorials, this has been a big help.

    I noticed that you set the gl.glFrontFace(GL10.GL_CW), but the tutorials have the vertices counter clockwise. If I turn on culling, this could be important. By default it looks like front face is set to GL10.GL_CCW.

  23. Hey HeyYou ^^

    Yes, you are right and regarding culling you should definitely see into it. Basically why it is still in the lessons even is not needed is because of classic oldskool copy and paste of my very first Android OpenGL class I read. ^^’
    So, in these lessons it is neither needed nor respected by the code besides, but for cases like starting culling it is important. But this is also important if you start reading larger chunks of vertices through any means of file formats then. And yes, standard should be ccw.


  24. Thank you for providing these very helpful tutorials!

    I have a question about Lesson 04: How is the redraw for the animation actually triggered? In most windowing toolkits / frameworks I know, the redraw of the OpenGL window has to be triggered explicitly somehow. However, I cannot find any such code in the Android port. Does Android simply redraw the screen continuously?


  25. Just to reply to myself here…. found the answer. GLSurfaceView.setRenderMode(). By default chooses continuous rendering. This is the ONLY windowing / UI toolkit I have ever seen both in the desktop and mobile space which by default keeps redrawing the GL surface whether there are graphical updates or not.

    From the docs:
    “Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance by allowing the GPU and CPU to idle when the view does not need to be updated.”

    Haha… I would think so!

  26. Hi

    Yes, this is a functionality added explicitly to Android1.5 allowing to constantly or redraw by request.
    The main thing here to be noted should be that OpenGL itself is not necessarily a windowing toolkit and in other cases OpenGL is also constantly redrawn but not by the UI toolkit but another threading manager. Whether its good to have this way or the other way round can be discussed. But the Android Blog says it pretty right: Most OpenGL need constant redrawing, therefore why don’t do it automatically. And for the others, use another rendermode, as you pointed out and requestRender yourself.
    Of course it is possible and can be considered to do it like that all the time and handle the drawing loop yourself for e.g. fixed framerates. But this was no real part of the tutorials and can be discussed ALL DAY LONG ^^’

    Best regards

  27. Hello!

    Thanks for the reply. I didn’t mean to critize Android or the demo code. It’s just that I’ve worked with OpenGL for around 10 years and with various windowing toolkits – GLAux, GLUT, fltk, Qt, SDL, and also recently OpenGL ES on the iPhone. I don’t think I’ve ever encountered any toolkit which by default permanently triggers a redraw. Not to start a pointless debate about the wisdom of this – it is true that maybe 90% of the applications need a constant redraw anyway. I am just wondering whether it would make sense to add a comment explaining this to the info box of lesson 04, as I am sure other people moving to Android from different OpenGL environments might be confused initially, too.

  28. Hi

    No no, I didn’t take that as offence. Your point is totally right. The idea to add it to the info box is good. I will reconsider it and how to add it there and think update the text. Hopefully this weekend, as I also have a Shadowing tutorial I want to publish.

    Best regards

  29. Yes furrykef, your remark is correct and important.

    Passing “this” is not necessarily wrong, and in case of the tutorials a minor, but you are right as the important thing is, it ‘can’ cause memory leaks.
    getApplication() is definitely the way to go if you want to program something bigger. I just used ‘this’ as I was “lazy” and just wanted to port the tutorials and never cared about the basics especially regarding Android Apps.

    Thanks for the point and in future ports I am already changing this.

    Best regards and Thanks again

  30. Hi, NeA, thanks for your website that is helpful for me to learn OpenGL in android. I have a problem that when I try to put a bitmap into OpenGL, and I used the example of Lesson 06, but this bitmap doesn’t show. This will happen only on Android 2.1, and this bitmap’s width and height are not the same, but I don’t know how can I fix it. Can you help me to know where the problem is and how to fix it?
    Thanks a lot for your help.

    Best regards

  31. Excellent tutorials. I will continue to reference these tutorials as I also learn OpenGL ES on Android. Kudos to you.

  32. First of all, thank you for taking the time to port the very useful NeHe OpenGL tutorials.
    I’m new to Android and OpenGL, but thought it would be a good place to start.
    I can’t but notice though, that in Lesson 7 using normals, you define 24 normals. To my best understanding, a normal is based on a polygon and not a vertex, whereas 12 normals should be enough (12 triangles, 12 indices)?

  33. Hi there

    That is a good point and basically the biggest flaw in the ports: My Laziness! ^^’
    As I comment in the source with the normals, these are nearly purely random. Sorry about that. You do not necessarily need 12 normals, it depends on the faces. For example if we would draw quads instead of triangles you could draw a cube with six faces and six normals. But basically you are correct: A normal is calcualted for a face.


  34. Hi wanted to know if you could do the llesson10 moving camera and moving the world

  35. Hi Pablo

    I do not exactly know what you mean? Lesson 10 is above in the ports. Do you want something else specifically?


  36. This is excellent. Helped me a lot.
    Waiting for more to come.
    Thanks a lot.

  37. Great!
    All lessons work on Acer Liquid E, if you select API2.1 as destination in the project settings.

    Thanks a lot!!!


  38. Nice tutorial, very useful for starting OpenGL development on the Android platform.
    Thanks a lot!


  39. Fantastic tutorials! I have one question though with regards to Lesson 9. In Lesson 9, there is only one star bitmap that is dealt with. Suppose I want to deal with more than just one bitmap (e.g. A program similar to lesson 9 that deals with bitmaps of squares, triangle, circles all being drawn in that spiraling pattern), what do I need to do in order to achieve this?

  40. Thanks for the port of the examples – as a newbie I’m sure they will be very helpful. Surprised you don’t come up more often in Google searches!

  41. Hi All,
    I show my idea :
    – I want to load an obj file a skeleton
    – I want listen the touchevent to see the move around the skeleton
    That’s ok. But :
    – I want to interact with it to color a bones. I have no idea to convert the screen coordinate in my object world coordinate and furthtermore how to know which face to colorate …
    Any idea will be welcome. Thx

  42. i have a question:how to get the modelview matrix ande projection matrix of OpenGL es? thank you evry much if you could give some code.

  43. First I want to say thanks for the tutorials, they are extremely helpful!

    But now for some errata:
    In your tutorials, you refer to the 4th float of each vertex in the color buffers as ‘luminosity’. It’s actually alpha, which refers to transparency. Changing that vertex won’t make it any darker or brighter.

  44. Hi

    Thanks for the hint. You are absolutely right that it is the alpha. Maybe in my “german foolishness” I just wanted to sound cooler because alpha is maybe not directly understood, but transparency would be the better alternative.

    Thanks for that

  45. I LOVE YOU! 🙂

    Would be great to see some tutorial about loading some 3D files/scenes etc. But any new tutorial will be very appreciated. Thanks for these 🙂


  46. I love you lol. As he said. On my way to making my first game.. it might be 3D 😮

  47. This is so cool..i have been looking for android opengl es code for newbies for days..

  48. Thanks for converting these tutorials to Android. That is quite an accomplishment! I wonder why the NeHe site does not include these alongside the other languages? I have been a big fan of the NeHe tutorials for years. When I first started Android development I looked your site, but I didn’t hover the mouse over the links to the Android code and instead when I clicked on the blue links they sent me to the NeHe site and I downloaded the java tutorials which didn’t work. Stupid me! For the last few days I’ve been banging my head against some of the crappy ApiDemos trying to get them to work and came across your site again and this time found the real code, thank heavens. Also, the names on the icons need to be shorter because the all say the same thing on my LG phone:

    Android Le…

    Keep up the good work!

    P.S: Also It would be awesome if anyone could convert NeHe’s lesson 36 to Android. That code really shows how bad OpenGL drivers have gotten lately…

  49. it is awesome tutorial, thanks for it

    but i have a very deep problem in compressed texture usage,
    can you help

  50. Hi. Thanks for the tutorial. However, when I am running the project files all I get is an android emulator with ‘Android_’ splashed on the virtual screen. There’s no graphics element displayed. No error report has been delivered by eclipse. Can you suggest a solution? Thanks in advance.

  51. Hello sir,

    can you please tell me how can i change the texture image dynamically?

    Thanks in advance,

  52. Many thanks,

    This is really useful, haven’t been over the NeHe examples in a few years and this was just what i was looking for.

    Thanks for Sharing


  53. Hi, thanks for the great tutorials. in the examples for the phone the cubes continue to rotate a bit after the user releases the touchpad. What method was used to simulate this? Any chance of a quick example. Thanks

  54. @Ed
    Since the “onDrawFrame” method is continuously being called so is:

    rtri += 0.2f;
    rquad -= 0.15f;

    Since these are in the rotations:

    gl.glRotatef(rtri, 0.0f, 1.0f, 0.0f);

    The cube is constantly rotating. See source.

  55. i myself use the mosync for programming opengl for android..

    do you have any problems with the render to texture example?

    i have tried to make my own but i have huge problems when drawing back the blurbuffer
    to the screen.. there is a lot of weird errors in the texture..

    it is supposed to be 32bit on my.Samsung Galaxy S2..
    On my old Samsung Galaxy S i have no errors..
    Anyone have any ideas what it might be?

  56. Hi!
    I see ths tutorial is written for OpenGL ES 1.1.

    I’m just getting into Android OpenGL development and I can not find the differences between OpenGL ES 1.1 or 2.0.

    Which one is better? Which one is worst? In 2.0 exists shaders which i don’t understand and drive me nuts…

    Maybe i can try to undestand this tutorials and then adapt them to OPENGL 2.0….

    Sincerely i don’t know what to do at all….

  57. Hi Sergio

    In general I wrote them for OpenGL ES 1.1 because at that time it was the Android State-of-the-Art (not even JIT ^^’). In general ES1.1 and ES2.0 are totally different. 2.0 follows a different approach (the shader approach as you noted). Besides that it has several additional functions and options not even available or emulated in 1.1. You can pretty much say 1.1 is old and becoming outdated and 2.0 is for the future as it also is more oriented to be similar/compatible with the “normal” OpenGL branch and development.

    I want to add some NeHe ports based on OpenGL ES 2.0 but I am totally out of time at the moment.

    But in general I would support maybe for you if are totally new to get into these tutorials and then try to port these or even try other things. A good start would also be to have a look at iPhone tutorials as these support ES2.0 for a longer time already.

    I know it may seem a little complicated because it is a pretty big paradigm shift, but if you want to continue in that direction you have to adept ES2.0.


  58. u r great! thanx alot .

    but i m finding a code to draw a sphare or torus king of designs.if u can show some code for tht too,ll be even greater.

  59. This is going to sound really dumb, but how do I open these projects? I can create my own android projects from scratch, but don’t know how to open these once unzipped. thanks

  60. ok ignore last post, managed to open it (In eclipse go to File->Import. Select ‘Existing projects into Workspace’ under the general tab and press next. Then Select Archive File and choose the zip file you downloaded.)

  61. These are all nice tutorials, but if they build on Android 1.5, then they are not much help for OpenGL ES 2.0.

    Now I realize it would be a lot of work to rewrite them in 2.0, so instead of asking for that, could you at least give us some nice guidelines for how to do the same things in 2.0? Perhaps with references to 2.0 sites and a list of hints on how to do the translation?

  62. Can any one give an example on how to add a glow effect to any of these examples? any help would be much appreciated, thanks

  63. Wow, as soon as I saw NeHe in google search I remembered the old tutorials I had read a few years ago. I’ve been wanting to learn android development. Thanks a ton.

  64. Your tutorial are very useful, thanks so much.
    I expect your more tutorials in the future.
    Come on!

  65. It is too useful to the beginners. if possible please provide some sample game tutorial..

  66. ty very much. this is actually the first thing that really helps me.
    the source code is awesome and understandable.
    Why isn’t this up on the original NeHe Page ?

  67. Thank you so much for this tutorial..!! I am beginner in openGL and I found it so helpful..
    I´m wondering… Do you have an Augmented reality example on android.. Something for begginers…??

  68. Dude. I am so glad that google direct me to ur web page . it has solve a hug problem of mine working with Open Gl and was trying to port the openGL SDL on android but ur lesson 10 made it all.. Bless you

  69. Um do you think u could add anons modles like people plz cause then its boring but still fun confusing huh oh and not bad ones I’m still 12 years old so no bad ones k

  70. Hi,

    I launched lesson 7 and the lighting didn’t appear well on the cube.
    I guess it’s because the normal vectors are wrong.
    I tried with the following array and it seems to work well:

    private float normals[] = {
    0.0f, 0.0f, 1.0f,
    0.0f, 0.0f, 1.0f,
    0.0f, 0.0f, 1.0f,
    0.0f, 0.0f, 1.0f,

    1.0f, 0.0f, 0.0f,
    1.0f, 0.0f, 0.0f,
    1.0f, 0.0f, 0.0f,
    1.0f, 0.0f, 0.0f,

    0.0f, 0.0f, -1.0f,
    0.0f, 0.0f, -1.0f,
    0.0f, 0.0f, -1.0f,
    0.0f, 0.0f, -1.0f,

    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,

    0.0f,-1.0f, 0.0f,
    0.0f,-1.0f, 0.0f,
    0.0f,-1.0f, 0.0f,
    0.0f,-1.0f, 0.0f,

    0.0f, 1.0f, 0.0f,
    0.0f, 1.0f, 0.0f,
    0.0f, 1.0f, 0.0f,
    0.0f, 1.0f, 0.0f

    Basically I used the same normals for all vetices on a given face.

    Can someone confirm these are the correct normals ?

  71. Here’s a bug inherited from theNeHe tutorials on textures mapping that could waste a couple days of your life!

    If you leave glEnable(GL_TEXTURE_2D) in the onSurfaceCreated (previously InitGL), every pure white polygon you display afterward will be tinted with some other color!

    This must not be a problem for these 36 other platforms, but it sure is on multiple Android devices:

    * DOWNLOAD Visual C++ Code For This Lesson.
    * DOWNLOAD Borland C++ Builder 6 Code For This Lesson. ( Conversion by Christian Kindahl )
    * DOWNLOAD C# Code For This Lesson. ( Conversion by Sabine Felsinger )
    * DOWNLOAD VB.Net CsGL Code For This Lesson. ( Conversion by X )
    * DOWNLOAD Code Warrior 5.3 Code For This Lesson. ( Conversion by Scott Lupton )
    * DOWNLOAD Cygwin Code For This Lesson. ( Conversion by Stephan Ferraro )
    * DOWNLOAD D Language Code For This Lesson. ( Conversion by Familia Pineda Garcia )
    * DOWNLOAD Delphi Code For This Lesson. ( Conversion by Michal Tucek )
    * DOWNLOAD Dev C++ Code For This Lesson. ( Conversion by Dan )
    * DOWNLOAD Euphoria Code For This Lesson. ( Conversion by Evan Marshall )
    * DOWNLOAD Game GLUT Code For This Lesson. ( Conversion by Milikas Anastasios )
    * DOWNLOAD GLUT Code For This Lesson. ( Conversion by Kyle Gancarz )
    * DOWNLOAD Irix Code For This Lesson. ( Conversion by Lakmal Gunasekara )
    * DOWNLOAD Java Code For This Lesson. ( Conversion by Jeff Kirby )
    * DOWNLOAD Jedi-SDL Code For This Lesson. ( Conversion by Dominique Louis )
    * DOWNLOAD JoGL Code For This Lesson. ( Conversion by Kevin J. Duling )
    * DOWNLOAD LCC Win32 Code For This Lesson. ( Conversion by Robert Wishlaw )
    * DOWNLOAD Linux Code For This Lesson. ( Conversion by Richard Campbell )
    * DOWNLOAD Linux/GLX Code For This Lesson. ( Conversion by Mihael Vrbanec )
    * DOWNLOAD Linux/SDL Code For This Lesson. ( Conversion by Ti Leggett )
    * DOWNLOAD LWJGL Code For This Lesson. ( Conversion by Mark Bernard )
    * DOWNLOAD Mac OS Code For This Lesson. ( Conversion by Anthony Parker )
    * DOWNLOAD Mac OS X/Cocoa Code For This Lesson. ( Conversion by Bryan Blackburn )
    * DOWNLOAD MASM Code For This Lesson. ( Conversion by Nico (Scalp) )
    * DOWNLOAD Visual C++ / OpenIL Code For This Lesson. ( Conversion by Denton Woods )
    * DOWNLOAD Power Basic Code For This Lesson. ( Conversion by Angus Law )
    * DOWNLOAD Pelles C Code For This Lesson. ( Conversion by Pelle Orinius )
    * DOWNLOAD Python Code For This Lesson. ( Conversion by John Ferguson )
    * DOWNLOAD REALbasic Code For This Lesson. ( Conversion by Thomas J. Cunningham )
    * DOWNLOAD Scheme Code For This Lesson. ( Conversion by Brendan Burns )
    * DOWNLOAD Solaris Code For This Lesson. ( Conversion by Lakmal Gunasekara )
    * DOWNLOAD Visual Basic Code For This Lesson. ( Conversion by Ross Dawson )
    * DOWNLOAD Visual Basic Code For This Lesson. ( Conversion by Peter De Tagyos )
    * DOWNLOAD Visual Fortran Code For This Lesson. ( Conversion by Jean-Philippe Perois )
    * DOWNLOAD Visual Studio .NET Code For This Lesson. ( Conversion by Grant James )

  72. These tutorials have a problem with losing memory on tablet but not phone:

    The following eats away the heap on the Toshiba Thrive but not on the
    LG G2X:
    byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    vertexBuffer = byteBuf.asFloatBuffer();
    I’ve tried byteBuf.clear, byteBuf.reset, making byteBuf static,
    System.gc, and combinations of these, but nothing works. I wonder why
    this is only a problem on the Toshiba but not the LG?

  73. Hello,
    i am learning it with your lessons. Thank you very much.
    I am now on lesson10. My aim is, i would like to stay in a cube, have panoramic photos from each side (bottom,top,front,behind,left,right,back).
    i could use only one texture, others does not work for me.
    what could be the world.txt? it is really confused..

  74. @andy kaya

    To make a photo-cube with several texture check example on this page:

  75. I wanted to thank you profusely for lesson 6. I have been looking for a lucid explanation of using textures on cube faces without results until I saw it. With minimal effort I had lesson 6 downloaded, imported into Eclipse, and working. Thanks to the excellent organization of the code, the mystery is now no longer a mystery. Again, many thanks.

  76. Hi,

    Thanks for the nice and useful tutorials. But I have a question, I just want to know how to visualise any of the mentioned graphics inside the camera.

    For an Example, if I want to turn the camera on and when it’s on, I want to display shapes as in the lesson05 in your tutorial.

    Any suggestions??

  77. Missed your site between March 12th, 2012 and June 23rd, 2012. Wonder what happened?

  78. as i know, there are several methods to calculate normals, just like normal of a face or a point. There is no right or wrong, just suitable or not.@bapm

  79. Finally i found a website with detailed tutorials, i can’t wait to get started, have been looking for a place to start learning about opengl and finally i found, thank you so much for all your tutorials.

  80. This site, and of course NEHE, are an absolute treasure. No book or class has ever offered the same amount of OpenGL knowledge.

  81. Great site and awesome tutorials…this is the beacon of light for all learners like me….grt job please keep the tutorials coming…:)…and thanx a tonn…these are really absolute treasure

  82. Its like you read my mind! You appear to know a lot about
    this, like you wrote the book in it or something. I think that you can do with some pics
    to drive the message home a bit, but other than that, this is wonderful blog.
    A fantastic read. I will certainly be back.

  83. I am a cse student .I have done a project on opengl where I loaded obj files and had done a shooter 3D game ..I want to port it to android ur tutorial is awsum ..can u explain how can I insert a dpad like button on the screen to control tonset the onclicklistner and bring the button on the screen…so I can play it on my tablet also.I am new to android ..I have been following nehe tutorials …pls reply.

  84. Hi,
    I really liked the lesson 10 and i made a whole new world out of it. but problem is i dont know were to put my character. I try to put my character in the world but the world always hides it… can any one help pls??

  85. Hello,
    I would like to use the lesson 6 and I do not know at all how to add a button that will serve me to trigger an action. I liked that this button follows the rotation of the cube, is that possible?
    Thank you very much.

  86. Hi,
    I am cse student.I am new to andriod and opengl.I found your tutorials to be very helpful.I had a query.In lesson 7,you have explaiined regarding zooming in/out and lighting .I wanted to perform these by interaction with the cube like touching the cube for lighting on/off and pinching in/out to zoom in/out.Any help would be highly appreciated.Thanks in advance

  87. Hey

    If you would like to have it with real object interaction, you would have to do translate the touchscreen interaction into the object space to find out if the object was touched. This is nothing that is even part of the concepts from the Nehe tutorials.
    There are options such as with GLU (especially “unproject”) which you could try, but I have no deeper experience here really. But if you google for the translation you will find much good help and many tutorials.


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

The Imagination Enhancer