当前位置: 首页 > article >正文

OpenGl(四) 提升Shader性能--VBO、EBO、VAO之EBO

什么是EBO

EBO:Element Buffer Object 元素缓冲对象也被称为IBO,用于存储顶点索引值
优点:减少数据拷贝 ,可以更灵活的使用顶点数据,有一些效果使用EBO更方便

使用步骤

  • 生成并绑定EBO
  • 从GPU拷贝数据到EBO(GPU)
  • 使用glDrawElements绘制图形
  • 解绑EBO
    相关API
  • glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,……)
  • glBufferData(GL_ELEMENT_ARRAY_BUFFER,……)
  • glDrawElements.(该函数有4个参数,第一个参数,指定要绘制的图形,第二个参数,指定顶点个数,第三个参数,指定数据类型,第四个参数,指定偏移量)

使用EBO绘制三角形


import android.opengl.GLES30
import android.opengl.GLSurfaceView
import android.opengl.Matrix
import android.util.Log
import java.nio.*
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

/**
 * Day:2024/7/13 15:28
 * @author wangdanfeng02
 */
class DemoEBOGlRender : GLSurfaceView.Renderer {
    /*
     * 顶点位置程序
     */
    private val vertexShaderCode =
                "attribute vec4 vPosition;" +
                "void main() {" +
                "  gl_Position = vPosition;" +
                "}"

    /**
     * 片元颜色程序
     */
    private val fragmentShaderCode =
        "precision mediump float;" +
                "uniform vec4 vColor;" +
                "void main() { " +
                "   gl_FragColor = vColor;" +
                "}"
    /**
     * 三角形顶点位置
     */
    private val triangleCoors = floatArrayOf(
        -0.5f, 0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f
    )

    /**
     * 三角形颜色值
     */
    private val color = floatArrayOf(
        1.0f, 1.0f, 1.0f, 1.0f
    )

    private var translateMatrix = FloatArray(16)
    private var program: Int? = null
    private var positionHandle: Int = -1
    private var colorHandle: Int = -1
    private var tMatrixHandle: Int = -1
    private var vertexBuffer: FloatBuffer? = null
    private lateinit var byteBuffer: ByteBuffer
    private var vboIds = IntArray(1)
    private var eboIds = IntArray(1)
//    private var indics = intArrayOf(0,1,2)
    private var indics = intArrayOf(0, 1, 2)


