Home | History | Annotate | Download | only in opengl
      1 page.title=Defining Shapes
      2 parent.title=Displaying Graphics with OpenGL ES
      3 parent.link=index.html
      4 
      5 trainingnavtop=true
      6 previous.title=Building an OpenGL ES Environment
      7 previous.link=environment.html
      8 next.title=Drawing Shapes
      9 next.link=draw.html
     10 
     11 @jd:body
     12 
     13 <div id="tb-wrapper">
     14 <div id="tb">
     15 
     16 <h2>This lesson teaches you to</h2>
     17 <ol>
     18   <li><a href="#triangle">Define a Triangle</a></li>
     19   <li><a href="#square">Define a Square</a></li>
     20 </ol>
     21 
     22 <h2>You should also read</h2>
     23 <ul>
     24   <li><a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL</a></li>
     25 </ul>
     26 
     27 <div class="download-box">
     28  <a href="{@docRoot}shareables/training/OpenGLES.zip"
     29 class="button">Download the sample</a>
     30  <p class="filename">OpenGLES.zip</p>
     31 </div>
     32 
     33 </div>
     34 </div>
     35 
     36 <p>Being able to define shapes to be drawn in the context of an OpenGL ES view is the first step in
     37 creating your high-end graphics masterpiece. Drawing with OpenGL ES can be a little tricky without
     38 knowing a few basic things about how OpenGL ES expects you to define graphic objects.</p>
     39 
     40 <p>This lesson explains the OpenGL ES coordinate system relative to an Android device screen, the
     41 basics of defining a shape, shape faces, as well as defining a triangle and a square.</p>
     42 
     43 
     44 <h2 id="triangle">Define a Triangle</h2>
     45 
     46 <p>OpenGL ES allows you to define drawn objects using coordinates in three-dimensional space. So,
     47 before you can draw a triangle, you must define its coordinates. In OpenGL, the typical way to do
     48 this is to define a vertex array of floating point numbers for the coordinates. For maximum
     49 efficiency, you write these coordinates into a {@link java.nio.ByteBuffer}, that is passed into the
     50 OpenGL ES graphics pipeline for processing.</p>
     51 
     52 <pre>
     53 class Triangle {
     54 
     55     private FloatBuffer vertexBuffer;
     56 
     57     // number of coordinates per vertex in this array
     58     static final int COORDS_PER_VERTEX = 3;
     59     static float triangleCoords[] = { // in counterclockwise order:
     60          0.0f,  0.622008459f, 0.0f,   // top
     61         -0.5f, -0.311004243f, 0.0f,   // bottom left
     62          0.5f, -0.311004243f, 0.0f    // bottom right
     63     };
     64 
     65     // Set color with red, green, blue and alpha (opacity) values
     66     float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
     67 
     68     public Triangle() {
     69         // initialize vertex byte buffer for shape coordinates
     70         ByteBuffer bb = ByteBuffer.allocateDirect(
     71                 // (number of coordinate values * 4 bytes per float)
     72                 triangleCoords.length * 4);
     73         // use the device hardware's native byte order
     74         bb.order(ByteOrder.nativeOrder());
     75 
     76         // create a floating point buffer from the ByteBuffer
     77         vertexBuffer = bb.asFloatBuffer();
     78         // add the coordinates to the FloatBuffer
     79         vertexBuffer.put(triangleCoords);
     80         // set the buffer to read the first coordinate
     81         vertexBuffer.position(0);
     82     }
     83 }
     84 </pre>
     85 
     86 <p>By default, OpenGL ES assumes a coordinate system where [0,0,0] (X,Y,Z) specifies the center of
     87 the {@link android.opengl.GLSurfaceView} frame, [1,1,0] is the top right corner of the frame and
     88 [-1,-1,0] is bottom left corner of the frame. For an illustration of this coordinate system, see the
     89 <a href="{@docRoot}guide/topics/graphics/opengl.html#coordinate-mapping">OpenGL ES</a> developer
     90 guide.</p>
     91 
     92 <p>Note that the coordinates of this shape are defined in a counterclockwise order. The drawing
     93 order is important because it defines which side is the front face of the shape, which you typically
     94 want to have drawn, and the back face, which you can choose to not draw using the OpenGL ES cull
     95 face feature. For more information about faces and culling, see the <a
     96 href="{@docRoot}guide/topics/graphics/opengl.html#faces-winding">OpenGL ES</a> developer guide.</p>
     97 
     98 
     99 <h2 id="square">Define a Square</h2>
    100 
    101 <p>Defining triangles is pretty easy in OpenGL, but what if you want to get a just a little more
    102 complex? Say, a square? There are a number of ways to do this, but a typical path to drawing such a
    103 shape in OpenGL ES is to use two triangles drawn together:</p>
    104 
    105 <img src="{@docRoot}images/opengl/ccw-square.png">
    106 <p class="img-caption">
    107   <strong>Figure 1.</strong> Drawing a square using two triangles.</p>
    108 
    109 <p>Again, you should define the vertices in a counterclockwise order for both triangles that
    110 represent this shape, and put the values in a {@link java.nio.ByteBuffer}. In order to avoid
    111 defining the two coordinates shared by each triangle twice, use a drawing list to tell the
    112 OpenGL ES graphics pipeline how to draw these vertices. Heres the code for this shape:</p>
    113 
    114 <pre>
    115 class Square {
    116 
    117     private FloatBuffer vertexBuffer;
    118     private ShortBuffer drawListBuffer;
    119 
    120     // number of coordinates per vertex in this array
    121     static final int COORDS_PER_VERTEX = 3;
    122     static float squareCoords[] = { -0.5f,  0.5f, 0.0f,   // top left
    123                                     -0.5f, -0.5f, 0.0f,   // bottom left
    124                                      0.5f, -0.5f, 0.0f,   // bottom right
    125                                      0.5f,  0.5f, 0.0f }; // top right
    126 
    127     private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
    128 
    129     public Square() {
    130         // initialize vertex byte buffer for shape coordinates
    131         ByteBuffer bb = ByteBuffer.allocateDirect(
    132         // (# of coordinate values * 4 bytes per float)
    133                 squareCoords.length * 4);
    134         bb.order(ByteOrder.nativeOrder());
    135         vertexBuffer = bb.asFloatBuffer();
    136         vertexBuffer.put(squareCoords);
    137         vertexBuffer.position(0);
    138 
    139         // initialize byte buffer for the draw list
    140         ByteBuffer dlb = ByteBuffer.allocateDirect(
    141         // (# of coordinate values * 2 bytes per short)
    142                 drawOrder.length * 2);
    143         dlb.order(ByteOrder.nativeOrder());
    144         drawListBuffer = dlb.asShortBuffer();
    145         drawListBuffer.put(drawOrder);
    146         drawListBuffer.position(0);
    147     }
    148 }
    149 </pre>
    150 
    151 <p>This example gives you a peek at what it takes to create more complex shapes with OpenGL. In
    152 general, you use collections of triangles to draw objects. In the next lesson, you learn how to draw
    153 these shapes on screen.</p>
    154