Android视频采集渲染学习(3)

以VBO方式存储顶点数据;渲染时候直接从VBO取数据(VBO是GPU缓冲区)能够节省渲染性能

VBO:生成,绑定,数据拷贝,使用(vertexattrpoints);解绑;基本每次渲染使用一次定点数据,这个数据如果每次都从CPU或者直接缓冲中读取,会比较耗费性能(在模型比较复杂的时候);

VBO:vertex buffer object 顶点缓冲对象, 一个存储在GPU中的对象

(代码来源于慕课网学习)

package com.example.glestest

import android.opengl.GLSurfaceView
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.android.camera2.myglsurfaceview.MyGLSurfaceView

class MainActivity : AppCompatActivity() {
    private lateinit var glview:GLSurfaceView;
    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        glview =MyGLSurfaceView(this)
        setContentView(/* view = */ this.glview)

    }
}
package com.example.android.camera2.myglsurfaceview

import android.content.Context
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
import android.opengl.GLES30
import android.opengl.GLSurfaceView
import com.example.glestest.triangre

class MyGLSurfaceView : GLSurfaceView {

    constructor(context: Context) : super(context) {
        //使用的OpenGL ES 版本
        setEGLContextClientVersion(3)

        //为GLSurfaceView设置Renderer,在该函数中会启动一个新的线程来构造EGL环境
        setRenderer(MyGLRenderer())
    }
}

class MyGLRenderer : GLSurfaceView.Renderer {

  private lateinit  var trangle:triangre;
    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        //设置OpenGL ES清屏色为红色, R,G,B,A
        GLES30.glClearColor(1.0f, 1.0f, 1.0f, .5f)
        trangle =triangre();
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        //设置OpenGLES的视口大小
        GLES30.glViewport(0, 0, width, height)
    }

    override fun onDrawFrame(gl: GL10?) {
        //清空当前缓冲区的颜色缓冲区
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        trangle.Draw();
    }
}
package com.example.glestest

import android.opengl.GLES30
import android.opengl.Matrix
import androidx.core.graphics.translationMatrix
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer

class triangre {
    private var program = 0;
    private var positionHandle = 0;
    private var colorHandle = 0;
    private var matrixHandle = 0;
    //着色器
    private val vertexShaderCode =
        "uniform mat4 mTMatrix; " +
        "attribute vec4 vPosition;" +
                "void main() {" +
                "  gl_Position = mTMatrix * vPosition;" +
                "}"

    private val fragmentShaderCode =
        "precision mediump float;" +
                "uniform vec4 vColor;" +
                "void main() {" +
                "  gl_FragColor = vColor;" +
                "}"
   //顶点坐标(系统坐标系 -1~1)
    private val triangleCoords = floatArrayOf(
        0.0f,  0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f)

    private val color = floatArrayOf(0.5f, 0.5f, 0.5f, 1.0f)//颜色数据
    //变换矩阵
    private var vertex_matrix = FloatArray(16);
    private  lateinit var vertexBuf:FloatBuffer;

   //vbO vertex vuffer obj
    private var VBOid = IntArray(1);

    private fun loadshader(type: Int,shadercode:String):Int{
        val shader =GLES30.glCreateShader(type);
        GLES30.glShaderSource(shader,shadercode);
        GLES30.glCompileShader(shader);
        return shader;
    }
    constructor(){
        //分配GPU可访问内存的操作是用ByteBuffer.allocate分配一段Native内存(直接缓冲),GPU 可以直接访问(DMA)
        // 他是直接内存,不是VBO
       val buf =   ByteBuffer.allocateDirect(triangleCoords.size*4);//开辟空间;顶点数据
        buf.order(ByteOrder.nativeOrder());//设置字节序
        vertexBuf =buf.asFloatBuffer();//只是转成float存储访问,但是数据仍然会存在buf中,所以VBO方式用的是buf
        vertexBuf.put(triangleCoords);//CPU 拷贝到GPU(拷贝到直接缓冲,是一个GPU可以访问的存储,但是不是GPU)
        vertexBuf.position(0);//从头读数据


        Matrix.setIdentityM(vertex_matrix,0);
       // Matrix.translateM(vertex_matrix,0,0.5f,0f,0f);//平移
        Matrix.scaleM(vertex_matrix, 0, 0.5f, 0.5f,1.0f);//缩放

        //创建着色器,指定源码,编译,绑定(attach),链接
        val vertexShader =  loadshader(GLES30.GL_VERTEX_SHADER,vertexShaderCode);
        val fregmentShader = loadshader(GLES30.GL_FRAGMENT_SHADER,fragmentShaderCode);
        //绑定
        program = GLES30.glCreateProgram();
        GLES30.glAttachShader(program,vertexShader);
        GLES30.glAttachShader(program,fregmentShader);
        //链接
        GLES30.glLinkProgram(program);
        //VBO 生成,绑定,数据拷贝,使用
        GLES30.glGenBuffers(1,VBOid,0);
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,VBOid[0]);
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,buf.capacity(),buf,GLES30.GL_STATIC_DRAW);//一次拷贝
        //解绑
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,0);
    }

    fun Draw(){
        //使用program
        GLES30.glUseProgram(program);
        //再次指定绑定的VBO
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,VBOid[0]);
        //数据传给着色器
        positionHandle= GLES30.glGetAttribLocation(program,"vPosition");//接入点
        GLES30.glEnableVertexAttribArray(positionHandle);
        //从 CPU直接缓冲中读取数据
        //GLES30.glVertexAttribPointer(positionHandle,3,GLES30.GL_FLOAT,false,0,vertexBuf);
        //从GPU中读取数据;最后一个参数是0就去GPU中找数据
        GLES30.glVertexAttribPointer(positionHandle,3,GLES30.GL_FLOAT,false,0,0);

        matrixHandle = GLES30.glGetUniformLocation(program,"mTMatrix")
        GLES30.glUniformMatrix4fv(matrixHandle,1,false,vertex_matrix,0);

        colorHandle =GLES30.glGetUniformLocation(program,"vColor");
        GLES30.glUniform4fv(colorHandle,1,color,0)
        //h绘制
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,0,triangleCoords.size/3);
        //释放顶点资源
        GLES30.glDisableVertexAttribArray(positionHandle);
        //解绑
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,0);
    }
}

 

posted on 2025-04-13 23:30  邗影  阅读(17)  评论(0)    收藏  举报

导航