    override fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {
        // 设置背景颜色
        GLES30.glClearColor(1f, 0f, 0f, 1.0f)
        // 清理缓存
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        createFloatBuffer()
        val idxBuffer = ByteBuffer.allocateDirect(indics.size * 4).order(ByteOrder.nativeOrder()).asIntBuffer()
        idxBuffer.put(indics).position(0)
        Matrix.setIdentityM(translateMatrix, 0)
        // 创建定点着色程序
        val vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertexShaderCode)
        // 创建片元着色程序
        val fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode)

        if (vertexShader != 0 && fragmentShader != 0) {
            linkProgram(vertexShader, fragmentShader)
            GLES30.glDeleteShader(vertexShader); // 立即释放vertexShader
            GLES30.glDeleteShader(fragmentShader); // 立即释放fragmentShader
            // VBO
            GLES30.glGenBuffers(1, vboIds, 0)
            // glBindBuffer,绑定VBO到GPU (该函数有2个参数,target,指定存放的目标数据类型,它是常量,如GL_ARRAY_BUFFER表示用于存储顶点数据,  int buffer,绑定的VBO对象ID,解绑定时将第二个参数设置为0)
            GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboIds[0])
            // glBufferData,拷贝数据到VBO   (该函数有4个参数,target,指定存放的目标数据类型,同glBindBuffer中的target,size指定拷贝数据的大小,data,从哪儿拷贝数据,usage,常量,指定拷贝数据的方式,一般设置为GL_STATIC_DRAW表示一次性拷贝)
            GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, byteBuffer.capacity(), byteBuffer, GLES30.GL_STATIC_DRAW)
            GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0)

            // EBO
            GLES30.glGenBuffers(1, eboIds, 0)
            // glBindBuffer,绑定VBO到GPU (该函数有2个参数,target,指定存放的目标数据类型,它是常量,如GL_ARRAY_BUFFER表示用于存储顶点数据,  int buffer,绑定的VBO对象ID,解绑定时将第二个参数设置为0)
            GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, eboIds[0])
            // glBufferData,拷贝数据到VBO   (该函数有4个参数,target,指定存放的目标数据类型,同glBindBuffer中的target,size指定拷贝数据的大小,data,从哪儿拷贝数据,usage,常量,指定拷贝数据的方式,一般设置为GL_STATIC_DRAW表示一次性拷贝)
            // 注意*4
            GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,
                idxBuffer.capacity() * Int.SIZE_BYTES,
                idxBuffer,
                GLES30.GL_STATIC_DRAW)
            GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0)
            program?.let {
                positionHandle = GLES30.glGetAttribLocation(it, "vPosition")
                GLES30.glEnableVertexAttribArray(positionHandle)

//                tMatrixHandle = GLES30.glGetUniformLocation(it, "mTMatrix")
                colorHandle = GLES30.glGetUniformLocation(it, "vColor")
            }
        }
    }

    private fun createFloatBuffer() {
        // 申请物理层空间
        byteBuffer = ByteBuffer.allocateDirect(triangleCoors.size * 4).apply {
            this.order(ByteOrder.nativeOrder())
        }
        // 坐标数据转换
        vertexBuffer = byteBuffer.asFloatBuffer()
        vertexBuffer?.put(triangleCoors, 0, triangleCoors.size)
        vertexBuffer?.position(0)
    }

    private fun linkProgram(vertexShader: Int, fragmentShader: Int) {
        // 创建空的opengl es 程序
        program = GLES30.glCreateProgram()
        program?.let {
            // 将顶点着色器加入程序
            GLES30.glAttachShader(it, vertexShader)
            // 将片元着色器加入程序
            GLES30.glAttachShader(it, fragmentShader)
            // 链接到着色器程序
            GLES30.glLinkProgram(it)
            // 将程序加入到opengl30环境中
            GLES30.glUseProgram(it)
            val info = GLES30.glGetProgramInfoLog(it)
            // 打印链接程序日志
            Log.e("wdf", "info==" + info)
        }
    }

    override fun onSurfaceChanged(p0: GL10?, width: Int, height: Int) {
        // 设置绘制窗口
        GLES30.glViewport(0, 0, width, height)
    }

    override fun onDrawFrame(p0: GL10?) {
        program ?: return
        if (program == 0) {
            return
        }
        program?.let {
            GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
            GLES30.glUseProgram(it)
            GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboIds[0])
            // 再次绑定VBO,表示从哪个VBO读取
            GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, eboIds[0])
            // 最后一个参数设置为0时,会从GPU中读取数据
            GLES30.glVertexAttribPointer(positionHandle, 3, GLES30.GL_FLOAT, false, 12, 0)
            //将数据传递给shader
//            GLES30.glUniformMatrix4fv(tMatrixHandle, 1, false, translateMatrix, 0)
            // 设置三角形颜色,与程序中声明vColor变量名保持一致
            GLES30.glUniform4fv(colorHandle, 1, color, 0)
            // 绘制
            GLES30.glDrawElements(GLES30.GL_TRIANGLES, indics.size, GLES30.GL_UNSIGNED_INT, 0)
//            GLES30.glDisableVertexAttribArray(vPosition)
            GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0)
            GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0)
        }
    }


    /**
     * 创建shader,加载shader程序
     */
    private fun loadShader(type: Int, shaderCode: String): Int {
        val shader = GLES30.glCreateShader(type)
        GLES30.glShaderSource(shader, shaderCode)
        GLES30.glCompileShader(shader)
        return shader
    }

}
class TriangleView : GLSurfaceView {
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    init {
        setEGLContextClientVersion(3)
        setRenderer(DemoEBOGlRender())
        renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
    }
}

http://www.kler.cn/a/470006.html

相关文章:

  • 高等数学-----极限、函数、连续
  • 用户界面软件01
  • Allure 集成 pytest
  • nodejs实现https://localhost在window系统自签名99年+授信
  • 深度学习中的正则化方法
  • STLG_01_10_程序设计C语言 - 字符串
  • Reactor测试框架之StepVerifier
  • JavaScript语言的编程范式
  • Python爬虫入门指南:从零开始抓取数据
  • Mysql--基础篇--概述
  • 专业无人机飞手培训,考证、组装、调参、维修全面技术详解
  • 网络协议安全
  • NLP论文速读|基于主动检索的渐进多模态推理
  • 【C++】AVL树|插入|单旋|双旋
  • 反向代理模块开发,
  • type1-88
  • python打包open3d问题
  • 尚硅谷· vue3+ts 知识点学习整理 |14h的课程(持续更ing)
  • 如何分析 Nginx 日志
  • 并查集:合并集合
  • (leetcode算法题)137. 只出现一次的数字 II
  • cursor vip
  • AFFAM模型详解及分析
  • Mac软件介绍之录屏软件Filmage Screen
  • day01_ Java概述丶开发环境的搭建丶常用DOS命令
  • 银河麒麟高级服务器操作系统忘记root密码