OpenGL ES-VBO(顶点缓冲对象)

1、VBO

Vertex Buffer object:顶点缓冲对象

2、为什么要用VBO?

不使用VBO时,我们每次绘制( glDrawArrays )图形时都是从本地内存处获取顶点数据然后传输给OpenGL来绘制,这样就会频繁的操作CPU->GPU增大开销,从而降低效率。

使用VBO,我们就能把顶点数据缓存到GPU开辟的一段内存中,然后使用时不必再从本地获取,而是直接从显存中获取,这样就能提升绘制的效率。

3、创建VBO

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);

4、使用VBO

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);
public class JfTextureRender implements JfEGLSurfaceView.JfGLRender {
    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
            0f,0.5f,
            0.5f,0.5f,
            0f,0f,
            0.5f,0f
    };
    private FloatBuffer fragmentBuffer;


    private int program;//程序
    private int vPosition;//顶点着色器属性
    private int fPosition;//片元着色器属性

    private int textureId;
    private int vboId;
    private int sampler;

    public JfTextureRender(Context context){
        this.context = context;
        vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(vertexData);
        vertexBuffer.position(0);

        fragmentBuffer = ByteBuffer.allocateDirect(fragmentData.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(fragmentData);
        fragmentBuffer.position(0);
    }
    @Override
    public void onSurfaceCreated() {
        //获取源码
        String vertexSource = JfShaderUtil.getRawResource(context,R.raw.vertex_shader);
        String fragmentSource = JfShaderUtil.getRawResource(context,R.raw.fragment_shader);
        //前6步完成
        program = JfShaderUtil.createProgram(vertexSource,fragmentSource);

        //得到着色器中的属性
        vPosition = GLES20.glGetAttribLocation(program,"v_Position");
        fPosition = GLES20.glGetAttribLocation(program,"f_Position");
        sampler = GLES20.glGetUniformLocation(program,"sTexture");


        //1、创建VBO
        int[] vbos = new int[1];
        GLES20.glGenBuffers(1, vbos, 0);
        vboId = vbos[0];

        //2、绑定VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);

        //3、分配VBO需要的缓存大小
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,vertexData.length * 4 + fragmentData.length * 4,null,GLES20. GL_STATIC_DRAW);

        //4、为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);

        //5、解绑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);//绑定纹理

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        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.fengjing);
        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);

        //使用源程序
        GLES20.glUseProgram(program);

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textureId);//再次绑定纹理

        //1、绑定VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);

        //使顶点属性数组有效
        GLES20.glEnableVertexAttribArray(vPosition);
        //为顶点属性赋值
        //GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8,vertexBuffer);
        GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8,0);
        GLES20.glEnableVertexAttribArray(fPosition);
        //GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8,fragmentBuffer);
        GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8,vertexData.length * 4);

        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,0);//再次解绑纹理
        //3、解绑VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_33805557/article/details/86984931
今日推荐