Android OpenGLes 3.0學(xué)習(xí):頂點(diǎn)繪制法 VBOs
目前只有android系統(tǒng)中只有android 4.3或以上支持opengles 3.0,但目前很多運(yùn)行android 4.3系統(tǒng)的硬件能支持opengles 3.0的也是非常少的。不過幸好,opengles 3.0是向后兼容的,當(dāng)程序發(fā)現(xiàn)硬件不支持opengles 3.0時(shí)則會(huì)自動(dòng)調(diào)用opengles 2.0的API。廢話不多說了,開始進(jìn)入正題,
實(shí)現(xiàn)過程:
1、在manifest中聲明程序中使用opengles 3.0
如果程序中使用了紋理壓縮的話,還需進(jìn)行如下聲明,以防止不支持這些壓縮格式的設(shè)備嘗試運(yùn)行程序。
2、實(shí)現(xiàn)兩個(gè)必不可少的類: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;
- }
- }
實(shí)現(xiàn)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;
- //定義環(huán)境光
- 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;
- //設(shè)置OPENGL視口
- GLES30.glViewport(0, 0, width, height);
- //設(shè)置矩陣投影參數(shù)
- 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工程,最重要是實(shí)現(xiàn)上面兩個(gè)類。另外本程序?yàn)榱死L制出圖中的圖案,還有四個(gè)類,可在附件中查看。:
CirclePlane.java //實(shí)現(xiàn)圖案中頂點(diǎn)緩存,這個(gè)類有比較多的數(shù)學(xué)知識(shí),不過只為了實(shí)現(xiàn)圖案的話,不用理解其中數(shù)學(xué)算法問題也沒關(guān)系。只要修改此類就可以繪制出不同的圖案
Vertex3f.java //定義了頂點(diǎn)類型
Until.java //生成頂點(diǎn)緩存的公共工具類
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);
- }
- }
- //創(chuàng)建三角形頂點(diǎn)
- 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;
- }
- }
- //設(shè)置頂點(diǎn)緩存
- 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 {
- //獲取整形緩沖數(shù)據(jù)
- 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;
- }
- //獲取浮點(diǎn)形緩沖數(shù)據(jù)
- 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;
- }
- //獲取字節(jié)型緩沖數(shù)據(jù)
- 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