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

server/2024/10/20 8:52:47/

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/server/127416.html

相关文章

排序算法——快速排序:普通快排与双路快排

快速排序: 普通快排: 选取待排序数组的首或尾元素作为枢轴(就是base,我们选出来的比较的数),大于base的放右边,小于base的放左边。 public void quickSort(int[] nums, int low, int high) {…

微服务(Microservices),服务网格(Service Mesh)以及无服务器运算Serverless简单介绍

文章目录 什么是微服务?一、定义与特点二、优势三、组件与架构四、应用场景五、挑战与解决方案什么是服务网格?一、定义与特点二、核心组件三、主要功能四、实现工具五、应用场景六、优势与挑战什么是Serverless?一、定义与特点二、主要领域三、优势四、应用场景五、挑战三者…

Redis数据库与GO(二):list,set

一、list(列表) list(列表)是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。List本质是个链表, list是一个双向链表,其元素是有序的,元…

PMP--三模--解题--151-160

文章目录 14.敏捷--仆人式领导--在敏捷环境中,项目经理充当仆人式领导,其工作重点转变为引导需要帮助的人,促进团队的合作,保持与干系人的需要一致。151、 [单选] 两个分布在不同地方的团队在同一个项目上。相比A团队,…

稿简单认识redis -2 java中的使用

1.idea配置 Jedis: 一款java操作redis数据库的工具. 1.1. 下载jedis的jar包 1 添加到 lib 目录 右键 后添加为库 2 配置maven项目在 pom.xml文件添加依赖 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><v…

[Uninstall] 软件彻底卸载工具的下载及详细安装使用过程(附有下载文件)

一般软件安装的有问题&#xff0c;或者想重新安装其他版本就需要将原来的版本删除干净&#xff0c;但常常删不干净&#xff0c;本文分享一个软件彻底卸载工具&#xff0c;完成彻底卸载软件的工作 下载链接在文末 下载压缩包后解压 &#xff01;&#xff01;安装路径不要有中文…

足球青训俱乐部后台:Spring Boot开发策略

4 系统设计 4.1 系统架构设计 B/S系统架构是本系统开发采用的结构模式&#xff0c;使用B/S模式开发程序以及程序后期维护层面需要的经济成本是很低的&#xff0c;用户能够承担得起。使用这样的模式开发&#xff0c;用户使用起来舒心愉悦&#xff0c;不会觉得别扭&#xff0c;操…

《无机杀手》制作团队选择Blender的原因分析

《无机杀手》&#xff08;Murder Drones&#xff09;是一部备受欢迎的动画短片&#xff0c;其制作团队选择使用Blender软件进行制作&#xff0c;这一选择背后有着多方面的原因。【成都渲染101--blender渲染农场邀请码6666提供文案参考】 开源且免费 Blender是一个开源且免费的…