OpenGL ES 顶点缓冲区和布局(3)

news/2024/10/4 13:55:42/

OpenGL_ES_3_0">OpenGL ES 顶点缓冲区和布局(3)

简述

顶点缓冲区的本质就是一段GPU上的显存,我们通过绑定顶点缓冲区的方式来将数据从CPU传到GPU。
我们之前在绘制三角形的例子中,我们往顶点缓冲区只传入了坐标,但是其实顶点是可以包含很多数据的,比如纹理索引,颜色等,因为它的本质其实就是一个Buffer,所以我们可以使用它做非常多的事情。
我们前面说了,顶点缓冲区只是一个一段内存,但是GPU并不知道这段内存里的这些数是什么意思,每个数据的含义是什么。所以我们需要告诉GPU顶点缓冲区布局,定义每个数据是什么意思。

配置布局接口

glVertexAttribPointer

  • 第一个参数是index,表示这个数据要传递给shader哪一个属性,这个我们在shader对篇章会详细介绍。
  • 第二个参数是size,表示有几个数
  • 第三个参数是type,表示数据类型
  • 第四个参数是normalized,表示参数是否需要归一化
  • 第五个参数是stride,每个顶点的步长,基本可以理解为一个顶点的长度
  • 第六个参数是offset,表示当前属性在当前顶点的偏移

绑定BufferData

glBufferData

  • 第一个参数,数据类型,顶点缓冲区一般用GL_ARRAY_BUFFER,后续我们还会介绍索引缓冲区
  • 第二个参数,size,我们需要分配缓冲区的大小。
  • 第三个参数,data,我们定义的数据。
  • 第四个参数,缓冲区用于使用的场景,GL_STREAM_DRAW/GL_STATIC_DRAW/GL_DYNAMIC_DRAW。
    GL_STREAM_DRAW:缓冲区数据代码设置,仅渲染一次,使用很少。
    GL_STATIC_DRAW:缓冲区数据是静态的,不会修改的。
    GL_DYNAMIC_DRAW:缓冲区数据会动态变化,常常需要更新数据。

实现渐变颜色三角形

我们这里通过顶点缓冲区传递数据,实现一个渐变三角形。这个demo会有助于我们对顶点缓冲区数据传递,同时还能对顶点着色器属性有一些了解。
我们基于之前那个三角形的案例来修改。

修改顶点缓冲区Buffer

我们之前顶点缓冲区只有9个数,三个顶点,每个顶点三个坐标,修改后每个顶点有7个数,前三个点依旧是坐标,和之前相同,而后面新增的四个顶点是坐标,即RGBA。
我们之前提过,着色器会对每个像素都调用一次,而顶点着色器则会根据顶点坐标渐变,对每个像素都进行调用。
这里实现的三个角的颜色分别是红黄蓝,然后向中间渐变。

private float[] vertexArray = new float[] {-0.5f, -0.5f, 0.0f, 1f, 0f, 0f, 1f,0.5f, -0.5f, 0.0f, 0f, 1f, 0f, 1f,0.0f, 0.5f, 0.0f, 0f, 0f, 1f, 1f
};

修改shader

添加了属性attribute vec4 inputColor,用于接收顶点缓冲区新增的四维用于表示颜色的数组,顶点缓冲区传递给vertexColor,通过varying传递给片段着色器。
片段着色器直接使用varying vec4 vertexColor作为gl_FragColor返回。

private final String vertexShaderCode ="attribute vec4 vPosition;" +"attribute vec4 inputColor;" +"varying vec4 vertexColor;" +"void main() {" +"  vertexColor = inputColor;" +"  gl_Position = vPosition;" +"}";private final String fragmentShaderCode ="precision mediump float;" +"varying vec4 vertexColor;" +"uniform vec4 vColor;" +"void main() {" +"  gl_FragColor = vertexColor;" +"}";

顶点缓冲区创建/数据填充

创建绑定顶点缓冲区,后使用glBufferData填充数据,这里和之前创建三角形一样,基本没有修改。

public void onSurfaceCreated(GL10 gl, EGLConfig config) {// 清除颜色GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);// 创建顶点缓冲区int[] idBuffer = new int[1];GLES30.glGenBuffers(1, idBuffer, 0);vertexBufferId = idBuffer[0];// 顶点缓冲区数据填充FloatBuffer vertexBuffer = ByteBuffer.allocateDirect(vertexArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();vertexBuffer.put(vertexArray);vertexBuffer.position(0);GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vertexBufferId);// 填充数据GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vertexArray.length * 4,vertexBuffer,GLES30.GL_STATIC_DRAW);GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);// shadershaderProgramId = initShaderProgram(vertexShaderCode, fragmentShaderCode);
}

配置顶点缓冲区布局

通过这里的glVertexAttribPointer使用,配合上面的api介绍,我们大概就能理解这个布局接口是怎么使用的。

