diff --git a/docs/html/images/opengl/ogl-triangle-projected.png b/docs/html/images/opengl/ogl-triangle-projected.png index 4b18b98adda14..a561bc569c7f3 100644 Binary files a/docs/html/images/opengl/ogl-triangle-projected.png and b/docs/html/images/opengl/ogl-triangle-projected.png differ diff --git a/docs/html/images/opengl/ogl-triangle-touch.png b/docs/html/images/opengl/ogl-triangle-touch.png index 8323dd9e968f5..67c4466cd5fc4 100644 Binary files a/docs/html/images/opengl/ogl-triangle-touch.png and b/docs/html/images/opengl/ogl-triangle-touch.png differ diff --git a/docs/html/images/opengl/ogl-triangle.png b/docs/html/images/opengl/ogl-triangle.png index 66047ab1629ac..f51c0c6c1feaf 100644 Binary files a/docs/html/images/opengl/ogl-triangle.png and b/docs/html/images/opengl/ogl-triangle.png differ diff --git a/docs/html/training/graphics/opengl/draw.jd b/docs/html/training/graphics/opengl/draw.jd index ba00627cf6b1c..a5880662b05d7 100644 --- a/docs/html/training/graphics/opengl/draw.jd +++ b/docs/html/training/graphics/opengl/draw.jd @@ -50,13 +50,21 @@ android.opengl.GLSurfaceView.Renderer#onSurfaceCreated onSurfaceCreated()} metho for memory and processing efficiency.

-public void onSurfaceCreated(GL10 unused, EGLConfig config) {
-    ...
+public class MyGLRenderer implements GLSurfaceView.Renderer {
 
-    // initialize a triangle
-    mTriangle = new Triangle();
-    // initialize a square
-    mSquare = new Square();
+    ...
+    private Triangle mTriangle;
+    private Square   mSquare;
+
+    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
+        ...
+
+        // initialize a triangle
+        mTriangle = new Triangle();
+        // initialize a square
+        mSquare = new Square();
+    }
+    ...
 }
 
@@ -77,21 +85,27 @@ one or more shapes.

You need at least one vertex shader to draw a shape and one fragment shader to color that shape. These shaders must be complied and then added to an OpenGL ES program, which is then used to draw -the shape. Here is an example of how to define basic shaders you can use to draw a shape:

+the shape. Here is an example of how to define basic shaders you can use to draw a shape in the +Triangle class:

-private final String vertexShaderCode =
-    "attribute vec4 vPosition;" +
-    "void main() {" +
-    "  gl_Position = vPosition;" +
-    "}";
+public class Triangle {
 
-private final String fragmentShaderCode =
-    "precision mediump float;" +
-    "uniform vec4 vColor;" +
-    "void main() {" +
-    "  gl_FragColor = vColor;" +
-    "}";
+    private final String vertexShaderCode =
+        "attribute vec4 vPosition;" +
+        "void main() {" +
+        "  gl_Position = vPosition;" +
+        "}";
+
+    private final String fragmentShaderCode =
+        "precision mediump float;" +
+        "uniform vec4 vColor;" +
+        "void main() {" +
+        "  gl_FragColor = vColor;" +
+        "}";
+
+    ...
+}
 

Shaders contain OpenGL Shading Language (GLSL) code that must be compiled prior to using it in @@ -125,13 +139,28 @@ get created once and then cached for later use.

public class Triangle() { ... - int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); - int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); + private final int mProgram; - mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program - GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program - GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program - GLES20.glLinkProgram(mProgram); // creates OpenGL ES program executables + public Triangle() { + ... + + int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, + vertexShaderCode); + int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, + fragmentShaderCode); + + // create empty OpenGL ES Program + mProgram = GLES20.glCreateProgram(); + + // add the vertex shader to program + GLES20.glAttachShader(mProgram, vertexShader); + + // add the fragment shader to program + GLES20.glAttachShader(mProgram, fragmentShader); + + // creates OpenGL ES program executables + GLES20.glLinkProgram(mProgram); + } } @@ -145,6 +174,12 @@ color values to the shape’s vertex shader and fragment shader, and then execut function.

