Vertex Buffer Object 顶点缓存对象
不使用VBO时,我们每次绘制( glDrawArrays )图形时都是从本地内存处获取顶点数据然后传输给OpenGL来绘制,使用VBO,我们就能把顶点数据缓存到GPU的显存中,直接从显存中获取数据,这样就能提升绘制的效率。
1、创建VBO
GLES20.glGenBuffers(1, vbos, 0);
2、绑定VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbos[0]);
3、分配VBO需要的缓存大小
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertex.length * 4,null, GLES20. GL_STATIC_DRAW);
4、为VBO设置顶点数据的值
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, vertexData.length * 4, vertexBuffer);
5、解绑VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
1、绑定VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbos[0]);
2、设置顶点数据
GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8, 0);
3、解绑VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
package com.example.opengl.eglpic;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import com.example.opengl.R;
import com.example.opengl.egl.MyGlSurfaceView;
import com.example.opengl.egl.ShaderUtil;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
public class PicRender implements MyGlSurfaceView.EGLRender {
private Context context;
//顶点坐标
private float[] vertexData = {
-1f, -1f,
1f, -1f,
-1f, 1f,
1f, 1f
};
private FloatBuffer vertexBuffer;
//纹理坐标
private float[] fragmentData = {
0f, 1f,
1f, 1f,
0f, 0f,
1f, 0f
};
private FloatBuffer fragmentBuffer;
//生成的shader程序
private int program;
//顶点坐标
private int vPosition;
//纹理坐标
private int fPosition;
//纹理的id
private int textureId;
private int sampler;
//vbo
private int vboId;
public PicRender(Context context) {
this.context = context;
vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)//4个字节
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(vertexData);
vertexBuffer.position(0);
fragmentBuffer = ByteBuffer.allocateDirect(fragmentData.length * 4)//4个字节
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(fragmentData);
fragmentBuffer.position(0);
}
/**
* OpenGl
*/
@Override
public void onSurfaceCreated() {
//读取shader的源码
String vertexSource = ShaderUtil.readRawTxt(context, R.raw.vertex_shader);
String fragmentSource = ShaderUtil.readRawTxt(context, R.raw.fragment_shader);
//创建shader程序
program = ShaderUtil.createProgram(vertexSource, fragmentSource);
vPosition = GLES20.glGetAttribLocation(program, "v_Position");
fPosition = GLES20.glGetAttribLocation(program, "f_Position");
sampler = GLES20.glGetUniformLocation(program, "sTexture");
int[] vbos = new int[1];
//创建vbo,生成一个,偏移量为0
GLES20.glGenBuffers(1, vbos, 0);
vboId = vbos[0];
//绑定vbo
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
//分配VBO需要的缓存大小,data=null是只需要申请空间,暂时不赋值
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4 + fragmentData.length * 4, null, GLES20.GL_STATIC_DRAW);
//为VBO设置顶点数据的值
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, vertexData.length * 4, vertexBuffer);
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4, fragmentData.length * 4, fragmentBuffer);
//解绑vbo
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
int[] textureIds = new int[1];
GLES20.glGenTextures(1, textureIds, 0);
textureId = textureIds[0];
//绑定
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
//激活第0个
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
//绑定sampler和0
GLES20.glUniform1i(sampler, 0);
//设置环绕方式
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
//设置过滤
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
//得到图片
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.photo);
//图片绑定到纹理
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
//回收
bitmap.recycle();
bitmap = null;
//解绑
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
}
@Override
public void onSurfaceChanged(int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame() {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClearColor(1f, 0f, 0f, 1f);
//使用shader程序
GLES20.glUseProgram(program);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
//使用vbo,绑定,在顶点和纹理赋值之前
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
//顶点赋值
GLES20.glEnableVertexAttribArray(vPosition);
// GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);
//从vbo中取数据
GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8, 0);
//纹理赋值
GLES20.glEnableVertexAttribArray(fPosition);
// GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8, fragmentBuffer);
//从vbo中取数据
GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8, vertexData.length * 4);
//从0开始绘制4个点
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
//解绑
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
//解绑vbo
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
}