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 public 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 public 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[] = {
    123             -0.5f,  0.5f, 0.0f,   // top left
    124             -0.5f, -0.5f, 0.0f,   // bottom left
    125              0.5f, -0.5f, 0.0f,   // bottom right
    126              0.5f,  0.5f, 0.0f }; // top right
    127 
    128     private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
    129 
    130     public Square() {
    131         // initialize vertex byte buffer for shape coordinates
    132         ByteBuffer bb = ByteBuffer.allocateDirect(
    133         // (# of coordinate values * 4 bytes per float)
    134                 squareCoords.length * 4);
    135         bb.order(ByteOrder.nativeOrder());
    136         vertexBuffer = bb.asFloatBuffer();
    137         vertexBuffer.put(squareCoords);
    138         vertexBuffer.position(0);
    139 
    140         // initialize byte buffer for the draw list
    141         ByteBuffer dlb = ByteBuffer.allocateDirect(
    142         // (# of coordinate values * 2 bytes per short)
    143                 drawOrder.length * 2);
    144         dlb.order(ByteOrder.nativeOrder());
    145         drawListBuffer = dlb.asShortBuffer();
    146         drawListBuffer.put(drawOrder);
    147         drawListBuffer.position(0);
    148     }
    149 }
    150 </pre>
    151 
    152 <p>This example gives you a peek at what it takes to create more complex shapes with OpenGL. In
    153 general, you use collections of triangles to draw objects. In the next lesson, you learn how to draw
    154 these shapes on screen.</p>
    155