目前只有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代码
- package com.gl.gl30_vbos02;
- import android.content.Context;
- import android.opengl.GLSurfaceView;
- import android.util.AttributeSet;
- import android.view.MotionEvent;
- public class MySurfaceView extends GLSurfaceView {
- private final float TOUCH_SCALE_FACOTOR = 180.0f / 320;
- private GLRender _render = new GLRender();
- private float _preX = 0.0f;
- private float _preY = 0.0f;
- public MySurfaceView(Context context)
- {
- super(context);
- // TODO Auto-generated constructor stub
- setEGLContextClientVersion(2);
- this.setRenderer(_render);
- setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
- }
- public MySurfaceView(Context context, AttributeSet attrs) {
- super(context, attrs);
- // TODO Auto-generated constructor stub
- }
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- // TODO Auto-generated method stub
- float x = event.getX();
- float y = event.getY();
- switch (event.getAction())
- {
- case MotionEvent.ACTION_MOVE:
- float dx = x - _preX;
- float dy = y - _preY;
- _render.zrot = dx * TOUCH_SCALE_FACOTOR;
- _render.xrot = dy * TOUCH_SCALE_FACOTOR;
- this.requestRender();
- break;
- default:
- break;
- }
- _preX = x;
- _preY = y;
- return true;
- }
- }
实现GLSurfaceView.Renderer的GLRender.java:
java代码
- package com.gl.gl30_vbos02;
- import java.nio.FloatBuffer;
- import javax.microedition.khronos.egl.EGLConfig;
- import javax.microedition.khronos.opengles.GL10;
- import android.opengl.GLES30;
- import android.opengl.GLSurfaceView.Renderer;
- import android.opengl.Matrix;
- import android.util.Log;
- //@TargetApi(18)
- public class GLRender implements Renderer {
- public float xrot, yrot, zrot;
- private static final String TAG = "GLRender";
- private final float[] mProjMatrix = new float[16];
- private final float[] mVMatrix = new float[16];
- private final float[] mMVPMatrix = new float[16];
- private final float[] mRotationMatrix = new float[16];
- // private volatile float mAngle;
- private CirclePlane _circlePlane;
- //定义环境光
- private FloatBuffer lightAmbient = FloatBuffer.wrap(new float[]{0.5f, 0.5f,
- 0.5f, 1.0f});
- //定义漫散射
- private FloatBuffer lightDiffuse = FloatBuffer.wrap(new float[]{1.0f, 1.0f,
- 1.0f, 1.0f});
- //光源的位置
- private FloatBuffer lightPosition = FloatBuffer.wrap(new float[]{0.0f,
- 0.0f, 2.0f, 1.0f});
- public GLRender() {
- // TODO Auto-generated constructor stub
- }
- @Override
- public void onDrawFrame(GL10 gl_unused) {
- // TODO Auto-generated method stub
- //清楚屏幕和深度缓存
- GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT |
- GLES30.GL_DEPTH_BUFFER_BIT);
- Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
- 0.0f);
- Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
- this._circlePlane.Draw(mMVPMatrix);
- }
- @Override
- public void onSurfaceChanged(GL10 gl_unused, int width, int height) {
- // TODO Auto-generated method stub
- float ratio = (float) width / height;
- //设置OPENGL视口
- GLES30.glViewport(0, 0, width, height);
- //设置矩阵投影参数
- Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
- }
- @Override
- public void onSurfaceCreated(GL10 gl, EGLConfig config) {
- // TODO Auto-generated method stub
- //black background
- GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- this._circlePlane = new CirclePlane(10, 20, 1.0f);
- }
- public static int loadShader(int type, String shaderCode)
- {
- // create a shader type (GLES30.GL_VERTEX_SHADER)
- // or a fragment shader type (GLES30.GL_FRAGMENT_SHADER)
- int shader = GLES30.glCreateShader(type);
- GLES30.glShaderSource(shader, shaderCode);
- GLES30.glCompileShader(shader);
- return shader;
- }
- public static void checkGLError(String glOperation)
- {
- int error;
- while((error = GLES30.glGetError()) != (GLES30.GL_NO_ERROR))
- {
- Log.e(TAG, glOperation + ": glError " + error);
- throw new RuntimeException(glOperation + ": glError " + error);
- }
- }
- }
要完成Opengl es工程,最重要是实现上面两个类。另外本程序为了绘制出图中的图案,还有四个类,可在附件中查看。:
CirclePlane.java //实现图案中顶点缓存,这个类有比较多的数学知识,不过只为了实现图案的话,不用理解其中数学算法问题也没关系。只要修改此类就可以绘制出不同的图案
Vertex3f.java //定义了顶点类型
Until.java //生成顶点缓存的公共工具类
OpenGLES30.java //工程的主类
附录
CirclePlane.java
java代码
- package com.gl.gl30_vbos02;
- import java.nio.FloatBuffer;
- import android.opengl.GLES30;
- //@TargetApi(18)
- public class CirclePlane {
- static final int COORDS_PRE_VERTEX = 3;
- private final int vertexStride = COORDS_PRE_VERTEX * 4;
- private int vertexCount = 0;
- private int mRow = 10;
- private int mColumn = 20;
- private float mRadius = 1.0f;
- private FloatBuffer mPlaneBuffer;
- private final int mProgram;
- private int mPositionHandle;
- private int mColorHandle;
- private int mMVPMatrixHandle;
- // Set color with red, green, blue and alpha (opacity) values
- float color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; //白色不透明
- private final String vertexShaderCode =
- "uniform mat4 uMVPMatrix;" +
- "attribute vec4 vPosition;" +
- "void main()" +
- "{" +
- " gl_Position = vPosition * uMVPMatrix;" +
- "}";
- private final String fragmentShaderCode =
- "precision mediump float;" +
- "uniform vec4 vColor;" +
- "void main()" +
- "{" +
- " gl_FragColor = vColor;" +
- "}";
- public CirclePlane(int row, int column, float radius)
- {
- // TODO Auto-generated constructor stub
- this.mRow = row;
- this.mColumn = column;
- this.mRadius = radius;
- this.createGraphics();
- int vertexShader = GLRender.loadShader(GLES30.GL_VERTEX_SHADER,
- vertexShaderCode);
- int fragmentShader = GLRender.loadShader(GLES30.GL_FRAGMENT_SHADER,
- fragmentShaderCode);
- this.mProgram = GLES30.glCreateProgram(); // create empty OpenGL
- Program
- GLES30.glAttachShader(this.mProgram, vertexShader); // add the vertex
- shader to program
- GLES30.glAttachShader(this.mProgram, fragmentShader); // add the fragment
- shader to program
- GLES30.glLinkProgram(this.mProgram); // create OpenGL program
- executables
- }
- private void createGraphics()
- {
- Vertex3f vertexs[][] = new Vertex3f[this.mRow][this.mColumn];
- float intervalR = this.mRadius / this.mRow;
- Vertex3f centralPos = new Vertex3f(0.0f, 0.0f, 0.0f);
- for(int i=0;i
- {
- float tmpR = intervalR * i;
- for(int j=0;j
- {
- double angle = 2 * j * Math.PI / (this.mColumn - 1);
- vertexs[i][j] = new Vertex3f((float)(tmpR * Math.cos(angle)), (float)(tmpR
- * Math.sin(angle)), centralPos.z);
- }
- }
- //创建三角形顶点
- int len = 2 * (this.mRow -1) * (this.mColumn - 1) * 3;
- this.vertexCount = len;
- Vertex3f tri[] = new Vertex3f[len];
- int index = 0;
- for(int i=0;i
- {
- for(int j=0;j
- {
- tri[index] = vertexs[i][j];
- tri[index+1] = vertexs[i+1][j];
- tri[index+2] = vertexs[i+1][j+1];
- tri[index+3] = vertexs[i][j];
- tri[index+4] = vertexs[i+1][j+1];
- tri[index+5] = vertexs[i+1][j];
- index += 6;
- }
- }
- //设置顶点缓存
- float[] plane = new float[len*3];
- for(int i=0;i
- {
- int vertexI = 3 * i;
- plane[vertexI] = tri[i].x;
- plane[vertexI+1] = tri[i].y;
- plane[vertexI+2] = tri[i].z;
- }
- this.mPlaneBuffer = Util.getFloatBuffer(plane);
- // plane = null;
- }
- public void Draw(float[] mvpMatrix)
- {
- GLES30.glUseProgram(this.mProgram);
- this.mPositionHandle = GLES30.glGetAttribLocation(this.mProgram,
- "vPosition");
- GLES30.glEnableVertexAttribArray(this.mPositionHandle);
- GLES30.glVertexAttribPointer(this.mPositionHandle, COORDS_PRE_VERTEX,
- GLES30.GL_FLOAT, false, this.vertexStride, this.mPlaneBuffer);
- this.mColorHandle = GLES30.glGetUniformLocation(this.mProgram,
- "vColor");
- GLES30.glUniform4fv(this.mColorHandle, 1, this.color, 0);
- this.mMVPMatrixHandle = GLES30.glGetUniformLocation(this.mProgram,
- "uMVPMatrix");
- GLRender.checkGLError("glGetUniformLocation");
- GLES30.glUniformMatrix4fv(this.mMVPMatrixHandle, 1, false, mvpMatrix,
- 0);
- GLRender.checkGLError("glUniformMatrix4fv");
- GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, this.vertexCount);
- GLES30.glDisableVertexAttribArray(this.mPositionHandle);
- // gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
- // gl.glVertexPointer(3, GL10.GL_FLOAT, 0, this.mPlaneBuffer);
- // gl.glDrawArrays(GL10.GL_TRIANGLES, 0,
- (this.mRow-1)*(this.mColumn-1)*2*3);
- //
- // gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
- // gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
- // gl.glFinish();
- }
- }
Vertex3f.java
java代码
- package com.gl.gl30_vbos02;
- public class Vertex3f {
- public float x = 0.0f;
- public float y = 0.0f;
- public float z = 0.0f;
- public Vertex3f(float x, float y, float z)
- {
- this.x = x;
- this.y = y;
- this.z = z;
- }
- }
Until.java
java代码
- package com.gl.gl30_vbos02;
- import java.nio.ByteBuffer;
- import java.nio.ByteOrder;
- import java.nio.FloatBuffer;
- import java.nio.IntBuffer;
- public class Util {
- //获取整形缓冲数据
- public static IntBuffer getIntBuffer(int[] vertexs)
- {
- IntBuffer buffer;
- ByteBuffer qbb = ByteBuffer.allocateDirect(vertexs.length * 4);
- qbb.order(ByteOrder.nativeOrder());
- buffer = qbb.asIntBuffer();
- buffer.put(vertexs);
- buffer.position(0);
- return buffer;
- }
- //获取浮点形缓冲数据
- public static FloatBuffer getFloatBuffer(float[] vertexs)
- {
- FloatBuffer buffer;
- ByteBuffer qbb = ByteBuffer.allocateDirect(vertexs.length * 4);
- qbb.order(ByteOrder.nativeOrder());
- buffer = qbb.asFloatBuffer();
- buffer.put(vertexs);
- buffer.position(0);
- return buffer;
- }
- //获取字节型缓冲数据
- public static ByteBuffer getByteBuffer(byte[] vertexs)
- {
- ByteBuffer buffer = null;
- buffer = ByteBuffer.allocateDirect(vertexs.length);
- buffer.put(vertexs);
- buffer.position(0);
- return buffer;
- }
- }
OpenGLES30.java
java代码
- package com.gl.gl30_vbos02;
- import android.opengl.GLSurfaceView;
- import android.os.Bundle;
- import android.app.Activity;
- import android.view.Menu;
- public class OpenGLES30 extends Activity {
- private GLSurfaceView mGL30View;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mGL30View = new MySurfaceView(this);
- setContentView(mGL30View);
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is
- present.
- getMenuInflater().inflate(R.menu.open_gles30, menu);
- return true;
- }
- @Override
- protected void onResume() {
- // TODO Auto-generated method stub
- super.onResume();
- this.mGL30View.onResume();
- }
- @Override
- protected void onPause() {
- // TODO Auto-generated method stub
- super.onPause();
- this.mGL30View.onPause();
- }
- }
原文:http://bbs.9ria.com/thread-260180-1-1.html