• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Defining Shapes
2parent.title=Displaying Graphics with OpenGL ES
3parent.link=index.html
4
5trainingnavtop=true
6previous.title=Building an OpenGL ES Environment
7previous.link=environment.html
8next.title=Drawing Shapes
9next.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"
29class="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
37creating your high-end graphics masterpiece. Drawing with OpenGL ES can be a little tricky without
38knowing 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
41basics 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,
47before you can draw a triangle, you must define its coordinates. In OpenGL, the typical way to do
48this is to define a vertex array of floating point numbers for the coordinates. For maximum
49efficiency, you write these coordinates into a {@link java.nio.ByteBuffer}, that is passed into the
50OpenGL ES graphics pipeline for processing.</p>
51
52<pre>
53class 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
87the {@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
90guide.</p>
91
92<p>Note that the coordinates of this shape are defined in a counterclockwise order. The drawing
93order is important because it defines which side is the front face of the shape, which you typically
94want to have drawn, and the back face, which you can choose to not draw using the OpenGL ES cull
95face feature. For more information about faces and culling, see the <a
96href="{@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
102complex? Say, a square? There are a number of ways to do this, but a typical path to drawing such a
103shape 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
110represent this shape, and put the values in a {@link java.nio.ByteBuffer}. In order to avoid
111defining the two coordinates shared by each triangle twice, use a drawing list to tell the
112OpenGL ES graphics pipeline how to draw these vertices. Here’s the code for this shape:</p>
113
114<pre>
115class 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
152general, you use collections of triangles to draw objects. In the next lesson, you learn how to draw
153these shapes on screen.</p>
154