OpenGL进阶 | glDrawArrays与glDrawElements

news/2025/1/16 7:53:35/

        glDrawArrays直接从顶点缓冲对象(VBO)中读取顶点数据,而glDrawElements使用一个元素缓冲对象(EBO)来指定顶点的索引。那么什么是EBO呢?

1.ElementArrayBufferObject

        ElementArrayBufferObject,简称EBO,用来节省内存开销。     

        在渲染3D场景时,通常需要绘制许多三角形或其他类型的图元,这时候存在顶点数据公用的现象,为了减少数据的重复,可以使用索引数组来定义顶点的顺序,这使得顶点可以在多个图元中共享。ElementArrayBufferObject就是用来存储这些索引数据的。

        通常情况下,我们使用一个顶点缓冲对象(VertexBufferObject)存储顶点数据,然后使用一个元素数组缓冲对象(ElementArrayBufferObject)存储顶点的索引。

2.举个例子

(1)使用glDrawArrays

        glDrawArrays是WebGL中的一个绘制函数,用于绘制几何图形。它从当前的顶点缓冲对象中读取顶点数据,并按照指定的参数进行绘制。这个函数绘制的图形是由顶点数据直接确定的,没有使用到顶点索引。

void Init()
{float data[] = {-0.2f,-0.2f,-0.6f,1.0f,0.2f,-0.2f,-0.6f,1.0f,-0.2f,0.2f,-0.6f,1.0f};glGenBuffers(1, &vbo);                                                   //需要1个VBO,把vbo写入到显卡进去,供后续操作glBindBuffer(GL_ARRAY_BUFFER, vbo);                                      //把vbo设置到卡槽上//glBufferData(GL_ARRAY_BUFFER,sizeof(float)*12, nullptr,GL_STATIC_DRAW);//只在GPU上开辟内存不传数据glBufferData(GL_ARRAY_BUFFER,sizeof(float)*12,data,GL_STATIC_DRAW);      //将数据从cpu传到Gpu,此后data数据可删除。glBindBuffer(GL_ARRAY_BUFFER, 0);                                        //卡槽重新绑定,防止误操作//读取shader源码到GPU程序//...//读取shader变量//...
}
void Draw()
{glClearColor(0.0f, 1.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//设置Uniform变量//...glBindBuffer(GL_ARRAY_BUFFER, vbo);  //将顶点缓冲对象绑定到OpenGL的顶点缓冲区(GL_ARRAY_BUFFER)glEnableVertexAttribArray(positionLocation);  //启用位置属性索引为positionLocation的顶点属性数组glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4, 0);   //定义位置属性glDrawArrays(GL_TRIANGLES, 0, 3);    //执行绘制操作。该函数指定了绘制的模式、起始顶点索引和顶点数量。glBindBuffer(GL_ARRAY_BUFFER, 0);    //解绑顶点缓冲对象
}

(2)使用glDrawElements

        使用glDrawElements时,我们需要事先创建一个元素缓冲对象(EBO),并将顶点索引数据存储在其中。这些索引指定了顶点在顶点缓冲对象中的顺序,从而确定了绘制的顺序。通过使用索引,我们可以共享顶点数据,减少存储空间和数据传输量,并允许更复杂的图形绘制。

        使用glDrawElements相比于glDrawArrays的主要优势在于它允许更高效地绘制具有共享顶点的复杂图形。

void Init()
{float data[] = {-0.2f,-0.2f,-0.6f,1.0f,0.2f,-0.2f,-0.6f,1.0f,-0.2f,0.2f,-0.6f,1.0f};glGenBuffers(1, &vbo);                                                   //需要1个VBO,把vbo写入到显卡进去,供后续操作glBindBuffer(GL_ARRAY_BUFFER, vbo);                                      //把vbo设置到卡槽上//glBufferData(GL_ARRAY_BUFFER,sizeof(float)*12, nullptr,GL_STATIC_DRAW);//只在GPU上开辟内存不传数据glBufferData(GL_ARRAY_BUFFER,sizeof(float)*12,data,GL_STATIC_DRAW);      //将数据从cpu传到Gpu,此后data数据可删除。glBindBuffer(GL_ARRAY_BUFFER, 0);                                        //卡槽重新绑定,防止误操作unsigned int indices[] = { 0, 1, 2,       // 第一个三角形 };glGenBuffers(1, &ebo);                                                   //创建1个EBO,并将标识符存储在ebo变量中glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);                               //将EBO绑定到GL_ELEMENT_ARRAY_BUFFER目标glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 3, indices, GL_STATIC_DRAW); //将索引数据从CPU传输到GPUglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);                                 //将索引数据从CPU传输到GPU//读取shader源码到GPU程序//...//读取shader变量//...
}
void Draw()
{glClearColor(0.0f, 1.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//设置Uniform变量//...glBindBuffer(GL_ARRAY_BUFFER, vbo);  //将顶点缓冲对象绑定到OpenGL的顶点缓冲区(GL_ARRAY_BUFFER)glEnableVertexAttribArray(positionLocation);  //启用位置属性索引为positionLocation的顶点属性数组glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4, 0);   //定义位置属性glBindBuffer(GL_ARRAY_BUFFER, 0);    //解绑顶点缓冲对象glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}


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

相关文章

Python库 pdf2docx 轻松将PDF转换成docx

前言: 可将 PDF 转换成 docx 文件的 Python 库。该项目通过 PyMuPDF 库提取 PDF 文件中的数据,然后采用 python-docx 库解析内容的布局、段落、图片、表格等,最后自动生成 docx 文件。 pdf2docx功能 解析和创建页面布局 页边距章节和分栏 (目…

推荐 5 月份炫炫炫的 GitHub 项目

推荐 6 个五月份比较火的开源项目。因为近期 AI 项目的火爆,每天 GitHub 热榜都被 AI 项目占据,后续开源项目会同时盘点 AI 和其他分类的开源项目。 本期推荐开源项目目录: 1. 多合一聊天机器人客户端(AI) 2. 数据库场…

【PCIE702-1】基于Kintex UltraScale系列FPGA的高性能PCIe总线数据预处理载板

板卡概述 PCIE702-1是一款基于PCIE总线架构的高性能数据预处理FMC载板,板卡采用Xilinx的高性能Kintex UltraScale系列FPGA作为实时处理器,实现各个接口之间的互联。板卡具有1个FMC(HPC)接口,1路PCIe x8主机接口&#x…

【fps系统重构】-观察cpu、memroy、io -iostat

当您使用iostat命令监控磁盘I/O情况时,可以查看以下指标: rrqm/s:每秒发生的读请求被合并的次数。如果该指标很低,说明读请求较少或未被合并,可能会导致磁盘I/O负载过重。wrqm/s:每秒发生的写请求被合并的…

嵌入式 QT QListWidget 显示列表视图的小部件类

目录 1. 添加对象 2. 设置间距 3. 获取内容 4. 删除对象 5.更改对象内容 在Qt框架中,QListWidget是一个用于显示列表视图的小部件类。它提供了一种方便的方式来显示和管理项目列表。QListWidget可以显示文本、图像和其他自定义的项目项,并允许用户进…

Java数组和列表的区别

数组(Array)与列表(ArrayList)的区别 列表(ArrayList)是对数组(Array)的一个加强 (1)空间大小 Array的空间大小是固定的,空间不够时也不能再次…

LC-1377. T 秒后青蛙的位置(DFS、BFS)

1377. T 秒后青蛙的位置 难度困难57 给你一棵由 n 个顶点组成的无向树,顶点编号从 1 到 n。青蛙从 顶点 1 开始起跳。规则如下: 在一秒内,青蛙从它所在的当前顶点跳到另一个 未访问 过的顶点(如果它们直接相连)。青…

ThinkPHP6 模型层的模型属性,表映射关系,以及如何在控制层中使用模型层和模型层中的简单CRUD

ThinkPHP6 模型层的模型属性,表映射关系,以及模型层的CRUD及如何在控制层中使用模型层 1. model 模型层的默认映射规则 模型,即mvc模式中的model层,model层用来对接数据库,操作数据库的增删改查。 在tp6中&#xff…