1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
|
page.title=Hello OpenGL ES 1.0
parent.title=Tutorials
parent.link=../../browser.html?tag=tutorial
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#creating">Creating an OpenGL ES 1.0 Application</a></li>
<li>
<a href="#drawing">Drawing Graphic Elements</a>
<ol>
<li><a href="#define-triangle">Defining a Triangle</a></li>
<li><a href="#draw-triangle">Draw the Triangle</a></li>
</ol>
</li>
<li><a href="#projection-and-views">Using Projection and Views</a></li>
<li><a href="#motion">Adding Motion</a></li>
<li><a href="#resources">Additional Resources</a></li>
</ol>
<h2 id="code-samples-list">Related Samples</h2>
<ol>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/
index.html">API Demos - graphics</a></li>
<li><a
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/
GLSurfaceViewActivity.html">GLSurfaceViewActivity</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/topics/graphics/opengl.html">3D with OpenGL</a></li>
<li><a href="{@docRoot}resources/tutorials/opengl/opengl-es20.html">Hello OpenGL
ES 2.0</a></li>
</ol>
</div>
</div>
<p>This tutorial shows you how to create a simple Android application that uses OpenGL ES 1.0 and
perform some basic operations using the OpenGL ES 1.0 API, including:</p>
<ul>
<li>Creating an application using {@link android.opengl.GLSurfaceView} and {@link
android.opengl.GLSurfaceView.Renderer}</li>
<li>Defining a graphic object and drawing it</li>
<li>Defining and applying an projection and view</li>
<li>Applying rotation to the drawn object</li>
</ul>
<p>This tutorial demonstrates use of the OpenGL ES 1.0 API. Both the OpenGL ES 1.0 and the ES 1.1
API are supported by the Android framework since release 1.0 (API Level 1). The OpenGL ES 1.1 API
is an extention of the 1.0 API, and it's capabilities are beyond the scope of this tutorial.</p>
<p>Beginning with Android 2.2 (API Level 8), the framework supports OpenGL ES 2.0. For more
information about compatibility for OpenGL versions and Android devices, see the <a
href="{@docRoot}guide/topics/graphics/opengl.html#compatibility">3D with OpenGL</a> document.</p>
<h2 id="creating">Creating an OpenGL ES 1.0 Application</h2>
<p>OpenGL applications for Android have the same basic structure as other applications, however
OpenGL applications use {@link android.opengl.GLSurfaceView} where other, non-OpenGL
applications use the {@link android.view.View} or {@link android.view.SurfaceView} class.<p>
<p>To get started using OpenGL in your Android application, you must implement both a {@link
android.opengl.GLSurfaceView} and a {@link android.opengl.GLSurfaceView.Renderer}. The {@link
android.opengl.GLSurfaceView} is the main view type for the OpenGL applications and the {@link
android.opengl.GLSurfaceView.Renderer} controls what is drawn within that view. For more
information about these classes, see the <a href="{@docRoot}guide/topics/graphics/opengl.html">3D
with OpenGL</a> document.</p>
<p>To create an application that uses OpenGL ES 1.0:</p>
<ol>
<li>Start a new Android project with an Activity called <code>HelloOpenGLES10</code>.
<p class="note"><b>Note:</b> If you have not created a basic Android application yet, follow the
<a href="{@docRoot}resources/tutorials/hello-world.html">Hello World Tutorial</a> instructions
to familiarize yourself with the process.</p>
</li>
<li>Modify the <code>HelloOpenGLES10</code> class as follows:
<pre>
package com.example.android.apis.graphics;
import android.app.Activity;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
public class HelloOpenGLES10 extends Activity {
private GLSurfaceView mGLView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLView = new HelloOpenGLSurfaceView(this);
setContentView(mGLView);
}
@Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}
@Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}
}
class HelloOpenGLES10SurfaceView extends GLSurfaceView {
public HelloOpenGLES10SurfaceView(Context context){
super(context);
setRenderer(new HelloOpenGLES10Renderer());
}
}
</pre>
<p>This Activity class creates a basic container for a {@link android.opengl.GLSurfaceView}.</p>
</li>
<li>Create the following class <code>HelloOpenGLES10Renderer</code>, which implements the
{@link android.opengl.GLSurfaceView.Renderer} interface:
<pre>
package com.example.android.apis.graphics;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView;
public class HelloOpenGLES10Renderer implements GLSurfaceView.Renderer {
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Set the background frame color
gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
}
public void onDrawFrame(GL10 gl) {
// Redraw background color
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
}
}
</pre>
</li>
</ol>
<p>These classes create a simple Android application which displays a grey screen using OpenGL
ES 1.0 calls. While this application does not do anything very interesting, by creating these two
classes, you have layed the foundation needed to start drawing graphic elements with OpenGL ES
1.0.</p>
<p>If you are familiar with the OpenGL ES APIs, these two classes should give you enough information
to start using the OpenGL ES 1.0 API and creating graphics. However, if you need a bit more help
getting started with OpenGL, head on to the next sections for a few more tips.</p>
<h2 id="drawing">Drawing Graphic Elements</h2>
<p>Once you have implemented a {@link android.opengl.GLSurfaceView.Renderer}, the next step is to
draw something on it. This section shows you how to define and draw a basic triangle shape with the
Android OpenGL ES 1.0 API.</p>
<p class="note"><b>Note:</b> The following instructions build on the previous section, so if you
have not been following along, go back to the <a href="#get-started">previous section</a> and catch
up.</p>
<h3 id="define-triangle">Defining a Triangle</h3>
<p>OpenGL allows you to define objects using coordinates in three-dimensional space. So, before you
can draw a triangle, you must define its coordinates. In OpenGL, the typical way to do this is to
define a vertex array for the coordinates.</p>
<p>By default, OpenGL ES assumes a coordinate system where 0,0,0 (X,Y,Z) specifies the center of
the {@link android.opengl.GLSurfaceView} frame, 1,1,0 is the top right corner of the frame and
-1,-1,0 is bottom left corner of the frame.</p>
<p>To define a vertex array for a triangle:</p>
<ol>
<li>In your <code>HelloOpenGLES10Renderer</code> class, add new member variable to contain the
vertices of a triangle shape:
<pre>
private FloatBuffer triangleVB;
</pre>
</li>
<li>Create a method, <code>initShapes()</code> which populates this member variable:
<pre>
private void initShapes(){
float triangleCoords[] = {
// X, Y, Z
-0.5f, -0.25f, 0,
0.5f, -0.25f, 0,
0.0f, 0.559016994f, 0
};
// initialize vertex Buffer for triangle
ByteBuffer vbb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
triangleCoords.length * 4);
vbb.order(ByteOrder.nativeOrder());
triangleVB = vbb.asFloatBuffer();
triangleVB.put(triangleCoords);
triangleVB.position(0);
}
</pre>
<p>This method defines a two-dimensional triangle shape with three equal sides.</p>
</li>
<li>Modify your <code>onSurfaceCreated()</code> method to initialize your triangle:
<pre>
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Set the background frame color
gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
// initialize the triangle vertex array
initShapes();
}
</pre>
<p class="warning"><strong>Warning:</strong> Shapes and other static objects should be initialized
once in your <code>onSurfaceCreated()</code> method for best performance. Avoid initializing the
new objects in <code>onDrawFrame()</code>, as this causes the system to re-create the objects
for every frame redraw and slows down your application.
</p>
</li>
</ol>
<h3 id="draw-triangle">Draw the Triangle</h3>
<p>Now that you have defined a shape to draw, you can use the OpenGL APIs to draw the
object.</p>
<p>To draw the triangle with OpenGL:</p>
<ol>
<li>Before you can draw your triangle, you must tell OpenGL that you are using vertex arrays.
Modify your <code>onSurfaceCreated()</code> method to enable vertex arrays.
<pre>
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Set the background frame color
gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
// initialize the triangle vertex array
initShapes();
// Enable use of vertex arrays
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
}
</pre>
<p>At this point, you are ready to draw the triangle object in the OpenGL frame.</p>
</li>
<li>Modify your <code>onDrawFrame()</code> method to draw the triangle.
<pre>
public void onDrawFrame(GL10 gl) {
// Redraw background color
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Draw the triangle
gl.glColor4f(0.63671875f, 0.76953125f, 0.22265625f, 0.0f);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleVB);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
}
</pre>
<p><b>Note:</b> Since the triangle is stationary at this point, the system is redrawing the
object repeatedly in exactly the same place and so is not the most efficient use of the OpenGL
graphics pipeline. In a <a href="#motion">later section</a>, we add motion to the object to
justify this use of processing power.</p>
</li>
</ol>
<p id="squashed-triangle">Try running this example application on your emulator or test device and
you should see something like this:</p>
<img src="{@docRoot}images/opengl/helloopengl-es10-1.png">
<p>There are a few problems with this example. First of all, it's not going to impress your
friends. Secondly, the triangle is a bit squashed and changes shape when you change the screen
orientation of the test device. The reason the shape is skewed is due to the fact that the object is
being rendered in a frame which is not perfectly square. We fix that problem in the
<a href="#projection-and-views">next section</a>.</p>
<h2 id="projection-and-views">Using Projection and Views</h2>
<p>OpenGL Projection and Views provide a way to calculate the coordinates of graphic objects in
realistic proportions on graphics displays of any size. One of the basic problems in displaying
graphics is that Android device displays are typically not square and—by default—OpenGL
happily maps a perfectly square, uniform coordinate system onto your typically non-square
screen.</p>
<img src="{@docRoot}images/opengl/coordinates.png">
<p>The illustration above shows the uniform coordinate system assumed for an OpenGL frame on the
left, and how these coordinates actually map to a typical device screen in landscape orientation
on the right. To solve this problem, you can apply OpenGL projection modes and views to transform
object coordinates so your graphic objects have the correct proportions on any display.</p>
<p>To use a projection transformation on your triangle:</p>
<ol>
<li>Modify your <code>onSurfaceChanged()</code> method to enable {@link
javax.microedition.khronos.opengles.GL10#GL_PROJECTION GL10.GL_PROJECTION} mode, calculate the
screen ratio and apply the ratio as a transformation of the object coordinates.
<pre>
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
// make adjustments for screen ratio
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);
}
</pre>
</li>
<li>Next, modify your <code>onDrawFrame()</code> method to apply the {@link
javax.microedition.khronos.opengles.GL10#GL_MODELVIEW GL_MODELVIEW} mode and set
a view point for the display using {@link
android.opengl.GLU#gluLookAt(javax.microedition.khronos.opengles.GL10, float, float, float, float,
float, float, float, float, float) GLU#gluLookAt()}.
<pre>
public void onDrawFrame(GL10 gl) {
// Redraw background color
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Set GL_MODELVIEW transformation mode
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
// When using GL_MODELVIEW, you must set the view point
GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Draw the triangle
...
}
</pre>
</li>
</ol>
<p>Try running this updated application on your emulator or test device and you should see something
like this:</p>
<img src="{@docRoot}images/opengl/helloopengl-es10-2.png">
<p>Now that you have applied this transformation, the triangle has three equal sides, instead of the
squashed display in the <a href="#squashed-triangle">earlier version</a>.</p>
<h2 id="motion">Adding Motion</h2>
<p>While it may be interesting exercise to create static graphic objects with OpenGL ES, chances
are you want at least some of your objects to move. In this section, we add motion to to our
triangle by rotating it.</p>
<p>To add rotation to your triangle:</p>
<ul>
<li>Modify your <code>onDrawFrame()</code> method to rotate the triangle object:
<pre>
public void onDrawFrame(GL10 gl) {
...
// When using GL_MODELVIEW, you must set the view point
GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Create a rotation for the triangle
long time = SystemClock.uptimeMillis() % 4000L;
float angle = 0.090f * ((int) time);
gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);
// Draw the triangle
...
}
</pre>
</li>
</ul>
<p>Run the application with this code and your triangle should rotate around its center.</p>
<!--
<h2>TouchScreen Interaction</h2>
Optional extra (using code from API examples)
-->
<h2 id="resources">Additional Resources</h2>
<p>Be sure to check out the OpenGL ES code samples are available in the
<a
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/index.html">API
Demos</a> sample application and listed in <a href="#code-samples-list">Related Samples</a>
sidebar above.
</p>
|