Android OpenGLes 3.0学习:顶点绘制法 VBOs

移动开发 Android
目前只有android系统中只有android 4.3或以上支持opengles 3.0,但目前很多运行android 4.3系统的硬件能支持opengles 3.0的也是非常少的。不过幸好,opengles 3.0是向后兼容的,当程序发现硬件不支持opengles 3.0时则会自动调用opengles 2.0的API。

目前只有android系统中只有android 4.3或以上支持opengles 3.0,但目前很多运行android 4.3系统的硬件能支持opengles 3.0的也是非常少的。不过幸好,opengles 3.0是向后兼容的,当程序发现硬件不支持opengles 3.0时则会自动调用opengles 2.0的API。废话不多说了,开始进入正题,

实现过程:

1、在manifest中声明程序中使用opengles 3.0

如果程序中使用了纹理压缩的话,还需进行如下声明,以防止不支持这些压缩格式的设备尝试运行程序。

2、实现两个必不可少的类:GLSurfaceView和GLSurfaceView.Renderer

继承GLSurfaceView类的MySurfaceView.java

java代码

  1. package com.gl.gl30_vbos02; 
  2.  
  3.   import android.content.Context; 
  4.   import android.opengl.GLSurfaceView; 
  5.   import android.util.AttributeSet; 
  6.   import android.view.MotionEvent; 
  7.   public class MySurfaceView extends GLSurfaceView { 
  8.   private final float TOUCH_SCALE_FACOTOR = 180.0f / 320
  9.   private GLRender _render = new GLRender(); 
  10.   private float _preX = 0.0f; 
  11.   private float _preY = 0.0f; 
  12.   public MySurfaceView(Context context) 
  13.   { 
  14.   super(context); 
  15.   // TODO Auto-generated constructor stub 
  16.   setEGLContextClientVersion(2); 
  17.   this.setRenderer(_render); 
  18.   setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 
  19.   } 
  20.   public MySurfaceView(Context context, AttributeSet attrs) { 
  21.   super(context, attrs); 
  22.   // TODO Auto-generated constructor stub 
  23.   } 
  24.   @Override 
  25.   public boolean onTouchEvent(MotionEvent event) { 
  26.   // TODO Auto-generated method stub 
  27.   float x = event.getX(); 
  28.   float y = event.getY(); 
  29.   switch (event.getAction()) 
  30.   { 
  31.   case MotionEvent.ACTION_MOVE: 
  32.   float dx = x - _preX; 
  33.   float dy = y - _preY; 
  34.   _render.zrot = dx * TOUCH_SCALE_FACOTOR; 
  35.   _render.xrot = dy * TOUCH_SCALE_FACOTOR; 
  36.   this.requestRender(); 
  37.   break
  38.   default
  39.   break
  40.   } 
  41.   _preX = x; 
  42.   _preY = y; 
  43.   return true
  44.   } 
  45.   } 

实现GLSurfaceView.Renderer的GLRender.java:

