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); } }
浙公网安备 33010602011771号