+private int mPositionHandle;
+private int mColorHandle;
+
+private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
+private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
+
 public void draw() {
     // Add program to OpenGL ES environment
     GLES20.glUseProgram(mProgram);
@@ -176,8 +211,17 @@ public void draw() {
 
 

Once you have all this code in place, drawing this object just requires a call to the {@code draw()} method from within your renderer’s {@link -android.opengl.GLSurfaceView.Renderer#onDrawFrame onDrawFrame()} method. When you run the -application, it should look something like this:

+android.opengl.GLSurfaceView.Renderer#onDrawFrame onDrawFrame()} method: + +
+public void onDrawFrame(GL10 unused) {
+    ...
+
+    mTriangle.draw();
+}
+
+ +

When you run the application, it should look something like this:

diff --git a/docs/html/training/graphics/opengl/environment.jd b/docs/html/training/graphics/opengl/environment.jd index 6b00c764f5e09..cf2b64ad80003 100644 --- a/docs/html/training/graphics/opengl/environment.jd +++ b/docs/html/training/graphics/opengl/environment.jd @@ -129,28 +129,22 @@ just create an inner class in the activity that uses it:

 class MyGLSurfaceView extends GLSurfaceView {
 
+    private final MyGLRenderer mRenderer;
+
     public MyGLSurfaceView(Context context){
         super(context);
 
+        // Create an OpenGL ES 2.0 context
+        setEGLContextClientVersion(2);
+
+        mRenderer = new MyGLRenderer();
+
         // Set the Renderer for drawing on the GLSurfaceView
-        setRenderer(new MyRenderer());
+        setRenderer(mRenderer);
     }
 }
 
-

When using OpenGL ES 2.0, you must add another call to your {@link android.opengl.GLSurfaceView} -constructor, specifying that you want to use the 2.0 API:

- -
-// Create an OpenGL ES 2.0 context
-setEGLContextClientVersion(2);
-
- -

Note: If you are using the OpenGL ES 2.0 API, make sure you declare -this in your application manifest. For more information, see Declare OpenGL ES -Use -in the Manifest.

-

One other optional addition to your {@link android.opengl.GLSurfaceView} implementation is to set the render mode to only draw the view when there is a change to your drawing data using the {@link android.opengl.GLSurfaceView#RENDERMODE_WHEN_DIRTY GLSurfaceView.RENDERMODE_WHEN_DIRTY} @@ -186,7 +180,7 @@ the geometry of the view changes, for example when the device's screen orientati

Here is a very basic implementation of an OpenGL ES renderer, that does nothing more than draw a -gray background in the {@link android.opengl.GLSurfaceView}:

+black background in the {@link android.opengl.GLSurfaceView}:

 public class MyGLRenderer implements GLSurfaceView.Renderer {
@@ -208,7 +202,7 @@ public class MyGLRenderer implements GLSurfaceView.Renderer {
 

That’s all there is to it! The code examples above create a simple Android application that -displays a gray screen using OpenGL. While this code does not do anything very interesting, by +displays a black screen using OpenGL. While this code does not do anything very interesting, by creating these classes, you have laid the foundation you need to start drawing graphic elements with OpenGL.

diff --git a/docs/html/training/graphics/opengl/motion.jd b/docs/html/training/graphics/opengl/motion.jd index fbcdd7fdfcc08..b026a4a31dbb0 100644 --- a/docs/html/training/graphics/opengl/motion.jd +++ b/docs/html/training/graphics/opengl/motion.jd @@ -45,16 +45,17 @@ to a shape with rotation.

Rotate a Shape

-

Rotating a drawing object with OpenGL ES 2.0 is relatively simple. You create another -transformation matrix (a rotation matrix) and then combine it with your projection and +

Rotating a drawing object with OpenGL ES 2.0 is relatively simple. In your renderer, create +another transformation matrix (a rotation matrix) and then combine it with your projection and camera view transformation matrices:

 private float[] mRotationMatrix = new float[16];
 public void onDrawFrame(GL10 gl) {
-    ...
     float[] scratch = new float[16];
 
+    ...
+
     // Create a rotation transformation for the triangle
     long time = SystemClock.uptimeMillis() % 4000L;
     float angle = 0.090f * ((int) time);
diff --git a/docs/html/training/graphics/opengl/projection.jd b/docs/html/training/graphics/opengl/projection.jd
index b09e74ce61ea4..356d5d42b792f 100644
--- a/docs/html/training/graphics/opengl/projection.jd
+++ b/docs/html/training/graphics/opengl/projection.jd
@@ -71,6 +71,11 @@ projection transformation {@link android.opengl.Matrix} using the {@link
 android.opengl.Matrix#frustumM Matrix.frustumM()} method:

+// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
+private final float[] mMVPMatrix = new float[16];
+private final float[] mProjectionMatrix = new float[16];
+private final float[] mViewMatrix = new float[16];
+
 @Override
 public void onSurfaceChanged(GL10 unused, int width, int height) {
     GLES20.glViewport(0, 0, width, height);
@@ -95,10 +100,10 @@ view transformation in order for anything to show up on screen.

Define a Camera View

Complete the process of transforming your drawn objects by adding a camera view transformation as -part of the drawing process. In the following example code, the camera view transformation is -calculated using the {@link android.opengl.Matrix#setLookAtM Matrix.setLookAtM()} method and then -combined with the previously calculated projection matrix. The combined transformation matrices -are then passed to the drawn shape.

+part of the drawing process in your renderer. In the following example code, the camera view +transformation is calculated using the {@link android.opengl.Matrix#setLookAtM Matrix.setLookAtM()} +method and then combined with the previously calculated projection matrix. The combined +transformation matrices are then passed to the drawn shape.

 @Override
@@ -119,7 +124,32 @@ public void onDrawFrame(GL10 unused) {
 

Apply Projection and Camera Transformations

In order to use the combined projection and camera view transformation matrix shown in the -previews sections, modify the {@code draw()} method of your graphic objects to accept the combined +previews sections, first add a matrix variable to the vertex shader previously defined +in the Triangle class:

+ +
+public class Triangle {
+
+    private final String vertexShaderCode =
+        // This matrix member variable provides a hook to manipulate
+        // the coordinates of the objects that use this vertex shader
+        "uniform mat4 uMVPMatrix;" +
+        "attribute vec4 vPosition;" +
+        "void main() {" +
+        // the matrix must be included as a modifier of gl_Position
+        // Note that the uMVPMatrix factor *must be first* in order
+        // for the matrix multiplication product to be correct.
+        "  gl_Position = uMVPMatrix * vPosition;" +
+        "}";
+
+    // Use to access and set the view transformation
+    private int mMVPMatrixHandle;
+
+    ...
+}
+
+ +

Next, modify the {@code draw()} method of your graphic objects to accept the combined transformation matrix and apply it to the shape:

@@ -127,14 +157,16 @@ public void draw(float[] mvpMatrix) { // pass in the calculated transformation m
     ...
 
     // get handle to shape's transformation matrix
-    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
+    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
 
     // Pass the projection and view transformation to the shader
-    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
+    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
 
     // Draw the triangle
     GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
-    ...
+
+    // Disable vertex array
+    GLES20.glDisableVertexAttribArray(mPositionHandle);
 }
 
diff --git a/docs/html/training/graphics/opengl/touch.jd b/docs/html/training/graphics/opengl/touch.jd index 4c9f0c77be554..089ede7b63dac 100644 --- a/docs/html/training/graphics/opengl/touch.jd +++ b/docs/html/training/graphics/opengl/touch.jd @@ -50,6 +50,10 @@ android.opengl.GLSurfaceView#onTouchEvent onTouchEvent()} to listen for touch ev an angle of rotation for a shape.

+private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
+private float mPreviousX;
+private float mPreviousY;
+
 @Override
 public boolean onTouchEvent(MotionEvent e) {
     // MotionEvent reports input details from the touch screen
@@ -77,7 +81,7 @@ public boolean onTouchEvent(MotionEvent e) {
 
             mRenderer.setAngle(
                     mRenderer.getAngle() +
-                    ((dx + dy) * TOUCH_SCALE_FACTOR);  // = 180.0f / 320
+                    ((dx + dy) * TOUCH_SCALE_FACTOR));
             requestRender();
     }
 
@@ -108,12 +112,22 @@ public MyGLSurfaceView(Context context) {
 

The example code above requires that you expose the rotation angle through your renderer by adding a public member. Since the renderer code is running on a separate thread from the main user interface thread of your application, you must declare this public variable as {@code volatile}. -Here is the code to do that:

+Here is the code to declare the variable and expose the getter and setter pair:

 public class MyGLRenderer implements GLSurfaceView.Renderer {
     ...
+
     public volatile float mAngle;
+
+    public float getAngle() {
+        return mAngle;
+    }
+
+    public void setAngle(float angle) {
+        mAngle = angle;
+    }
+}