OpenGL ES Tutorial for Android – Part II – Building a polygon

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

Previous tutorial was all about setting up the GLSurfaceView. Be sure to read it beacuse it’s a really importent one to be able to continue.

Building a polygon

In this tutorial we will render our first polygon.

3D models are built up with smaller elements (vertices, edges, faces, and polygons) which can be manipulated individually.


A vertex (vertices in plural) is the smallest building block of 3D model. A vertex is a point where two or more edges meet. In a 3D model a vertex can be shared between all connected edges, paces and polygons. A vertex can also be a represent for the position of a camera or a light source. You can see a vertex in the image below marked in yellow.


Vertices for a square.

To define the vertices on android we define them as a float array that we put into a byte buffer to gain better performance. Look at the image to the right and the code below to match the vertices marked on the image to the code.

private float vertices[] = {
      -1.0f,  1.0f, 0.0f,  // 0, Top Left
      -1.0f, -1.0f, 0.0f,  // 1, Bottom Left
       1.0f, -1.0f, 0.0f,  // 2, Bottom Right
       1.0f,  1.0f, 0.0f,  // 3, Top Right

// a float is 4 bytes, therefore we multiply the number if vertices with 4.
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
FloatBuffer vertexBuffer = vbb.asFloatBuffer();

Don’t forget that a float is 4 bytes and to multiply it with the number of vertices to get the right size on the allocated buffer.

OpenGL ES have a pipeline with functions to apply when you tell it to render. Most of these functions are not enabled by default so you have to remember to turn the ones you like to use on. You might also need to tell these functions what to work with. So in the case of our vertices we need to tell OpenGL ES that it’s okay to work with the vertex buffer we created we also need to tell where it is.

// Enabled the vertex buffer for writing and to be used during rendering.
// Specifies the location and data format of an array of vertex
// coordinates to use when rendering.
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

When you are done with the buffer don’t forget to disable it.

// Disable the vertices buffer.


Edge is a line between two vertices. They are border lines of faces and polygons. In a 3D model an edge can be shared between two adjacent faces or polygons. Transforming an edge affects all connected vertices, faces and polygons. In OpenGL ES you don’t define the edges, you rather define the face by giving them the vertices that would build up the three edges. If you would like modify an edge you change the two vertices that makes the edge. You can see an edge in the image below marked in yellow.



Face is a triangle. Face is a surface between three corner vertices and three surrounding edges. Transforming a face affects all connected vertices, edges and polygons.


The order does matter.

When winding up the faces it’s important to do it in the right direction because the direction defines what side will be the front face and what side will be the back face. Why this is important is because to gain performance we don’t want to draw both sides so we turn off the back face. So it’s a good idea to use the same winding all over your project. It is possible to change what direction that defines the front face with glFrontFace.


To make OpenGL skip the faces that are turned into the screen you can use something called back-face culling. What is does is determines whether a polygon of a graphical object is visible by checking if the face is wind up in the right order.


It’s ofcource possible to change what face side should be drawn or not.




Indices for a square.

Time to wind the faces, remember we have decided to go with the default winding meaning counter-clockwise. Look at the image to the right and the code below to see how to wind up this square.

private short[] indices = { 0, 1, 2, 0, 2, 3 };

To gain some performance we also put this ones in a byte buffer.

// short is 2 bytes, therefore we multiply the number if vertices with 2.
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ShortBuffer indexBuffer = ibb.asShortBuffer();

Don’t forget that a short is 2 bytes and to multiply it with the number of indices to get the right size on the allocated buffer.


Time to get something on the screen, there is two functions used to draw and we have to decide which one to use.

The two functions are:

public abstract void glDrawArrays(int mode, int first, int count)

glDrawArrays draws the vertices in that order they are specified in the construction of our verticesBuffer.

public abstract void glDrawElements(int mode, int count, int type,
                                    Buffer indices) 

glDrawElements need a little bit more to be able to draw. It needs to know the order which to draw the vertices, it needs the indicesBuffer.

Since we already created the indicesBuffer I’m guessing that you figured out that’s the way we are going.

What is common for this functions is that they both need to know what it is they should draw, what primitives to render. Since there is some various ways to render this indices and some of them are good to know about for debugging reasons. I’ll go through them all.

What primitives to render


Draws individual points on the screen.



Series of connected line segments.



Same as above, with a segment added between last and first vertices.



Pairs of vertices interpreted as individual line segments.



Triples of vertices interpreted as triangles.



Draws a series of triangles (three-sided polygons) using vertices v0, v1, v2, then v2, v1, v3 (note the order), then v2, v3, v4, and so on. The ordering is to ensure that the triangles are all drawn with the same orientation so that the strip can correctly form part of a surface.



Same as GL_TRIANGLE_STRIP, except that the vertices are drawn v0, v1, v2, then v0, v2, v3, then v0, v3, v4, and so on.


I think the GL_TRIANGLES is the easiest to use so we go with that one for now.

Putting it all togetter

So let’s putting our square together in a class.

package se.jayway.opengl.tutorial;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

public class Square {
	// Our vertices.
	private float vertices[] = {
		      -1.0f,  1.0f, 0.0f,  // 0, Top Left
		      -1.0f, -1.0f, 0.0f,  // 1, Bottom Left
		       1.0f, -1.0f, 0.0f,  // 2, Bottom Right
		       1.0f,  1.0f, 0.0f,  // 3, Top Right

	// The order we like to connect them.
	private short[] indices = { 0, 1, 2, 0, 2, 3 };

	// Our vertex buffer.
	private FloatBuffer vertexBuffer;

	// Our index buffer.
	private ShortBuffer indexBuffer;

	public Square() {
		// a float is 4 bytes, therefore we multiply the number if
		// vertices with 4.
		ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
		vertexBuffer = vbb.asFloatBuffer();

		// short is 2 bytes, therefore we multiply the number if
		// vertices with 2.
		ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
		indexBuffer = ibb.asShortBuffer();

	 * This function draws our square on screen.
	 * @param gl
	public void draw(GL10 gl) {
		// Counter-clockwise winding.
		// Enable face culling.
		// What faces to remove with the face culling.

		// Enabled the vertices buffer for writing and to be used during
		// rendering.
		// Specifies the location and data format of an array of vertex
		// coordinates to use when rendering.
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0,

		gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
				  GL10.GL_UNSIGNED_SHORT, indexBuffer);

		// Disable the vertices buffer.
		// Disable face culling.


We have to initialize our square in the OpenGLRenderer class.

// Initialize our square.
Square square = new Square();

And in the draw function call on the square to draw.

public void onDrawFrame(GL10 gl) {
		// Clears the screen and depth buffer.
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT |

		// Draw our square.
		square.draw(gl); // ( NEW )

If you run the application now the screen is still black. Why? Because OpenGL ES render from where the current position is, that by default is at point: 0, 0, 0 the same position that the view port is located. And OpenGL ES don’t render the things that are too close to the view port. The solution to this is to move the draw position a few steps into the screen before rendering the square:

// Translates 4 units into the screen.
gl.glTranslatef(0, 0, -4);

I will talk about the different transformations in the next tutorial.

Run the application again and you will see that the square is drawn but quickly moves further and further into the screen. OpenGL ES doesn’t reset the drawing point between the frames that you will have to do yourself:

// Replace the current matrix with the identity matrix

Now if you run the application you will see the square on a fixed position.


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

You can download the source for this tutorial here: Tutorial_Part_II
You can also checkout the code from:

Previous tutorial: OpenGL ES Tutorial for Android – Part I – Setting up the view
Next tutorial: OpenGL ES Tutorial for Android – Part III – Transformations

This Post Has 85 Comments

  1. agentorange

    This is the first OpenGL tutorial i got the first time around. I must say the 3D tube you included to illustrate Vertex, Edge, Face and Polygon was well chosen. Please keep it up. You have been bookmarked…thanksalot,–

  2. brandon edley

    Very informative. Best and most up to date android opengl tutorial I’ve seen. Can’t wait for part 3. Keep up the excellent work for us nubs.

  3. Tjerk

    Best Android + GL tutorial ever! You helped me alot with getting my game to work with opengl! Thanks a lot man!

  4. Sam

    Best OpenGL tutorial i have ever gone through. Waiting eagerly for the next one. Please let me know when will the next one get published.

  5. Per-Erik Bergman

    I’m working on the next tutorial. Hopefully, it will be published next week.

  6. Samuh Varta

    Wonderful tutorial; exactly what I was looking for!

    :thumb up:


  7. JHandal

    Well explained GL ES ,excellent!

    Thanks !


  8. Sam

    Eagerly waiting for your next tutorial.Next week is about to get over, please let me know when can I expect the next tutorial.

  9. Jason

    Can’t wait for the next tutorial… this is by FAR the best explanation I have found on the subject. Well done for being so descriptive, and not assuming we’ve all been programming graphics since the womb.

  10. Tim Hansen

    Tusen takk! Your tutorial is great and is just what I needed to get me up and running with Android and OpenGL ES. Can you recommend any books as well until the next installment! Hadet! 8)

  11. Hal

    Nice tutorial, thanks. I notice it crashes when running on my G1 though.

    The problem is in Cube.draw(GL10). glDrawElements is called with vertices.length as the count, but I believe it should be indices.length. This fixes the crash.


  12. odd

    As Hal, I too had crashes on a donut avd (1.6), the fix suggested by Hall has solved that problem.

    Still an excellent tutorial. Thanks.

  13. Per-Erik Bergman

    Thanks for the input. And of course it should be indics.length, my bad. I have updated the source and the tutorials affected.

  14. Brian

    Great tutorial! One thing I’m wondering is if it’s possible to use int arrays instead of float arrays for defining vertices. My understanding is that floating point performance is pretty bad on android devices because there is no dedicated floating point processing unit. I ask now because I ran across this post at

    Your input would be greatly appreciated!

  15. John

    I’m trying to use DrawArrays with GL_POINTS, but my point(s) are only ever rendered in the middle of the screen, if at all (and the strangest code changest can prevent them from being appearing, like adding an extra LoadIdentity). I’ve put in a color-changing if-statement to confirm that my buffer contains the coordinates that I want it to, which it definitely does. Even changing the parameters of glOrthof (so that the origin should be to the left or right of the viewport) doesn’t prevent my point from just appearing in the middle of the viewport, regardless of the point’s coordinates. The only thing that ever moves the point on the screen at all is if I change the size or location of the actual viewport (not the ‘camera’). Can anyone explain this? Could it just be a problem with the AVD simulation?

  16. lee

    thank you, it’s very good lecture for me.
    but, i can draw square using just your code.
    so i add other code.
    onDrawFrame method is added gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    also i modify indices[] from short to byte in

    like do this, i can draw it.

    can other people draw Square??
    i wander.

  17. lee

    oh, i’m mistake. it executes very well when i add code of previous lecture

  18. Enrique

    I’m taking my firsts steps into OpenGL and I have to say this tutorial is AMAZING!
    Many Thanks! Keep up the excellent work :)

  19. Jyothi

    Thanks a lot for your tutorial. I understood very well this sample program.can u explain little more clear about indices. Waiting eagerly for more tutorials from u..

  20. ashik

    hey i couldn’t get the indices part?? seeing the image for square and seeing the code! I couldn’t get how its done in short indices!!?? pls help me there!!I got the triangles part but not the square indices?? :(

  21. ashik

    hey Guys Im gettin NullPointerExceptio in gl.glVertexPOinter()??

  22. polosatik

    Dude, you’re just rock!

  23. polosatik

    You rock, I meant :)

  24. Claudio

    Great tutorials pls keep up the good work!

  25. Adrian

    Great Tutorial. One question though.
    The last step to get the square in a fixed position using
    // Replace the current matrix with the identity matrix
    gl.glLoadIdentity(); // OpenGL docs
    Where exactly does this line go?
    My square never appears when i put this line in and without this line my square goes “into” the screen.

  26. Arun

    Thank u..nice tutorial..the OpenGL docs reference hyperlink given for glVertexPointer is pointing to glDrawElemtents. hope u will correct it..

  27. oochieman

    Excellent tutorial, thanks

  28. RGB tool

    Do you recommend same techniques for 2D rendering?

    Great tutorial, thanks!

  29. Pierre M

    Excellent, very intuitive and clear.

  30. Per-Erik Bergman

    ashik: We only work with triangles so the indices is the way we tell OpenGL how to build our triangles.

    Adrian: glLoadIdentity() resets the current matrix it’s like moving the pen back to it’s original location.

    RGB tool: It depends some hardware support direct texture rendering and that is faster but sure, this is a good way to start.

  31. dongfeng

    Excellent, Great tutorial!

  32. Raymond Wilson

    This is awesome, thanks!

  33. Naveen Patel

    I am trying to plot ecg on android, using opengl is there any way, if anybody have idea please help in this.
    Form India

  34. Ciprian

    I tried the code and debugged on my htc wildfire.. and still, just blank screen. No error and I put together everything from the two tutorials.

  35. pgm1961us

    cannot see square. am using eclipse to launch android emulator. what color is the square suppose to be? any suggestions?

  36. Randin

    Thank you for your great work.

  37. Randin

    Thank you for your great tutorial.



  39. Evan


    A very good tutorial for beginner like me.

    But I was wondering, instead of declaring the vertices and indices manually one by one for the cube, do we have other method?


  40. CP Gangstaz

    Damn, this tutorial is dope!

  41. S

    Man this tutorial makes more sense than the stock android one.

    So basically, we need to make a custom class for each particular shape we want to render?

    I’m used to just rendering in straight OpenGL, and not OpenGL ES, so this is somewhat foreign to me.

    I feel like there has to be some simple library which contains all of the rendering classes for each of the primitive shapes?

    I confess, I’m a newb and just want to take as many shortcuts as possible to get up and running, but does such a library exist?

  42. idoudi karim

    Very nice.Thank’s

  43. gebs

    Hi..the program exits unexpectedly. When i checked logcat in eclipse it mentioned a nullpointer exception at OpenGLrenderer.onDrawFrame.. any ideas or help would be really appreiciated!

    Thanks a lot

  44. gebs

    I figured it out ..thanks .I , by accident, added a return type to the constructor :P :P

  45. ashok

    i am not getting squre when i run

  46. Aaron

    Gracias por el tuturial, hasta donde voy me ha quedado bastante claro lo que has enseñado

  47. Anonymous

    Thanks this is very helpful!

  48. thai

    Thanks for your sharing^^

  49. Ooms

    I find this an excelent tutorial.

    I have several objects, including a torus as in this example.
    A torus has quite some symmetry. I can make one big buffer including al the vertices of the torus, and call the draw function once every frame, or i can make a small patch of the torus an call this patch 16 times per frame with different position/ orientation. What will give the best performance?

    Thanks alot

  50. Chris

    Hello everyone, I am learning opengl es these days. and I got stuck by the difference on the surface and surfaceview.
    so is there anybody who can tell me the difference between surface and surfaceview in android.
    it is urgent.
    Many thanks.

  51. aYo

    Simply a lifesaver – Many thanks

  52. Daniel Adamko

    Fantastische! I made a rotating cube without lighting and texture. Wow!

  53. Kelsie

    When I ran the app, it always said The (app name) has stopped unexpectedly.

    What might be the problem???

  54. Kelsie

    Alright. I figured it out~

  55. RAza

    Log.i(“Woww”, “Now this one i must say excellent !”);

  56. Mike

    Excellent tutorial, you explain these stuff really well. I don’t know much about openGL and it’s the first tutorial I feel I really understood

  57. Isaac

    So, followed the tutorial(Which is Phenomenal, Thank you very much) but when I run the program, it doesn’t draw the square. Is there something maybe that I am missing about color, AKA is it drawing a black square, but because there is a black background, it doesn’t show up. All that shows up is a black screen. Any Ideas?

  58. Isaac

    Hey, Figured it out and wanted to post a reply, since other people seem to be having a similar problem. The last two parts of the tutorial:

    gl.glTranslatef(0, 0, -4); // OpenGL docs


    gl.glLoadIdentity(); // OpenGL docs

    need to be called in this order:



    gl.glTranslatef(0, 0, -4);

    See if that works. Doing it the other way (which I did forever) doesn’t make sense because its reseting to the identity matrix after the translation, so there is no translation at all…

  59. Andi

    Great tutorial, thanks a lot!

    @Isaac: Thank you, as an OpenGL beginner I stumbled about this one before

  60. null

    “1.0f, 1.0f, 0.0f, // 3, Top Right”

    Should be

    “1.0f, 1.0f, 0.0f // 3, Top Right”

    Don’t need the last comma.

  61. null

    Also awesome tutorials! Thanks!

  62. Nemanja

    Cool tuts. Is there, a third tutorial? When I click to a link on a bottom of a page 404 apears.

  63. rrivera

    Buen Tutorial

  64. vlitomsk


    Thanks for this series of tutorials.

    I have one question: why do we reload identitiy each frame? I put that snippet (glLoadIdentity + glTranslatef) to onSurfaceChanged and all works fine. In this example we must change viewport state only when surface changes so we don’t overload `OpenGL core` by useless calls, do we?

    P.S. Sorry for English mistakes.

  65. George

    Thank you for sharing your knowledge, Per-Erik…
    Excellent tutorials and very well explained.
    Keep up the good work.

  66. James

    This tutorial doesn’t seem to seamlessly follow on from the previous one. Quite a few changes are required to make this work, if you start at Tutorial 1.

    This is a shame, as I’m not sure what is going wrong. The app starts but is still a black screen

  67. Tobiah

    Nice looking article, but the html links are
    expanded into html source in the code snippets rendering
    them almost unreadable.

  68. Keyren

    Very good tutorial =) but i don’t have understand one thing
    // Replace the current matrix with the identity matrix

    where where i insert this?I try in renderer class,but the screen or still black or i don’t have any effect

    1. webster

      public void onDrawFrame(GL10 gl) {
      // Clears the screen and depth buffer.
      gl.glClear(GL10.GL_COLOR_BUFFER_BIT |
      // Insert Load Identity Here //

      // Draw our square.
      square.draw(gl); // ( NEW )

  69. webster

    Finally, a great tutorial on OpenGL ES 1.

  70. Alkis

    This is a very good tutorial. Thank you, Per-Erik.

    Despite the questions about the “invisible” square I didn’t see any reply that the square is white, but a more important question for me is “Where is the color of the square set?” This would also answer the question of the color of the square. I double-checked the code to find out anything about the color, not in the code nor in the documentation. Normally, it should be near the position and size (gl.glTranslatef()). Quite strange. I must certainly miss somthing.

  71. Trần Lê Duy

    thank a lot. this is a great tutorial

  72. jagadish

    Actually i am working on getting 3d mesh from images. i finished getting 3d mesh from images. now i have to load 3d mesh on android app , generated 3d mesh file is .ply binary format and texture information is saving in .png file, now i am facing problems loading of this 3d mesh please help me in this. i am new to this opengl concept

  73. MJB

    How can I find a sample code for using GL_LINE_STRIP? I really need one

Leave a Reply