Android OpenGL ES 2.0 (一) 画三角形

看Opengl es的相关知识也有几天了。开始动手跟着例子写代码了。现在就先写个最简单的,画个三角形吧,里面包含了最基本的vertex shader和fragment shader的用法.

Activity里设置opengl es版本为2.0,如果没设,会默认用1.0,然后运行会报API未实现exception.

TestActivity.java

 1 package com.android.jayce.test;
 2 
 3 import android.app.Activity;
 4 import android.app.ActivityManager;
 5 import android.content.Context;
 6 import android.content.pm.ConfigurationInfo;
 7 import android.opengl.GLSurfaceView;
 8 import android.opengl.GLSurfaceView.Renderer;
 9 import android.os.Bundle;
10 
11 public class TestActivity extends Activity
12 {
13     private GLSurfaceView mGLSurfaceView;
14     
15     public void onCreate(Bundle savedInstanceState)
16     {
17         super.onCreate(savedInstanceState);
18         mGLSurfaceView = new GLSurfaceView(this);
19         final ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
20         final ConfigurationInfo configInfo = activityManager.getDeviceConfigurationInfo();
21         if(configInfo.reqGlEsVersion >= 0x20000)
22         {
23             mGLSurfaceView.setEGLContextClientVersion(2);
24             Renderer renderer = new TestRenderer();
25             mGLSurfaceView.setRenderer(renderer);
26         }
27         
28         setContentView(mGLSurfaceView);
29     }
30     
31     @Override
32     protected void onResume() 
33     {
34         // The activity must call the GL surface view's onResume() on activity onResume().
35         super.onResume();
36         mGLSurfaceView.onResume();
37     }
38 
39     @Override
40     protected void onPause() 
41     {
42         // The activity must call the GL surface view's onPause() on activity onPause().
43         super.onPause();
44         mGLSurfaceView.onPause();
45     }    
46 }

然后是Renderer的实现,参数很少,只有点坐标,颜色