java代码

  1. package com.gl.gl30_vbos02; 
  2.  
  3.   import java.nio.FloatBuffer; 
  4.   import javax.microedition.khronos.egl.EGLConfig; 
  5.   import javax.microedition.khronos.opengles.GL10; 
  6.   import android.opengl.GLES30; 
  7.   import android.opengl.GLSurfaceView.Renderer; 
  8.   import android.opengl.Matrix; 
  9.   import android.util.Log; 
  10.   //@TargetApi(18) 
  11.   public class GLRender implements Renderer { 
  12.   public float xrot, yrot, zrot; 
  13.   private static final String TAG = "GLRender"
  14.   private final float[] mProjMatrix = new float[16]; 
  15.   private final float[] mVMatrix = new float[16]; 
  16.   private final float[] mMVPMatrix = new float[16]; 
  17.   private final float[] mRotationMatrix = new float[16]; 
  18.   // private volatile float mAngle; 
  19.   private CirclePlane _circlePlane; 
  20.   //定义环境光 
  21.   private FloatBuffer lightAmbient = FloatBuffer.wrap(new float[]{0.5f, 0.5f, 
  22. 0.5f, 1.0f}); 
  23.   //定义漫散射 
  24.   private FloatBuffer lightDiffuse = FloatBuffer.wrap(new float[]{1.0f, 1.0f, 
  25. 1.0f, 1.0f}); 
  26.   //光源的位置 
  27.   private FloatBuffer lightPosition = FloatBuffer.wrap(new float[]{0.0f, 
  28. 0.0f, 2.0f, 1.0f}); 
  29.   public GLRender() { 
  30.   // TODO Auto-generated constructor stub 
  31.   } 
  32.   @Override 
  33.   public void onDrawFrame(GL10 gl_unused) { 
  34.   // TODO Auto-generated method stub 
  35.   //清楚屏幕和深度缓存 
  36.   GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | 
  37. GLES30.GL_DEPTH_BUFFER_BIT); 
  38.   Matrix.setLookAtM(mVMatrix, 000, -30.0f, 0.0f, 0.0f, 0.0f, 1.0f, 
  39. 0.0f); 
  40.   Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0); 
  41.   this._circlePlane.Draw(mMVPMatrix); 
  42.   } 
  43.   @Override 
  44.   public void onSurfaceChanged(GL10 gl_unused, int width, int height) { 
  45.   // TODO Auto-generated method stub 
  46.   float ratio = (float) width / height; 
  47.   //设置OPENGL视口 
  48.   GLES30.glViewport(00, width, height); 
  49.   //设置矩阵投影参数 
  50.   Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1137); 
  51.   } 
  52.   @Override 
  53.   public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
  54.   // TODO Auto-generated method stub 
  55.   //black background 
  56.   GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
  57.   this._circlePlane = new CirclePlane(10201.0f); 
  58.   } 
  59.   public static int loadShader(int type, String shaderCode) 
  60.   { 
  61.   // create a shader type (GLES30.GL_VERTEX_SHADER) 
  62.   // or a fragment shader type (GLES30.GL_FRAGMENT_SHADER) 
  63.   int shader = GLES30.glCreateShader(type); 
  64.   GLES30.glShaderSource(shader, shaderCode); 
  65.   GLES30.glCompileShader(shader); 
  66.   return shader; 
  67.   } 
  68.   public static void checkGLError(String glOperation) 
  69.   { 
  70.   int error; 
  71.   while((error = GLES30.glGetError()) != (GLES30.GL_NO_ERROR)) 
  72.   { 
  73.   Log.e(TAG, glOperation + ": glError " + error); 
  74.   throw new RuntimeException(glOperation + ": glError " + error); 
  75.   } 
  76.   } 
  77.   } 

要完成Opengl es工程,最重要是实现上面两个类。另外本程序为了绘制出图中的图案,还有四个类,可在附件中查看。:

CirclePlane.java //实现图案中顶点缓存,这个类有比较多的数学知识,不过只为了实现图案的话,不用理解其中数学算法问题也没关系。只要修改此类就可以绘制出不同的图案

Vertex3f.java //定义了顶点类型

Until.java //生成顶点缓存的公共工具类

OpenGLES30.java //工程的主类

附录

CirclePlane.java

