新公司网站建设流程,wordpress连载小说插件,wordpress的字体,上海申远建筑设计有限公司目录
一、缓冲区对象概念
二、分类
三、顶点缓冲区对象VBO
1、概念
2、为什么使用VBO
3、如何使用VBO
生成缓冲区对象
绑定缓冲区对象
输入缓冲区数据
更新缓冲区中的数据
删除缓冲区
4、VBO应用
四、顶点数组对象VAO
1、概念
2、为什么使用VAO
3、如何使用VAO…目录
一、缓冲区对象概念
二、分类
三、顶点缓冲区对象VBO
1、概念
2、为什么使用VBO
3、如何使用VBO
生成缓冲区对象
绑定缓冲区对象
输入缓冲区数据
更新缓冲区中的数据
删除缓冲区
4、VBO应用
四、顶点数组对象VAO
1、概念
2、为什么使用VAO
3、如何使用VAO
生成VAO
绑定VAO
解绑VAO
删除VAO
4、VAO应用
五、索引缓冲区对象EBO/IBO
1、概念
2、为什么使用IBO/EBO
3、如何使用EBO
生成EBO
绑定EBO
输入数据到缓冲区
链接属性
绘制
4、EBO应用
5、绘制过程
六、总结
1、常用各类缓冲区分析
2、无法删除缓冲区
七、源码下载 一、缓冲区对象概念
缓冲区对象Buffer Object是OpenGL中用于在GPU内存中存储数据的一种机制它们使得数据传输和渲染更加高效。
二、分类
常用的缓冲区分类如下
VAO(Vertex Array Object): 顶点数组对象用于存储顶点数据 VBO(Vertex Buffer Object): 顶点缓冲对象用于存储顶点数据 EBO(Element Buffer Object): 元素缓冲对象用于存储顶点的索引数据 IBO(Index Buffer Object): 索引缓冲对象用于存储索引数据
FBO(Index Buffer Object):帧缓冲对象用于渲染到纹理或离屏渲染。
PBO(Pixel Buffer Object):像素缓冲区对象
GL_ARRAY_BUFFER标志指定的数组缓冲区对象用于创建保存顶点数据的缓冲区对象。GL_ELEMENT_ARRAY_BUFFER标志指定的元素数组缓冲区对象用于创建保存图元索引的缓冲区对象。
应用程序对顶点属性数据和元素索引使用顶点缓冲区对象。
三、顶点缓冲区对象VBO
1、概念
VBO(Vertex Buffer Object)顶点缓冲对象是在显卡存储空间即GPU内存中开辟的一块区域在显卡存储空间中开辟一块区域用于存放顶点的各类属性信息。如顶点坐标、纹理坐标、顶点颜色等数据。 在渲染时直接从显VBO去取数据而不必与CPU进行数据交换。
2、为什么使用VBO
什么是顶点缓冲区对象为什么要使用它们
解释1
将对象数据存储在客户端内存中只有在渲染时将其传输到GPU内存即显存中。没有大量数据传输时这很好但随着我们的场景越来越复杂会有更多的物体和三角形这会给CPU和内存增加额外的成本。
我们能做些什么呢我们可以使用顶点缓冲对象而不是每帧从客户端内存传输顶点信息信息将被传输一次然后渲染器将从该图形存储器缓存中得到数据。
解释2
直接只用顶点数组来绘图在客户端制定顶点数据每次绘制时从先从内存中加载这些数据这样会带来绘制延时因此我们想着在显存中开辟一块区域在每次绘制间隔就将顶点数据加载过来这样绘制时直接读取显存中的数据就可以了明显提高渲染速度。于是我们需要引入顶点缓冲区。 一般在两种不同处理速度的物理组件之间进行数据传输时都要用到缓冲区OpenGL由于需要处理内存与GPU的数据传输也要用到一系列缓冲区对象顶点缓冲区只是其中之一。在顶点数组的基础上使用定点缓冲区可以提高渲染速率。
解释3
VBO允许开发者将大量顶点数据从CPU传输到GPU减少每帧的CPU-GPU通信量提高渲染效率。缓冲区对象通过在 GPU 上存储数据提高了数据传输和渲染的效率。
使用顶点数组指定的顶点数据保存在客户内存中。在进行 glDrawArrays或者 glLDrawElements 等绘图调用时这些数据必须从客户内存复制到图形内存。但是如果我们没有必要在每次绘图调用时都复制顶点数据而是在图形内存中缓存这些数据那就好得多了。这种方法可以显著地改进渲染性能也会降低内存带宽和电力消耗需求对于手持设备相当重要。这是顶点缓冲区对象发挥作用的地方。
顶点组冲区对象使应用程序可以在高性能的图形内存中分配和缓存顶点数据并从这个内存进行泻染从而避免在每次绘制图元的时候重新发送数据。不仅是项点数据描述图元顶点索引、作为 glDrawElements 参数传递的元素索引也可以缓存。
解释4
通过顶点缓冲对象(Vertex Buffer Objects, VBO)管理这个内存它会在GPU内存通常被称为显存中储存大量顶点。使用这些缓冲对象的好处是我们可以一次性的发送一大批数据到显卡上而不是每个顶点发送一次。
从CPU把数据发送到显卡相对较慢所以只要可能我们都要尝试尽量一次性发送尽可能多的数据。当数据发送至显卡的内存中后顶点着色器几乎能立即访问顶点这是个非常快的过程。
解释5
为什么需要使用VBO
将顶点数据保存在内存中在调用glDrawArrays或者glDrawElements等绘制方法前需要调用相应的方法将数据送入显存I/O开销大性能不够好。 若采用顶点缓冲区对象存放顶点数据则不需要在每次绘制前都将顶点数据复制进显存而是在初始化顶点缓冲区对象时一次性将顶点数据送入显存 每次绘制时直接使用显存中的数据可以大大提高渲染性能。
3、如何使用VBO
顶点缓冲区的使用需要经历一下步骤 生成缓冲区对象
glGenBuffers(GLsizei n, GLuint* buffers);
分配n个缓冲区对象标识符返回的标识符存储在buffers数组中。每一个标识符表示一个已经开始使用的缓冲区对象。具体如何分配有OpenGL内部决定与调用者无关。此外该方法调用之后在buffers中存储的标识符并不一定是连续的数字而且0作为一个被保留的缓冲区对象名称该方法从来不会返回0标识符。
绑定缓冲区对象
glBindBuffer(GLenum target, GLuint buffer);
绑定缓冲区对象。OpenGL有很多缓冲对象类型顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER。buffer是glGenBuffers()返回的标识符数组的一个值target表示改缓冲区应该绑定为什么类型的缓冲区对象有GL_ARRAY_BUFFER(顶点数组缓冲区)、GL_ELEMENT_ARRAY_BUFFER(索引数组缓冲区)等。需要注意的是以GL_ARRAY_BUFFER为例
如果buffer为0则停用顶点数组缓冲区如果buffer为非零整数且buffer代表的缓冲区之前未绑定过则创建一个新的缓冲区对象和buffer相对应如果buffer之前绑定过则激活buffer对应的缓冲区。
OpenGL有很多缓冲对象类型顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER。OpenGL允许我们同时绑定多个缓冲只要它们是不同的缓冲类型。我们可以使用glBindBuffer函数把新创建的缓冲绑定到GL_ARRAY_BUFFER目标上。
输入缓冲区数据
glBufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
初始化缓冲区对象并指定缓冲区数据。target和glBindBuffer()中的target一样data表示要写入到缓冲区的数据数组头指针size表示data数组的字节数usage表示数据在分配到缓冲区之后如何进行读取和写入主要用来提供性能指定了我们希望显卡如何管理给定的数据。其值为“GL_频率_操作”格式有
GL_STREAM_DRAW、
GL_STREAM_READ、
GL_STREAM_COPY、
GL_STATIC_*、
GL_DYNAMIC_*。
其中“频率”指缓冲区数据的读取或者渲染速率有流模式、静态模式动态模式
STREAM流模式当缓冲区中的数据更新频率高但使用频率低时使用STATIC静态模式当缓冲区中的数据只需制定一次但使用频率比较高时使用DYNAMIC动态模式当缓冲区中的数据更新频率高并且使用频率高时使用。
“操作”有绘制 、读取和拷贝
DRAW绘制缓冲区中的数据直接用于渲染也就是内存中的数据直接作为渲染数据READ读取缓冲区中的数据主要用于应用程序的计算而不是直接作用于渲染COPY拷贝缓冲区中的数据对渲染来说是只读数据需要拷贝后将拷贝数据作为渲染数据。
例如如下三种形式的含义
GL_STATIC_DRAW 数据不会或几乎不会改变。仅在显存上进行读取,不进行写入,适用于静态数据。GL_DYNAMIC_DRAW数据会被改变很多。仅在显存上进行读取,并允许写入,数据经常改变。GL_STREAM_DRAW 数据每次绘制时都会改变。仅在显存上进行读取,不进行写入,数据每次绘制都改变。
一般情况下位置数据不会改变每次渲染调用时都保持原样所以它的使用类型最好是GL_STATIC_DRAW。如果比如说一个缓冲中的数据将频繁被改变那么使用的类型就是GL_DYNAMIC_DRAW或GL_STREAM_DRAW这样就能确保显卡把数据放在能够高速写入的内存部分。现在我们已经把顶点数据储存在显卡的内存中用VBO这个顶点缓冲对象管理。
更新缓冲区中的数据
glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
更新缓冲区中的数据。target和之前两个方法的参数一样data指写入缓冲区的数据所在数组头指针size指data数组中要写入缓冲区的数据的字节数offset指要写入缓冲区的第一个数据在data数组的位置。也即将data数组中从offset字节为单位开始的size个字节写入缓冲区。
删除缓冲区
glDeleteBuffers(GLsizei n, const GLuint* buffers);
删除buffers中前n个缓冲区对象他们的名称就是buffers数组中的元素。
4、VBO应用
创建VBO四步
val buffers IntArray(1)
//1.生成一个VBO,并ID存储在VBO中,此时VBO拥有了其唯一的id
GLES20.glGenBuffers(buffers.size, buffers, 0)
if (buffers[0] 0) {Log.d(TAG, can not create a new vertex buffer object.)
}
bufferId buffers[0]
//2.绑定缓冲区
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0])
val vertexArray ByteBuffer.allocateDirect(indexData.size * BYTES_PER_SHORT).order(ByteOrder.nativeOrder()).asShortBuffer().put(indexData)
vertexArray.position(0)
//3.将顶点数据复制到缓冲中,并指定数据用以静态访问
将顶点数据上传到GPU内存中以便后续的渲染操作。
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,vertexArray.capacity() * BYTES_PER_SHORT,vertexArray,GLES20.GL_STATIC_DRAW
)
//4.将buffer id设置为0解绑缓冲区
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0)
四、顶点数组对象VAO
1、概念
VAO(vertex Array Object)顶点数组对象。
注意 VAO是OpenGL ES 3.0之后才推出的新特性 所以在使用VAO前需要确定OpenGL ES的版本是否是3.0之后的版本。
顶点数组对象可以像顶点缓冲对象那样被绑定任何随后的顶点属性调用都会储存在这个VAO中。这样的好处就是当配置顶点属性指针时你只需要将那些调用执行一次之后再绘制物体的时候只需要绑定相应的VAO就行了。这使在不同顶点数据和属性配置之间切换变得非常简单只需要绑定不同的VAO就行了。刚刚设置的所有状态都将存储在VAO中。
VAO用于保存顶点属性数组的状态包括与VBO的绑定以及顶点属性的配置。
2、为什么使用VAO
解释1
顶点属性存储有2种方式客户端顶点数组和顶点缓冲区对象。VAO使得客户端顶点数组的数据传入VBO的速度加快。
通过VAO开发者可以一次性配置好顶点数组的所有状态在后续的绘制中快速恢复这些状态减少OpenGL函数调用次数提升效率。
解释2
在上面VBO的介绍中我们知道每次在绘制的时候都需要频繁地绑定与解绑VBO每次绘制还需要取出VBO中的数据进行赋值之后才能进行绘制渲染。当数据量大的时候重复这些操作就会变得很繁琐。通过VAO就可以简化这个过程因此VAO可以简单理解成VBO的管理者避免在帧绘制时再去手动操纵VBOVAO不能单独使用 需要搭配VBO使用。
对于GPU来说VBO就是一堆数据但是这堆数据怎么解析使用需要glEnableVertexAttribArray等相关函数在每次绘制的时候告诉GPU那么VAO的作用就是简化这个过程的只需要在初始化的时候将这些解析逻辑与VAO绑定一次即可 然后每次在绘制的时候只需绑定对应的VAO而不必每次再绑定VBO然后去告诉GPU如何解析相关数据了可以说是一个性能的优化了。 解释3 当我们再绘制不同的顶点数据或者是其他数据时我们需要重新进行一遍绑定设置等等操作来完成绘制不同这时候就引出顶点数组对象。
在OpenGL中顶点数组对象Vertex Array ObjectVAO是一种OpenGL对象用于存储顶点数据的状态信息包括顶点坐标、法线、纹理坐标等。VAO可以看作是一种包含了多个顶点属性配置的容器使得你可以在绘制时轻松地切换和使用不同的顶点数据。
顶点数组对象的使用可以帮助你更有效地组织和管理顶点数据特别是在绘制多个物体或者在渲染循环中多次切换不同的顶点数据时。
其实可能还不太明白其实使用的时候确实都是要走绑定顶点缓冲区然后设置顶点的布局等等但是我们现在把上面一套流程放进了一个叫VAO的对象中也就是生成绑定它就相当于走完了内部的一套流程在换顶点数据或者顶点布局的时候就不需要再写一遍这么麻烦了相当于是封装了一层我们后续可以看看其实也是真的要封装一层的我们可以通过在换顶点布局或者顶点数据的时候体现流程
老一套的流程是
1.解绑并重新绑定新的着色器程序 glUseProgram(0) glUseProgram(shaderID) 2.解绑和重新绑定顶点缓冲区 glBindBuffer(GL_ARRAY_BUFFER, 0) glBindBuffer(GL_ARRAY_BUFFER, buffer)); 3.重新设置顶点的布局 glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0); 4.绑定我们的索引缓冲区 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)); 5.绘制调用glDrawElements
引入VAO之后我们要更改数据就变成了这样
1.解绑并重新绑定新的着色器程序 glUseProgram(0) glUseProgram(shaderID) 2.绑定顶点数组包含了绑定顶点缓冲区设置顶点的布局方便直接绑定别的可以切换glBindVertexArray(vao)3.绑定索引缓冲glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)4.绘制调用glDrawElements
另外这个顶点数组对象对于OpenGL是强制性的因为即使我们没有创建它还是走的老一套流程其实状态还是由顶点数组对象来维护的。
3、如何使用VAO
生成VAO
unsigned int VAO;
glGenVertexArrays(1, VAO);
绑定VAO
glBindVertexArray(VAO)
解绑VAO
glBindVertexArray(0)
删除VAO
glDeleteVertexArrays
4、VAO应用
// 生成VAO和VBO
GLuint vao;
glGenVertexArrays(1, vao);
GLuint vbo;
glGenBuffers(1, vbo);// 绑定VAO
glBindVertexArray(vao);// 绑定VBO并设置顶点数据
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// 配置顶点属性用于将当前的顶点属性与顶点缓冲对象VBO关联起来
//配置顶点属性指针 使用 glVertexAttribPointer 函数配置顶点属性指针告诉OpenGL如何解释顶点数据。
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);// 解绑VAO和VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
五、索引缓冲区对象EBO/IBO
1、概念
IBO/EBO, Element Buffer Objec索引缓冲区对象。EBO用于存储顶点的索引数据允许通过索引引用顶点避免重复存储相同的顶点数据。
索引缓冲区和顶点缓冲区类似也是显存上的一段内存只不过上面的数据用处不同索引缓冲区故名思义里面的数据是用于索引主要作用是用于复用顶点缓冲区里的数据。
使用的GL_ELEMENT_ARRAY_BUFFER表示索引缓冲区。
2、为什么使用IBO/EBO
解释1
EBO提高了渲染效率减少了顶点数据的冗余尤其在渲染复杂网格时通过索引复用顶点能够显著节省内存。
解释2
OpenGL渲染都是渲染三角形如果我们想渲染一个正方形就要通过渲染两个三角形拼接成一个正方形那么这两个三角形有两个顶点是重合的如果没有索引缓冲区两个三角形则需要六个顶点而实际上一个正方形只有四个顶点这里有两个顶点时数据冗余。仅仅一个正方形就有这么多冗余那么一个复杂的游戏场景就会浪费非常多的内存。
解释3
为什么使用EBO
正常画一个立方体需要8个顶点合计6个面。 但实际我们是用了4*624个点来画的因为4个点组成一个面我们能看出来有很多重复点为了能节省内存空间我们想只用8个点描画立方体这需要用到EBO
VertexData vc[] {//正面{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4//右面{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3//左面{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1{QVector3D(-0.5f, 0.0f, -0.5f),QVector3D(1.0f, 0.0f, 1.0f)}, //8{QVector3D(-0.5f, 1.0f, -0.5f),QVector3D(1.0f, 0.6f, 0.0f)}, //7{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4//背面{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6{QVector3D(-0.5f, 1.0f, -0.5f), QVector3D(1.0f, 0.6f, 0.0f)}, //7{QVector3D(-0.5f, 0.0f, -0.5f), QVector3D(1.0f, 0.0f, 1.0f)}, //8//顶面{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6{QVector3D(-0.5f, 1.0f, -0.5f), QVector3D(1.0f, 0.6f, 0.0f)}, //7{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4//底面{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5{QVector3D(-0.5f, 0.0f, -0.5f), QVector3D(1.0f, 0.0f, 1.0f)}, //8{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1};EBO原理
//顶点有8个
VertexData vcs[] {//正面{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6{QVector3D(-0.5f, 1.0f, -0.5f),QVector3D(1.0f, 0.6f, 0.0f)}, //7{QVector3D(-0.5f, 0.0f, -0.5f),QVector3D(1.0f, 0.0f, 1.0f)}, //8};
//索引 对应8个面每个面说明使用哪4个顶点GLuint indices[] { // 起始于0!0, 1, 2, 3, // face 11, 4, 5, 2, // face 20, 7, 6, 3, // face 34, 5, 6, 7, // face 42, 5, 6, 3, // face 51, 4, 7, 0, // face 6};3、如何使用EBO
生成EBO glGenBuffers(1, EBO);
绑定EBO glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
输入数据到缓冲区 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
链接属性
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)0);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)sizeof(QVector3D));
绘制
/*
glDrawElements是用于渲染索引缓冲区
第一个和其他DrawCall一样
第二个参数是count表示有多少顶点需要渲染
第三个参数是索引缓冲区参数类型必须是GLES30.GL_UNSIGNED_SHORT或者GL_UNSIGNED_BYTE
第四个参数是offset。
*/
GLES30.glDrawElements(GLES30.GL_TRIANGLES, count, type, offset)PS: 绑定和解绑的顺序很重要勿更改另外EBO不用解绑就算要解绑也要在VAO解绑后。
4、EBO应用
//1 使用glGenBuffers函数生成一个缓冲ID
glGenVertexArrays(1, VAO);
glGenBuffers(1, VBO);
glGenBuffers(1, EBO);
//2 绑定vao
glBindVertexArray(VAO);
//3 使用glBindBuffer函数把新创建的缓冲绑定到GL_ARRAY_BUFFER缓冲类型上
glBindBuffer(GL_ARRAY_BUFFER, VBO); //绑定和解绑的顺序很重要勿更改
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
//4 把用户定的义数据复制到当前绑定缓冲的函数
glBufferData(GL_ARRAY_BUFFER, sizeof(vcs), vcs, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//5 链接顶点属性//indx: 属性名//size: 顶点大小//type: 数据类型//normalized数据被标准化//stride: 步长//ptr: 数据在缓冲中起始位置的偏移量
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)0);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)sizeof(QVector3D));
//6 解绑缓存绑定和解绑的顺序很重要勿更改
glBindBuffer(GL_ARRAY_BUFFER, 0);
//7 解绑VAO
glBindVertexArray(0);
5、绘制过程
//1 绑定vao
glBindVertexArray(VAO);
//2 开启顶点属性
glEnableVertexAttribArray(0);
//颜色值
glEnableVertexAttribArray(1);
//3 绘制四边形24个索引值
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, (GLvoid*)0);
//4 停用对应的顶点属性数组
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
//5 解绑VAO
glBindVertexArray(0); 六、总结
1、常用各类缓冲区分析
VBO: 存储大量顶点,因而可以利用VBO一次性发送大量数据到显卡 VAO: 配置并告诉了OpenGL如何使用VBO,以及使用哪个VBO
EBO/IBO
索引缓冲区里面就是存储了一系列索引用于复用顶点缓冲区。 有个问题大家可能会想之前用6个顶点也不过18个数使用了顶点缓冲区后变为12个但是索引缓冲区还有6个好像没有节省多少内存。 但是实际上顶点可能包含了非常多的数据比如我们之前用它来存颜色它还可以存纹理等额外数据实际应用场景一个顶点可能有非常多数据所以复用可节省的内存是非常可观的。
2、无法删除缓冲区
OpenGL并没有提供直接删除缓冲区的函数或方法。这是因为OpenGL的设计理念是尽可能地提供高性能和灵活性而不是提供高级别的内存管理功能。因此开发者需要手动管理缓冲区的生命周期。
要删除缓冲区开发者需要按照以下步骤进行操作 解绑缓冲区在删除缓冲区之前需要先解绑缓冲区。可以使用glBindBuffer函数将当前的缓冲区绑定到一个无效的缓冲区对象上例如glBindBuffer(GL_ARRAY_BUFFER, 0)。 删除缓冲区对象使用glDeleteBuffers函数来删除缓冲区对象。该函数接受一个整数参数表示要删除的缓冲区对象的数量以及一个指向缓冲区对象的指针。例如glDeleteBuffers(1, bufferObject)将删除名为bufferObject的缓冲区对象。
需要注意的是删除缓冲区对象并不会自动释放缓冲区所占用的内存。开发者需要在删除缓冲区对象之前确保已经释放了缓冲区所占用的内存以避免内存泄漏。 七、源码下载
VAO顶点数组对象应用演示demo源码下载
https://download.csdn.net/download/github_27263697/89915626
VBO顶点缓冲区对象应用演示demo源码下载
https://download.csdn.net/download/github_27263697/89915617
EBO/IBO索引缓冲区对象应用演示demo源码下载
https://download.csdn.net/download/github_27263697/89916753 参考文章
OpenGL入门四顶点缓冲区_顶点缓冲器有什么用-CSDN博客
Android OpenGL ES 2.0七--- 顶点缓冲区对象-CSDN博客
OpenGL 入门二— 顶点数组对象VAO和顶点缓冲对象VBO_glvertexattribpointer-CSDN博客
你好三角形 - LearnOpenGL CN
https://segmentfault.com/a/1190000042610598?sortnewest#item-1
OpenGL学习总结-数据缓存区四_opengl genbuffer-CSDN博客
一篇搞懂OpenGL uniforms变量和顶点数组对象Vertex Array ObjectVAO_glgenvertexarrays-CSDN博客OpenGL无法删除缓冲区_OpenGL/OpenTK -多帧缓冲区_使用OpenGL内插数据缓冲区 - 腾讯云开发者社区 - 腾讯云小白学opengl 第五课 之 索引缓冲对象 - 踏月清风 - 博客园OpenGL无法删除缓冲区_OpenGL/OpenTK -多帧缓冲区_使用OpenGL内插数据缓冲区 - 腾讯云开发者社区 - 腾讯云一篇搞懂OpenGL uniforms变量和顶点数组对象Vertex Array ObjectVAO_glgenvertexarrays-CSDN博客OpenGL ES 索引缓冲区(4)_opengl索引缓冲区-CSDN博客 文章转载自: http://www.morning.szoptic.com.gov.cn.szoptic.com http://www.morning.gwmny.cn.gov.cn.gwmny.cn http://www.morning.gywxq.cn.gov.cn.gywxq.cn http://www.morning.wfbnp.cn.gov.cn.wfbnp.cn http://www.morning.guanszz.com.gov.cn.guanszz.com http://www.morning.sqfnx.cn.gov.cn.sqfnx.cn http://www.morning.jycr.cn.gov.cn.jycr.cn http://www.morning.lhqw.cn.gov.cn.lhqw.cn http://www.morning.hnrdtz.com.gov.cn.hnrdtz.com http://www.morning.xwbwm.cn.gov.cn.xwbwm.cn http://www.morning.srkwf.cn.gov.cn.srkwf.cn http://www.morning.khdw.cn.gov.cn.khdw.cn http://www.morning.drcnf.cn.gov.cn.drcnf.cn http://www.morning.xylxm.cn.gov.cn.xylxm.cn http://www.morning.tdzxy.cn.gov.cn.tdzxy.cn http://www.morning.nynyj.cn.gov.cn.nynyj.cn http://www.morning.dbdmr.cn.gov.cn.dbdmr.cn http://www.morning.fbylq.cn.gov.cn.fbylq.cn http://www.morning.kqzt.cn.gov.cn.kqzt.cn http://www.morning.phjyb.cn.gov.cn.phjyb.cn http://www.morning.wpqwk.cn.gov.cn.wpqwk.cn http://www.morning.rqrh.cn.gov.cn.rqrh.cn http://www.morning.dbbcq.cn.gov.cn.dbbcq.cn http://www.morning.ncwgt.cn.gov.cn.ncwgt.cn http://www.morning.lfcfn.cn.gov.cn.lfcfn.cn http://www.morning.jjwt.cn.gov.cn.jjwt.cn http://www.morning.jpzcq.cn.gov.cn.jpzcq.cn http://www.morning.tklqs.cn.gov.cn.tklqs.cn http://www.morning.nlkjq.cn.gov.cn.nlkjq.cn http://www.morning.ssxlt.cn.gov.cn.ssxlt.cn http://www.morning.qmwzz.cn.gov.cn.qmwzz.cn http://www.morning.lyldhg.cn.gov.cn.lyldhg.cn http://www.morning.xqcbz.cn.gov.cn.xqcbz.cn http://www.morning.5-73.com.gov.cn.5-73.com http://www.morning.bxqtq.cn.gov.cn.bxqtq.cn http://www.morning.bpmnj.cn.gov.cn.bpmnj.cn http://www.morning.ishoufeipin.cn.gov.cn.ishoufeipin.cn http://www.morning.jgrjj.cn.gov.cn.jgrjj.cn http://www.morning.wtbzt.cn.gov.cn.wtbzt.cn http://www.morning.lveyue.com.gov.cn.lveyue.com http://www.morning.wkqrp.cn.gov.cn.wkqrp.cn http://www.morning.jjxxm.cn.gov.cn.jjxxm.cn http://www.morning.qxltp.cn.gov.cn.qxltp.cn http://www.morning.pyncx.cn.gov.cn.pyncx.cn http://www.morning.bssjz.cn.gov.cn.bssjz.cn http://www.morning.fhtbk.cn.gov.cn.fhtbk.cn http://www.morning.wsyst.cn.gov.cn.wsyst.cn http://www.morning.ymwcs.cn.gov.cn.ymwcs.cn http://www.morning.tslwz.cn.gov.cn.tslwz.cn http://www.morning.lcwhn.cn.gov.cn.lcwhn.cn http://www.morning.wkwds.cn.gov.cn.wkwds.cn http://www.morning.wwsgl.com.gov.cn.wwsgl.com http://www.morning.ryyjw.cn.gov.cn.ryyjw.cn http://www.morning.cnqwn.cn.gov.cn.cnqwn.cn http://www.morning.wtdhm.cn.gov.cn.wtdhm.cn http://www.morning.dbbcq.cn.gov.cn.dbbcq.cn http://www.morning.sdamsm.com.gov.cn.sdamsm.com http://www.morning.xtkw.cn.gov.cn.xtkw.cn http://www.morning.hsgxj.cn.gov.cn.hsgxj.cn http://www.morning.tnfyj.cn.gov.cn.tnfyj.cn http://www.morning.rsnd.cn.gov.cn.rsnd.cn http://www.morning.fnzbx.cn.gov.cn.fnzbx.cn http://www.morning.httzf.cn.gov.cn.httzf.cn http://www.morning.qzmnr.cn.gov.cn.qzmnr.cn http://www.morning.lxdbn.cn.gov.cn.lxdbn.cn http://www.morning.mlycx.cn.gov.cn.mlycx.cn http://www.morning.ztqyj.cn.gov.cn.ztqyj.cn http://www.morning.c7495.cn.gov.cn.c7495.cn http://www.morning.gctgc.cn.gov.cn.gctgc.cn http://www.morning.pbknh.cn.gov.cn.pbknh.cn http://www.morning.ykklw.cn.gov.cn.ykklw.cn http://www.morning.fsrtm.cn.gov.cn.fsrtm.cn http://www.morning.wlxfj.cn.gov.cn.wlxfj.cn http://www.morning.sbwr.cn.gov.cn.sbwr.cn http://www.morning.ckfyp.cn.gov.cn.ckfyp.cn http://www.morning.tkyry.cn.gov.cn.tkyry.cn http://www.morning.lpyjq.cn.gov.cn.lpyjq.cn http://www.morning.gnjtg.cn.gov.cn.gnjtg.cn http://www.morning.bxsgl.cn.gov.cn.bxsgl.cn http://www.morning.rfhmb.cn.gov.cn.rfhmb.cn