TestRenderer.java

  1 package com.android.jayce.test;
  2 
  3 import java.nio.ByteBuffer;
  4 import java.nio.ByteOrder;
  5 import java.nio.FloatBuffer;
  6 
  7 import javax.microedition.khronos.egl.EGLConfig;
  8 import javax.microedition.khronos.opengles.GL10;
  9 
 10 import android.opengl.GLES20;
 11 import android.opengl.Matrix;
 12 import android.opengl.GLSurfaceView;
 13 
 14 
 15 public class TestRenderer implements GLSurfaceView.Renderer
 16 {
 17 
 18     private final FloatBuffer mTriangle1Vertices;
 19     private static final int BYTES_PER_FLOAT = 4;
 20     private float[] mMVPMatrix = new float[16];
 21     private float[] mViewMatrix = new float[16];
 22     private float[] mModelMatrix = new float[16];
 23     private float[] mProjectionMatrix = new float[16];
 24     private int mMVPMatrixHandle;
 25     private int mPositionHandle;
 26     private int mColorHandle;
 27     private final int POSITION_OFFSET = 0;
 28     private final int COLOR_OFFSET = 3;
 29     private final int POSITION_DATA_SIZE = 3;
 30     private final int COLOR_DATA_SIZE = 4;
 31     private final int STRIDE = 7 * BYTES_PER_FLOAT;
 32     
 33     public TestRenderer()
 34     {
 35         final float[] triangle1VerticesData = {
 36                 // X, Y, Z, 
 37                 // R, G, B, A
 38                 -0.5f, -0.25f, 0.0f, 
 39                 1.0f, 0.0f, 0.0f, 1.0f,
 40                 
 41                 0.5f, -0.25f, 0.0f,
 42                 0.0f, 0.0f, 1.0f, 1.0f,
 43                 
 44                 0.0f, 0.559016994f, 0.0f, 
 45                 0.0f, 1.0f, 0.0f, 1.0f};
 46         
 47         mTriangle1Vertices = ByteBuffer.allocateDirect(triangle1VerticesData.length * BYTES_PER_FLOAT)
 48                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
 49         mTriangle1Vertices.put(triangle1VerticesData).position(0);
 50     }
 51     
 52     @Override
 53     public void onDrawFrame(GL10 gl) {
 54         // TODO Auto-generated method stub
 55         GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
 56         
 57         Matrix.setIdentityM(mModelMatrix, 0);
 58         drawTriandle(mTriangle1Vertices);
 59     }
 60 
 61     private void drawTriandle(final FloatBuffer triangleBuffer)
 62     {
 63         triangleBuffer.position(POSITION_OFFSET);
 64         GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20.GL_FLOAT, false, STRIDE, triangleBuffer);
 65         GLES20.glEnableVertexAttribArray(mPositionHandle);
 66         
 67         triangleBuffer.position(COLOR_OFFSET);
 68         GLES20.glVertexAttribPointer(mColorHandle, COLOR_DATA_SIZE, GLES20.GL_FLOAT, false, STRIDE, triangleBuffer);
 69         GLES20.glEnableVertexAttribArray(mColorHandle);
 70         
 71         Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
 72         Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
 73         
 74         GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
 75         GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
 76     }
 77     
 78     @Override
 79     public void onSurfaceChanged(GL10 gl, int width, int height) {
 80         // TODO Auto-generated method stub
 81         GLES20.glViewport(0, 0, width, height);
 82         
 83         final float ratio = (float) width / height;
 84         final float left = -ratio;
 85         final float right = ratio;
 86         final float bottom = -1.0f;
 87         final float top = 1.0f;
 88         final float near = 1.0f;
 89         final float far = 10.0f;
 90         
 91         Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
 92     }
 93 
 94     @Override
 95     public void onSurfaceCreated(GL10 gl, EGLConfig config) {
 96         // TODO Auto-generated method stub
 97         GLES20.glClearColor(0f, 0f, 0f, 1f);
 98         
 99         // Position the eye behind the origin.
100         final float eyeX = 0.0f;
101         final float eyeY = 0.0f;
102         final float eyeZ = 1.5f;
103 
104         // We are looking toward the distance
105         final float lookX = 0.0f;
106         final float lookY = 0.0f;
107         final float lookZ = -5.0f;
108 
109         // Set our up vector. This is where our head would be pointing were we holding the camera.
110         final float upX = 0.0f;
111         final float upY = 1.0f;
112         final float upZ = 0.0f;
113 
114         // Set the view matrix. This matrix can be said to represent the camera position.
115         // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
116         // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
117         Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
118         
119         final String vertexShader =
120                 "uniform mat4 u_MVPMatrix;      \n"        // A constant representing the combined model/view/projection matrix.
121                 
122               + "attribute vec4 a_Position;     \n"        // Per-vertex position information we will pass in.
123               + "attribute vec4 a_Color;        \n"        // Per-vertex color information we will pass in.              
124               
125               + "varying vec4 v_Color;          \n"        // This will be passed into the fragment shader.
126               
127               + "void main()                    \n"        // The entry point for our vertex shader.
128               + "{                              \n"
129               + "   v_Color = a_Color;          \n"        // Pass the color through to the fragment shader. 
130                                                           // It will be interpolated across the triangle.
131               + "   gl_Position = u_MVPMatrix   \n"     // gl_Position is a special variable used to store the final position.
132               + "               * a_Position;   \n"     // Multiply the vertex by the matrix to get the final point in                                                                      
133               + "}                              \n";    // normalized screen coordinates.
134             
135         final String fragmentShader =
136                 "precision mediump float;       \n"        // Set the default precision to medium. We don't need as high of a 
137                                                         // precision in the fragment shader.                
138               + "varying vec4 v_Color;          \n"        // This is the color from the vertex shader interpolated across the 
139                                                           // triangle per fragment.              
140               + "void main()                    \n"        // The entry point for our fragment shader.
141               + "{                              \n"
142               + "   gl_FragColor = v_Color;     \n"        // Pass the color directly through the pipeline.          
143               + "}                              \n";    
144             
145         int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
146         if(vertexShaderHandle != 0)
147         {
148             GLES20.glShaderSource(vertexShaderHandle, vertexShader);
149             GLES20.glCompileShader(vertexShaderHandle);
150             
151             final int[] compileStatus = new int[1];
152             GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
153             
154             if(compileStatus[0] == 0)
155             {
156                 GLES20.glDeleteShader(vertexShaderHandle);
157                 vertexShaderHandle = 0;
158             }
159         }
160         
161         if(vertexShaderHandle == 0)
162         {
163             throw new RuntimeException("failed to creating vertex shader");
164         }
165         
166         int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
167         if(fragmentShaderHandle != 0)
168         {
169             GLES20.glShaderSource(fragmentShaderHandle, fragmentShader);
170             GLES20.glCompileShader(fragmentShaderHandle);
171             
172             final int[] compileStatus = new int[1];
173             GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
174             
175             if(compileStatus[0] == 0)
176             {
177                 GLES20.glDeleteShader(fragmentShaderHandle);
178                 fragmentShaderHandle = 0;
179             }
180             
181         }
182         
183         if(fragmentShaderHandle == 0)
184         {
185             throw new RuntimeException("failed to create fragment shader");
186         }
187         
188         int programHandle = GLES20.glCreateProgram();
189         if(programHandle != 0)
190         {
191             GLES20.glAttachShader(programHandle, vertexShaderHandle);
192             GLES20.glAttachShader(programHandle, fragmentShaderHandle);
193             
194             GLES20.glBindAttribLocation(programHandle, 0, "a_Position");
195             GLES20.glBindAttribLocation(programHandle, 1, "a_Color");
196             
197             GLES20.glLinkProgram(programHandle);
198             
199             final int[] linkStatus = new int[1];
200             GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
201             
202             if(linkStatus[0] == 0)
203             {
204                 GLES20.glDeleteProgram(programHandle);
205                 programHandle = 0;
206             }
207         }
208         
209         if(programHandle == 0)
210         {
211             throw new RuntimeException("failed to create program");
212         }
213         
214         mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVPMatrix");
215         mPositionHandle = GLES20.glGetAttribLocation(programHandle, "a_Position");
216         mColorHandle = GLES20.glGetAttribLocation(programHandle, "a_Color");
217         
218         GLES20.glUseProgram(programHandle);
219     }
220 
221     
222     
223 }

最后附上效果图:

原文地址:https://www.cnblogs.com/jayceli/p/2473203.html