public void onDrawFrame(GL10 gl) {// 清除屏幕GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);// 使能着色器程序GLES30.glUseProgram(shaderProgramId);GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vertexBufferId);int positionLocation = GLES30.glGetAttribLocation(shaderProgramId, "vPosition");GLES30.glEnableVertexAttribArray(positionLocation);// 主要改动部分在这里// 这里的步长为7个顶点 * sizeof(float), 这里index是传给vPosition,type还是GL_FLOAT,size为3个顶点GLES30.glVertexAttribPointer(positionLocation, 3, GLES30.GL_FLOAT, false, 7 * 4, 0);// 步长和上面一样, 这里index是传给inputColor,type还是GL_FLOAT,size为4个顶点int colorInputLocation = GLES30.glGetAttribLocation(shaderProgramId, "inputColor");GLES30.glEnableVertexAttribArray(colorInputLocation);GLES30.glVertexAttribPointer(colorInputLocation, 4, GLES30.GL_FLOAT, false, 7 * 4, 3 * 4);// 调用DrawCall绘制三角形GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 3);// 清除配置GLES30.glDisableVertexAttribArray(positionLocation);GLES30.glDisableVertexAttribArray(colorInputLocation);GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);GLES30.glUseProgram(0);
}

效果

在这里插入图片描述

顶点数组

还有一个概念是顶点数组,我们简称VAO,相关的接口glGenVertexArrays,这个接口在GLES20上没有,但是在GLES30上有。
顶点数组的本质的作用是用于记录顶点缓冲区和顶点布局的关系,如果有多个缓冲区,顶点数组可以记录这些,可以减少调用绑定的次数。
相信大家会有一个问题,为什么GLES20上没有这个api,而且我们之前绘制三角形的demo中也没有使用这个顶点数组,为什么还可以正常绘制呢。
按照技术上的作用,这个顶点数组是必要的,前面这个问题的答案其实是因为OpenGL默认配置下就会有一个顶点数组。
这个目前了解一下即可,后续我们绘制多个对象的时候会再仔细介绍顶点数组。

小结

本节介绍了顶点缓冲区和布局,且通过实现一个渐变色的三角形demo来展示了怎么使用顶点缓冲区和布局。
顶点缓冲区的数据可以是位置,颜色,纹理等等,本质这里就是一个内存缓冲区,这里展示了颜色的用法。
配置顶点布局的接口使用比较简单,按照文档的使用即可。


http://www.ppmy.cn/news/1534446.html

相关文章

python三局两胜游戏

分为以下步骤实现这个功能 1、猜拳 2、机器产生数值 3、人去猜数字,定义剪刀石头布 4、控制机器产生,123程序运行的时候可能会出现一点玄学问题,就是,提示n1这一行不符合pep8然后报错,不用管,运行就可以&am…

平安养老险深圳分公司积极开展“金融教育宣传月”活动,展现金融为民新风尚

2024年9月,平安养老险深圳分公司以“金融为民谱新篇,守护权益防风险”为主题,正式启动2024年“金融教育宣传月”活动,通过多样化开展进乡村、进商圈、进企业等宣传教育活动,将金融消保知识送达广大消费者身边&#xff…

AI大模型之旅-最强开源文生图工具Stable Diffusion WebUI 教程

1.1克隆 Automatic1111 的 GitHub 仓库 在你想安装 Web UI 的文件夹路径下执行 git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui 这将会克隆整个仓库到本地。 这里会默认访问 https://huggingface.co/ 下载 因此需要魔法 1.2 进入仓库目录 cd stable-di…

信息学奥赛一本通 1416:【17NOIP普及组】棋盘 | 洛谷 P3956 [NOIP2017 普及组] 棋盘

【题目链接】 洛谷 P3956 [NOIP2017 普及组] 棋盘 ybt 1416:【17NOIP普及组】棋盘 【题目考点】 1. 深搜:深搜回溯 2. 深搜剪枝:最优化剪枝 【解题思路】 搜索从左上角到右下角的所有走法中花费金币最少的走法。 需要使用深搜回溯&…

智能新宠:BabyAlpha A2开启家庭机器人新时代

具身智能领域的“疯狂”,已经迈入了全新的阶段!让我们一起来看看这段视频:一个人形机器人在前面奔跑,一群机器狗紧随其后;接着是人追赶机器狗,随后机器狗又追逐人……视频最后,那个机器人似乎还…

Python知识点:如何使用KubeEdge与Python进行容器化边缘计算

开篇,先说一个好消息,截止到2025年1月1日前,翻到文末找到我,赠送定制版的开题报告和任务书,先到先得!过期不候! 如何使用KubeEdge与Python进行容器化边缘计算 随着云计算的发展,边缘…

基于大数据技术的颈椎病预防交流与数据分析及可视化系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏:Java精选实战项目…

Ubuntu Server 20.04 64bit定时备份MySQL8.0.36数据库数据

一、编写sh脚本 常见备份命令介绍 我选用的是mysqldump命令,命令使用简介 [root]> mysqldump -helpUsage: mysqldump [OPTIONS] database_name [tables] OR mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...] OR mysqldump [OPTIONS] --all…