diff --git a/docs/html/images/opengl/coordinates.png b/docs/html/images/opengl/coordinates.png new file mode 100644 index 0000000000000..7180cd5cecf3d Binary files /dev/null and b/docs/html/images/opengl/coordinates.png differ diff --git a/docs/html/images/opengl/helloopengl-es10-1.png b/docs/html/images/opengl/helloopengl-es10-1.png new file mode 100644 index 0000000000000..bdfbcdb96eede Binary files /dev/null and b/docs/html/images/opengl/helloopengl-es10-1.png differ diff --git a/docs/html/images/opengl/helloopengl-es10-2.png b/docs/html/images/opengl/helloopengl-es10-2.png new file mode 100644 index 0000000000000..c07dabbbe46d2 Binary files /dev/null and b/docs/html/images/opengl/helloopengl-es10-2.png differ diff --git a/docs/html/images/opengl/helloopengl-es20-1.png b/docs/html/images/opengl/helloopengl-es20-1.png new file mode 100644 index 0000000000000..44abe7729cfa7 Binary files /dev/null and b/docs/html/images/opengl/helloopengl-es20-1.png differ diff --git a/docs/html/images/opengl/helloopengl-es20-2.png b/docs/html/images/opengl/helloopengl-es20-2.png new file mode 100644 index 0000000000000..22fa52cea82fe Binary files /dev/null and b/docs/html/images/opengl/helloopengl-es20-2.png differ diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js index 097d0041c73d1..f71307e651169 100644 --- a/docs/html/resources/resources-data.js +++ b/docs/html/resources/resources-data.js @@ -761,6 +761,26 @@ var ANDROID_RESOURCES = [ en: 'A multi-part tutorial discussing intermediate-level concepts such as data access.' } }, + { + tags: ['tutorial', 'gl', 'new'], + path: 'tutorials/opengl/opengl-es10.html', + title: { + en: 'Hello OpenGL ES 1.0' + }, + description: { + en: 'The basics of implementing an application using the OpenGL ES 1.0 APIs.' + } + }, + { + tags: ['tutorial', 'gl', 'new'], + path: 'tutorials/opengl/opengl-es20.html', + title: { + en: 'Hello OpenGL ES 2.0' + }, + description: { + en: 'The basics of implementing an application using the OpenGL ES 2.0 APIs.' + } + }, { tags: ['tutorial', 'testing'], path: 'tutorials/testing/helloandroid_test.html', diff --git a/docs/html/resources/tutorials/opengl/opengl-es10.jd b/docs/html/resources/tutorials/opengl/opengl-es10.jd new file mode 100644 index 0000000000000..d18a547399950 --- /dev/null +++ b/docs/html/resources/tutorials/opengl/opengl-es10.jd @@ -0,0 +1,409 @@ +page.title=Hello OpenGL ES 1.0 +parent.title=Tutorials +parent.link=../../browser.html?tag=tutorial +@jd:body + + +
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:
+ +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.
+ +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 3D with OpenGL document.
+ + +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.
+ +
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 3D +with OpenGL document.
+ +To create an application that uses OpenGL ES 1.0:
+ +HelloOpenGLES10.
+
+ Note: If you have not created a basic Android application yet, follow the + Hello World Tutorial instructions + to familiarize yourself with the process.
+HelloOpenGLES10 class as follows:
+
+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());
+ }
+
+}
+
+ This Activity class creates a basic container for a {@link android.opengl.GLSurfaceView}.
+HelloOpenGLES10Renderer, which implements the
+ {@link android.opengl.GLSurfaceView.Renderer} interface:
+
+
+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);
+ }
+
+}
+
+ 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.
+ +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.
+ +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.
+ +Note: The following instructions build on the previous section, so if you +have not been following along, go back to the previous section and catch +up.
+ +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.
+ +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.
+ +To define a vertex array for a triangle:
+ +HelloOpenGLES10Renderer class, add new member variable to contain the
+vertices of a triangle shape:
++ private FloatBuffer triangleVB; ++
initShapes() which populates this member variable:
+
+ 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);
+
+ }
+
+ This method defines a two-dimensional triangle shape with three equal sides.
+onSurfaceCreated() method to initialize your triangle:
+
+ 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();
+ }
+
+ Warning: Shapes and other static objects should be initialized
+ once in your onSurfaceCreated() method for best performance. Avoid initializing the
+ new objects in onDrawFrame(), as this causes the system to re-create the objects
+ for every frame redraw and slows down your application.
+
Now that you have defined a shape to draw, you can use the OpenGL APIs to draw the +object.
+ +To draw the triangle with OpenGL:
+ +onSurfaceCreated() method to enable vertex arrays.
+
+ 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);
+ }
+
+ At this point, you are ready to draw the triangle object in the OpenGL frame.
+onDrawFrame() method to draw the triangle.
+
+ 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);
+ }
+
+ Note: 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 later section, we add motion to the object to + justify this use of processing power.
+Try running this example application on your emulator or test device and +you should see something like this:
+ +
+
+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 +next section.
+ +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.
+ +
+
+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.
+ +To use a projection transformation on your triangle:
+onSurfaceChanged() 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.
+
+ 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);
+ }
+
+ onDrawFrame() 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()}.
+
+ 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
+ ...
+ }
+
+ Try running this updated application on your emulator or test device and you should see something +like this:
+ +
+
+Now that you have applied this transformation, the triangle has three equal sides, instead of the +squashed display in the earlier version.
+ +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.
+ +To add rotation to your triangle:
+onDrawFrame() method to rotate the triangle object:
+
+ 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
+ ...
+ }
+
+ Run the application with this code and your triangle should rotate around its center.
+ + + +Be sure to check out the OpenGL ES code samples are available in the +API +Demos sample application and listed in Related Samples +sidebar above. +
diff --git a/docs/html/resources/tutorials/opengl/opengl-es20.jd b/docs/html/resources/tutorials/opengl/opengl-es20.jd new file mode 100644 index 0000000000000..5cdc3430fd416 --- /dev/null +++ b/docs/html/resources/tutorials/opengl/opengl-es20.jd @@ -0,0 +1,514 @@ +page.title=Hello OpenGL ES 1.0 +parent.title=Tutorials +parent.link=../../browser.html?tag=tutorial +@jd:body + + +This tutorial shows you how to create a simple Android application that uses OpenGL ES 2.0 and +perform some basic operations using the OpenGL ES 2.0 API, including:
+ +This tutorial demonstrates use of the OpenGL ES 2.0 API. Beginning with Android 2.2 (API Level +8), the framework supports OpenGL ES 2.0.
+ +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).For more information about compatibility for OpenGL versions and Android devices, +see the 3D with OpenGL +document.
+ + +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.
+ +
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 3D +with OpenGL document.
+ +To create an application that uses OpenGL ES 2.0:
+ +HelloOpenGLES20.
+
+ Note: If you have not created a basic Android application yet, follow the + Hello World Tutorial instructions + to familiarize yourself with the process.
+HelloOpenGLES20 class as follows:
+
+package com.example.android.apis.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+
+public class HelloOpenGLES20 extends Activity {
+
+ private GLSurfaceView mGLView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mGLView = new HelloOpenGLES20SurfaceView(this);
+ setContentView(mGLView);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mGLView.onPause();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mGLView.onResume();
+ }
+}
+
+class HelloOpenGLES20SurfaceView extends GLSurfaceView {
+
+ public HelloOpenGLES20SurfaceView(Context context){
+ super(context);
+
+ // Create an OpenGL ES 2.0 context.
+ setEGLContextClientVersion(2);
+
+ setRenderer(new HelloOpenGLES20Renderer());
+ }
+}
+
+ This Activity class creates a basic container for a {@link android.opengl.GLSurfaceView}.
+HelloOpenGLES20Renderer, which implements the
+ {@link android.opengl.GLSurfaceView.Renderer} interface:
+
+
+package com.example.android.apis.graphics;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+public class HelloOpenGLES20Renderer implements GLSurfaceView.Renderer {
+
+ public void onSurfaceCreated(GL10 unused, EGLConfig config) {
+
+ // Set the background frame color
+ GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
+ }
+
+ public void onDrawFrame(GL10 unused) {
+
+ // Redraw background color
+ GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+ }
+
+ public void onSurfaceChanged(GL10 unused, int width, int height) {
+ GLES20.glViewport(0, 0, width, height);
+ }
+
+}
+
+ These classes create a simple Android application which displays a grey screen using OpenGL +ES 2.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 +2.0.
+ +If your application only supports OpenGL ES 2.0, then you should declare that your application + requires OpenGL ES 2.0 by adding the following settings to your AndroidManifest.xml file as +shown below.
+ ++... + </application> + + <!-- Tell the system that you need ES 2.0. --> + <uses-feature android:glEsVersion="0x00020000" android:required="true" /> + +</manifest> ++ +
Adding this declaration hides your application from devices that do not support OpenGL ES 2.0 +in the Android Market.
+ +If you are familiar with the OpenGL ES APIs, these preceding classes and the AndroidManifest.xml +declaration should give you enough information to start using the OpenGL ES 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.
+ + +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 +OpenGL ES 2.0 API.
+ +Note: The following instructions build on the previous section, so if you +have not been following along, go back to the previous section and catch +up.
+ +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.
+ +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.
+ +To define a vertex array for a triangle:
+ +HelloOpenGLES20Renderer class, add new member variable to contain the
+vertices of a triangle shape:
++ private FloatBuffer triangleVB; ++
initShapes() which populates this member variable:
+
+ 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);
+
+ }
+
+ This method defines a two-dimensional triangle shape with three equal sides.
+onSurfaceCreated() method to initialize your triangle:
+
+ public void onSurfaceCreated(GL10 unused, EGLConfig config) {
+
+ // Set the background frame color
+ GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
+
+ // initialize the triangle vertex array
+ initShapes();
+ }
+
+ Warning: Shapes and other static objects should be initialized
+ once in your onSurfaceCreated() method for best performance. Avoid initializing the
+ new objects in onDrawFrame(), as this causes the system to re-create the objects
+ for every frame redraw and slows down your application.
+
Now that you have defined a shape to draw, you can now use the OpenGL APIs to draw the + object. In order to do this with OpenGL ES 2.0, you must define a vertex shader and a +fragment shader to describe how to draw your shape.
+ +To draw the triangle with OpenGL:
+ +HelloOpenGLES20Renderer class, define a vertex shader and a fragment
+shader.
+
+ private final String vertexShaderCode =
+ "attribute vec4 vPosition; \n" +
+ "void main(){ \n" +
+ " gl_Position = vPosition; \n" +
+ "} \n";
+
+ private final String fragmentShaderCode =
+ "precision mediump float; \n" +
+ "void main(){ \n" +
+ " gl_FragColor = vec4 (0.63671875, 0.76953125, 0.22265625, 1.0); \n" +
+ "} \n";
+
+ HelloOpenGLES20Renderer class, create a method for loading the shaders.
+
+ private int loadShader(int type, String shaderCode){
+
+ int shader = GLES20.glCreateShader(type);
+
+ GLES20.glShaderSource(shader, shaderCode);
+ GLES20.glCompileShader(shader);
+
+ return shader;
+ }
+
+ HelloOpenGLES20Renderer class for an OpenGL
+Program.
++ private int mProgram; + private int maPositionHandle; ++
onSurfaceCreated() method to load the shaders and attach them to a
+OpenGL Program.
+
+ public void onSurfaceCreated(GL10 unused, EGLConfig config) {
+
+ // Set the background frame color
+ GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
+
+ // initialize the triangle vertex array
+ initShapes();
+
+ // Create shaders for shape and attach to program
+ int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
+ int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
+
+ mProgram = GLES20.glCreateProgram();
+ GLES20.glAttachShader(mProgram, vertexShader);
+ GLES20.glAttachShader(mProgram, fragmentShader);
+ GLES20.glLinkProgram(mProgram);
+
+ maPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
+ }
+
+ At this point, you are ready to draw the triangle object in the OpenGL frame.
+onDrawFrame() method to draw the triangle.
+
+ public void onDrawFrame(GL10 unused) {
+
+ // Redraw background color
+ GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+ // Specify a program with shaders
+ GLES20.glUseProgram(mProgram);
+
+ // Prepare the triangle data
+ GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 12, triangleVB);
+ GLES20.glEnableVertexAttribArray(maPositionHandle);
+
+ // Draw the triangle
+ GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
+ }
+
+ Note: 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 later section, we add motion to the object to + justify this use of processing power.
+Try running this example application on your emulator or test device and +you should see something like this:
+ +
+
+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 +next section.
+ +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.
+ +
+
+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.
+ +To use a projection transformation on your triangle:
+HelloOpenGLES20Renderer class.
++ private int muMVPMatrixHandle; + private float[] mMVPMatrix = new float[16]; + private float[] mMMatrix = new float[16]; + private float[] mVMatrix = new float[16]; + private float[] mProjMatrix = new float[16]; ++
vertexShaderCode string to add a variable for a model view
+projection matrix.
+
+ private final String vertexShaderCode =
+ "uniform mat4 uMVPMatrix; \n" +
+ "attribute vec4 vPosition; \n" +
+ "void main(){ \n" +
+ " gl_Position = uMVPMatrix * vPosition; \n" +
+ "} \n";
+
+ onSurfaceChanged() method to reference the uMVPMatrix
+shader variable you added and define a view transformation matrix.
+
+ public void onSurfaceCreated(GL10 unused, EGLConfig config) {
+ ...
+ maPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
+
+ muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
+ Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
+ }
+
+ onSurfaceChanged() method to calculate the device screen
+ration and create a projection matrix.
+
+ public void onSurfaceChanged(GL10 unused, int width, int height) {
+ GLES20.glViewport(0, 0, width, height);
+
+ float ratio = (float) width / height;
+ Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
+ }
+
+ onDrawFrame() method to apply the transformation.
+
+ public void onDrawFrame(GL10 unused) {
+ ...
+ // Apply a ModelView Projection transformation
+ Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
+ GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
+
+ // Draw the triangle
+ GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
+ }
+
+ Try running this updated application on your emulator or test device and you should see +something like this:
+ +
+
+Now that you have applied this transformation, the triangle has three equal sides, instead of the +squashed display in the earlier version.
+ + +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.
+ +To add rotation to your triangle:
+HelloOpenGLES20Renderer
+class.
+ + private float[] mMMatrix = new float[16]; ++
onDrawFrame() method to rotate the triangle object:
+
+ public void onDrawFrame(GL10 gl) {
+ ...
+
+ // Create a rotation for the triangle
+ long time = SystemClock.uptimeMillis() % 4000L;
+ float angle = 0.090f * ((int) time);
+ Matrix.setRotateM(mMMatrix, 0, angle, 0, 0, 1.0f);
+ Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
+ Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
+
+ // Apply a ModelView Projection transformation
+ //Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
+ GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
+
+ // Draw the triangle
+ ...
+ }
+
+ Run the application with this code and your triangle should rotate around its center.
+ + + +Be sure to check out the OpenGL ES code samples are available in the +API +Demos sample application and listed in Related Samples +sidebar above. +