java代码

  1. package com.gl.gl30_vbos02; 
  2.  
  3.   import java.nio.FloatBuffer; 
  4.   import android.opengl.GLES30; 
  5.   //@TargetApi(18) 
  6.   public class CirclePlane { 
  7.   static final int COORDS_PRE_VERTEX = 3
  8.   private final int vertexStride = COORDS_PRE_VERTEX * 4
  9.   private int vertexCount = 0
  10.   private int mRow = 10
  11.   private int mColumn = 20
  12.   private float mRadius = 1.0f; 
  13.   private FloatBuffer mPlaneBuffer; 
  14.   private final int mProgram; 
  15.   private int mPositionHandle; 
  16.   private int mColorHandle; 
  17.   private int mMVPMatrixHandle; 
  18.   // Set color with red, green, blue and alpha (opacity) values 
  19.   float color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; //白色不透明 
  20.   private final String vertexShaderCode = 
  21.   "uniform mat4 uMVPMatrix;" + 
  22.   "attribute vec4 vPosition;" + 
  23.   "void main()" + 
  24.   "{" + 
  25.   " gl_Position = vPosition * uMVPMatrix;" + 
  26.   "}"
  27.   private final String fragmentShaderCode = 
  28.   "precision mediump float;" + 
  29.   "uniform vec4 vColor;" + 
  30.   "void main()" + 
  31.   "{" + 
  32.   " gl_FragColor = vColor;" + 
  33.   "}"
  34.   public CirclePlane(int row, int column, float radius) 
  35.   { 
  36.   // TODO Auto-generated constructor stub 
  37.   this.mRow = row; 
  38.   this.mColumn = column; 
  39.   this.mRadius = radius; 
  40.   this.createGraphics(); 
  41.   int vertexShader = GLRender.loadShader(GLES30.GL_VERTEX_SHADER, 
  42. vertexShaderCode); 
  43.   int fragmentShader = GLRender.loadShader(GLES30.GL_FRAGMENT_SHADER, 
  44. fragmentShaderCode); 
  45.   this.mProgram = GLES30.glCreateProgram(); // create empty OpenGL 
  46. Program 
  47.   GLES30.glAttachShader(this.mProgram, vertexShader); // add the vertex 
  48. shader to program 
  49.   GLES30.glAttachShader(this.mProgram, fragmentShader); // add the fragment 
  50. shader to program 
  51.   GLES30.glLinkProgram(this.mProgram); // create OpenGL program 
  52. executables 
  53.   } 
  54.   private void createGraphics() 
  55.   { 
  56.   Vertex3f vertexs[][] = new Vertex3f[this.mRow][this.mColumn]; 
  57.   float intervalR = this.mRadius / this.mRow; 
  58.   Vertex3f centralPos = new Vertex3f(0.0f, 0.0f, 0.0f); 
  59.   for(int i=0;i 
  60.   { 
  61.   float tmpR = intervalR * i; 
  62.   for(int j=0;j 
  63.   { 
  64.   double angle = 2 * j * Math.PI / (this.mColumn - 1); 
  65.   vertexs[i][j] = new Vertex3f((float)(tmpR * Math.cos(angle)), (float)(tmpR 
  66. * Math.sin(angle)), centralPos.z); 
  67.   } 
  68.   } 
  69.   //创建三角形顶点 
  70.   int len = 2 * (this.mRow -1) * (this.mColumn - 1) * 3
  71.   this.vertexCount = len; 
  72.   Vertex3f tri[] = new Vertex3f[len]; 
  73.   int index = 0
  74.   for(int i=0;i 
  75.   { 
  76.   for(int j=0;j 
  77.   { 
  78.   tri[index] = vertexs[i][j]; 
  79.   tri[index+1] = vertexs[i+1][j]; 
  80.   tri[index+2] = vertexs[i+1][j+1]; 
  81.   tri[index+3] = vertexs[i][j]; 
  82.   tri[index+4] = vertexs[i+1][j+1]; 
  83.   tri[index+5] = vertexs[i+1][j]; 
  84.   index += 6
  85.   } 
  86.   } 
  87.   //设置顶点缓存 
  88.   float[] plane = new float[len*3]; 
  89.   for(int i=0;i 
  90.   { 
  91.   int vertexI = 3 * i; 
  92.   plane[vertexI] = tri[i].x; 
  93.   plane[vertexI+1] = tri[i].y; 
  94.   plane[vertexI+2] = tri[i].z; 
  95.   } 
  96.   this.mPlaneBuffer = Util.getFloatBuffer(plane); 
  97.   // plane = null; 
  98.   } 
  99.   public void Draw(float[] mvpMatrix) 
  100.   { 
  101.   GLES30.glUseProgram(this.mProgram); 
  102.   this.mPositionHandle = GLES30.glGetAttribLocation(this.mProgram, 
  103. "vPosition"); 
  104.   GLES30.glEnableVertexAttribArray(this.mPositionHandle); 
  105.   GLES30.glVertexAttribPointer(this.mPositionHandle, COORDS_PRE_VERTEX, 
  106.   GLES30.GL_FLOAT, falsethis.vertexStride, this.mPlaneBuffer); 
  107.   this.mColorHandle = GLES30.glGetUniformLocation(this.mProgram, 
  108. "vColor"); 
  109.   GLES30.glUniform4fv(this.mColorHandle, 1this.color, 0); 
  110.   this.mMVPMatrixHandle = GLES30.glGetUniformLocation(this.mProgram, 
  111. "uMVPMatrix"); 
  112.   GLRender.checkGLError("glGetUniformLocation"); 
  113.   GLES30.glUniformMatrix4fv(this.mMVPMatrixHandle, 1false, mvpMatrix, 
  114. 0); 
  115.   GLRender.checkGLError("glUniformMatrix4fv"); 
  116.   GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0this.vertexCount); 
  117.   GLES30.glDisableVertexAttribArray(this.mPositionHandle); 
  118.   // gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
  119.   // gl.glVertexPointer(3, GL10.GL_FLOAT, 0, this.mPlaneBuffer); 
  120.   // gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 
  121. (this.mRow-1)*(this.mColumn-1)*2*3); 
  122.   // 
  123.   // gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
  124.   // gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
  125.   // gl.glFinish(); 
  126.   } 
  127.   } 

Vertex3f.java

java代码

  1. package com.gl.gl30_vbos02; 
  2.  
  3.   public class Vertex3f { 
  4.   public float x = 0.0f; 
  5.   public float y = 0.0f; 
  6.   public float z = 0.0f; 
  7.   public Vertex3f(float x, float y, float z) 
  8.   { 
  9.   this.x = x; 
  10.   this.y = y; 
  11.   this.z = z; 
  12.   } 
  13.   } 

Until.java

java代码

  1. package com.gl.gl30_vbos02; 
  2.  
  3.   import java.nio.ByteBuffer; 
  4.   import java.nio.ByteOrder; 
  5.   import java.nio.FloatBuffer; 
  6.   import java.nio.IntBuffer; 
  7.   public class Util { 
  8.   //获取整形缓冲数据 
  9.   public static IntBuffer getIntBuffer(int[] vertexs) 
  10.   { 
  11.   IntBuffer buffer; 
  12.   ByteBuffer qbb = ByteBuffer.allocateDirect(vertexs.length * 4); 
  13.   qbb.order(ByteOrder.nativeOrder()); 
  14.   buffer = qbb.asIntBuffer(); 
  15.   buffer.put(vertexs); 
  16.   buffer.position(0); 
  17.   return buffer; 
  18.   } 
  19.   //获取浮点形缓冲数据 
  20.   public static FloatBuffer getFloatBuffer(float[] vertexs) 
  21.   { 
  22.   FloatBuffer buffer; 
  23.   ByteBuffer qbb = ByteBuffer.allocateDirect(vertexs.length * 4); 
  24.   qbb.order(ByteOrder.nativeOrder()); 
  25.   buffer = qbb.asFloatBuffer(); 
  26.   buffer.put(vertexs); 
  27.   buffer.position(0); 
  28.   return buffer; 
  29.   } 
  30.   //获取字节型缓冲数据 
  31.   public static ByteBuffer getByteBuffer(byte[] vertexs) 
  32.   { 
  33.   ByteBuffer buffer = null
  34.   buffer = ByteBuffer.allocateDirect(vertexs.length); 
  35.   buffer.put(vertexs); 
  36.   buffer.position(0); 
  37.   return buffer; 
  38.   } 
  39.   } 

OpenGLES30.java

java代码

  1. package com.gl.gl30_vbos02; 
  2.  
  3.   import android.opengl.GLSurfaceView; 
  4.   import android.os.Bundle; 
  5.   import android.app.Activity; 
  6.   import android.view.Menu; 
  7.   public class OpenGLES30 extends Activity { 
  8.   private GLSurfaceView mGL30View; 
  9.   @Override 
  10.   protected void onCreate(Bundle savedInstanceState) { 
  11.   super.onCreate(savedInstanceState); 
  12.   mGL30View = new MySurfaceView(this); 
  13.   setContentView(mGL30View); 
  14.   } 
  15.   @Override 
  16.   public boolean onCreateOptionsMenu(Menu menu) { 
  17.   // Inflate the menu; this adds items to the action bar if it is 
  18. present. 
  19.   getMenuInflater().inflate(R.menu.open_gles30, menu); 
  20.   return true
  21.   } 
  22.   @Override 
  23.   protected void onResume() { 
  24.   // TODO Auto-generated method stub 
  25.   super.onResume(); 
  26.   this.mGL30View.onResume(); 
  27.   } 
  28.   @Override 
  29.   protected void onPause() { 
  30.   // TODO Auto-generated method stub 
  31.   super.onPause(); 
  32.   this.mGL30View.onPause(); 
  33.   } 
  34.   } 

原文:http://bbs.9ria.com/thread-260180-1-1.html

责任编辑:闫佳明 来源: bbs.9ria
相关推荐

2013-04-15 14:23:21

2013-04-26 11:17:48

2013-07-25 09:32:26

OpenGL ESAndroid4.3

2019-08-05 13:20:35

Android绘制代码

2009-11-27 12:02:56

IT运维

2010-10-13 14:35:14

Android 3.0

2011-04-14 17:36:15

Android 3.0iPad佩奇

2011-02-03 10:10:49

Android3.0Android谷歌

2011-01-28 10:14:59

Android 3.0

2011-02-13 11:37:45

Android 3.0

2014-04-29 14:27:59

OpenGL ES 2Android绘制纹理

2020-08-25 09:50:35

Vue3.0命令前端

2013-04-26 10:26:08

2010-10-20 08:53:57

Android 3.0

2011-04-28 10:35:51

上网本东芝REGZA Table

2011-04-04 11:53:05

索尼平板电脑Android 3.0

2011-02-15 13:45:43

Android 3.0

2011-01-13 13:48:52

Android 3.0

2017-08-21 21:36:23

AndroidViewJava

2017-05-12 14:55:39

Android绘制刻度盘
点赞
收藏

51CTO技术栈公众号