一般情況下數據都是有CPU從RAM取數據 然后傳給GPU去處理,相對於GPU速度要慢一些。
使用VBO技術 可以把數據存儲到GPU的內存空間中,這樣GPU可以直接從GPU的內存中取得數據進行處理 速度會提升很多。
使用VBO,主要有3個函數
glGenBuffers() 申請緩沖對象
glBindBuffer() 綁定緩沖對象
glBufferData() 需要緩沖的數據 存儲起來
下面演示用法
private int vboId[] = new int[1]; //頂點緩沖數據 void initVBO () { GLES30.glGenBuffers(1, vboId, 0);//申請一個緩沖區 GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboId[0]);//綁定緩沖區 GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4, vertexBuffer, GLES30.GL_STATIC_DRAW);//把數據存儲到GPU中 GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);//現在不使用這個緩沖區 }
vertexBuffer 數據被存儲到緩沖區中。
繪制的時候我們使用緩沖區的數據
void drawVBO () { GLES30.glUseProgram(programId); Matrix.setRotateM(GLRenderer.matrixs, 0, 0, 1, 0, 0); Matrix.translateM(GLRenderer.matrixs, 0, 0, 0, 1); GLRenderer.mViewPjMatrix = new float[16]; Matrix.multiplyMM(GLRenderer.mViewPjMatrix, 0, GLRenderer.viewMatrix,0, GLRenderer.matrixs, 0); Matrix.multiplyMM(GLRenderer.mViewPjMatrix, 0, GLRenderer.projMatrix,0, GLRenderer.mViewPjMatrix, 0); GLES30.glUniformMatrix4fv(mVPMatrixHandle, 1, false, GLRenderer.mViewPjMatrix, 0);
//begin GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboId[0]);//綁定存在的VBO GLES30.glEnableVertexAttribArray(0);//開啟頂點 GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 0, 0);//頂點XYZ,三個點,使用GPU中的緩沖數據,不再從RAM中取數據,所以后面的2個參數都是0
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);//數據已經得到 就可以不再使用這個綁定了 GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 6);//從頂點緩存中繪制數據 }
對於大量的頂點,比如繪制一個3D汽車, 使用緩沖數據方式 能提高速度。
下面補充缺失的代碼。
final static float vertices1[] = new float[] { -1,1,0, -0.5f,0,0, 0,-1,0, -1,0,0, 0.5f,0,0, 1,-1,0 }; ByteBuffer vb = ByteBuffer.allocateDirect(vertices1.length * 4); vb.order(ByteOrder.nativeOrder()); vertexBuffer = vb.asFloatBuffer(); vertexBuffer.put(vertices1); vertexBuffer.position(0);
Note: initVBO方法需要在onSurfaceCreate中初始化
腳本如下
public static final String fragment5 =
"#version 300 es \n" +
"precision mediump float;\n"
+ "in vec2 vTextureCoord;\n"
+ "out vec4 v_color;\n"
+ "void main() { \n"
+ "v_color = vec4(1.0,1.0,1.0,0.0); \n"
+ "}\n"
;
public static final String vertex3 =
"#version 300 es \n" +
"uniform mat4 uMVPMatrix;\n"
+ "layout(location = 0) in vec3 aPosition;\n"
+ "layout(location = 1) in vec2 aTexCoor;\n"
+ "out vec2 vTextureCoord;\n"
+ "void main() { \n"
+ "gl_Position = uMVPMatrix * vec4(aPosition,1);\n"
+ "gl_PointSize = 20.0;\n"
+ "vTextureCoord = aTexCoor;\n"
+ "}\n"
;
package com.example.gles300; import java.io.IOException; import java.io.InputStream; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLES30; import android.opengl.GLSurfaceView.Renderer; import android.opengl.GLUtils; import android.opengl.Matrix; import android.util.Log; /** * @author gaofeng * */ public class GLRenderer implements Renderer { public static float[] projMatrix = new float[16]; public static float[] viewMatrix = new float[16]; public static float[] mViewPjMatrix; public static float[] matrixs = new float[16]; public static int textureId = -1; public Context context; public MyDrawModel drawModel; public void setContext(Context context) { this.context = context; } public GLRenderer() { } @Override public void onDrawFrame(GL10 arg0) { GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT); drawModel.drawVBO(); } @Override public void onSurfaceChanged(GL10 arg0, int w, int h) { GLES30.glViewport(0, 0, w, h); float ratio = (float) w / h; Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1, 1, 1, 10); Matrix.setLookAtM(viewMatrix, 0, 0, 0, 3, 0, 0, 0, 0.0f, 1.0f, 0.0f); } @Override public void onSurfaceCreated(GL10 g, EGLConfig eglConfig) { GLES30.glClearColor(0.0f,0.0f,0.0f, 0.0f); GLES30.glEnable(GLES30.GL_DEPTH_TEST); InputStream ins = null; drawModel = new MyDrawModel(); drawModel.init(); GLES30.glDisable(GLES30.GL_CULL_FACE); } }
顯示繪制了一個三角形

