惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Latest
Security Latest
Know Your Adversary
Know Your Adversary
S
Schneier on Security
K
Kaspersky official blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Google DeepMind News
Google DeepMind News
Project Zero
Project Zero
Recorded Future
Recorded Future
T
The Blog of Author Tim Ferriss
P
Palo Alto Networks Blog
Engineering at Meta
Engineering at Meta
MyScale Blog
MyScale Blog
L
LINUX DO - 热门话题
The Register - Security
The Register - Security
B
Blog
V
Vulnerabilities – Threatpost
M
MIT News - Artificial intelligence
P
Proofpoint News Feed
Cyberwarzone
Cyberwarzone
Latest news
Latest news
Webroot Blog
Webroot Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
美团技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
CXSECURITY Database RSS Feed - CXSecurity.com
L
LINUX DO - 最新话题
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
B
Blog RSS Feed
aimingoo的专栏
aimingoo的专栏
The GitHub Blog
The GitHub Blog
D
Docker
G
Google Developers Blog
T
Threatpost
F
Full Disclosure
Attack and Defense Labs
Attack and Defense Labs
L
Lohrmann on Cybersecurity
Application and Cybersecurity Blog
Application and Cybersecurity Blog
月光博客
月光博客
D
DataBreaches.Net
WordPress大学
WordPress大学
F
Fortinet All Blogs
S
Secure Thoughts
Y
Y Combinator Blog
博客园 - Franky
Scott Helme
Scott Helme
Apple Machine Learning Research
Apple Machine Learning Research
Hacker News: Ask HN
Hacker News: Ask HN
酷 壳 – CoolShell
酷 壳 – CoolShell
Cloudbric
Cloudbric
N
News | PayPal Newsroom

博客园 - 夏天/isummer

vcpkg的安装,配置vs2022, 全局使用,清单使用 wsGLCanvas中的OnPaint和OnSize的调用顺序 Visual Studio 2022中配置Eigen.Natvis文件,实现Debug查看:Eigen库查看矩阵与向量的值 “模型法线到视图法线”的变换矩阵(normal matrix)的计算和作用 python 用control库绘制自动控制原理中的根轨迹: C++ 无法从“const char [ ]”转换为“char *” 根据文件内存字节数,返回文件占用内存大小:单位:T,G,M,K,B 泛洪算法(Flood fill Algorithm):符号洪水填充算法 opengl中的glDrawElements 用法和glDrawArray OpenGL着色器Shader小结 VS2022 在编译大型项目出现:c/c++ intellance 操作-优化VS2022,提高Intellance速度 用VS2022创建空桌面程序【Empty】运行wxWidgets应用,报错:MSVCRTD.lib(exe_main.obj) : error LNK2019: 无法解析的外部符号 main VS下使用全局配置的方式使用VCPKG vcpkg 安装过程中install的参数: ApriTags应用 【/MT、/MTd、/MD、/MDd】C++ 出现异常“.... \debug_heap.cpp Line:980 Expression:__acrt_first_block==header"【已解决】 - 夏天/isummer QString的tostdstring问题-提示堆栈内存溢出(2024.12) vsftpd和FileZiler配置:本地登录,支持上传-下载-删除文件和目录-添加文件和目录 PyQt开发-mkvirtualenv虚拟环境 线程池ThreadPool, C++ github 命令git下载失败: Failed to connect to github.com port 443 解决方案,解决CMAKE中下载其他库失败的问题
opengl中的VBO,IBO,VAO,EBO总结:
夏天/isummer · 2025-07-10 · via 博客园 - 夏天/isummer

比较常用的时:VBO配合IBO使用。

OpenGL理解VBO,IBO,VAO:https://blog.csdn.net/Mhypnos/article/details/123516615

VBO,VAO和EBO详解:https://www.jianshu.com/p/c7833cd9553a

Opengl:EBO和IBO的使用:https://blog.csdn.net/weixin_44629261/article/details/145257838

VBO:VBO(Vertex Buffer Objects)顶点缓冲区对象,需要绑定缓存类型:GL_ARRAY_BUFFER 指的是在 GPU 显存里面存储的顶点数据(位置、颜色,纹理等)。仅仅时GPU内存中存放的时顶点各种属性

IBO:(Index Buffer Objects) 顶点索引缓冲区对象,需要绑定缓存类型:GL_ELEMENT_ARRAY_BUFFER。 可以利用点的索引,来构建三角面面片,减少上传GPU中点的数量。使用基于索引的绘图机制。

EBO:Element Buffer Object  元素缓存对象,需要绑定缓存类型:GL_ELEMENT_ARRAY_BUFFER。 于存储顶点索引,避免重复存储相同顶点,减少内存消耗。

VAO:Vertex Array Object 顶点数组对象,就是保存VBO(以及IBO,如果用的话)中的属性配置。

二、void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices);
1、从索引缓冲区渲染模型,即从当前绑定到GL_ELEMENT_ARRAY_BUFFER目标的EBO中获取其索引。
2、mode指定要绘制的图元类型。
3、count指定要绘制的顶点个数。
4、type指定索引数据类型。
5、indices即可以指定EBO的偏移量(使用EBO),也可以传递一个索引数组(不使用EBO,不建议)。
 

总结:VBO,VAO,EBO之间的联系与区别

   ① 顶点缓冲对象 VBO (VertexBufferOjbect)是在显卡存储空间中开辟出的一块内存缓存区,用于存储顶点的各类属性信息,如顶点坐标、顶点法向量、顶点颜色数据等。在渲染时,可以直接从 VBO 中取出顶点的各类属性数据,由于 VBO 在显存而不是在内存中,不需要从CPU传输数据,所以处理效率更高。

  所以可以理解为 VBO 就是显存中的一个存储区域,可以保持大量的顶点属性信息。并且可以开辟很多个 VBO ,每个 VBO 在 OpenGL 中有它的唯一标识 ID ,这个 ID 对应着具体的 VBO 的显存地址,通过这个 ID 可以对特定的 VBO 内的数据进行存取操作。

  • VBO就像一个仓库,专门存放3D模型所需要的原材料(顶点数据)。所有材料都是提前存放到仓库中的,使用时可以直接取用,无需临时搬运。
  • 支持批量数据传输,例如一次性存储万个顶点数据
  • 避免每帧将顶点数据从CPU传输到GPU,提升渲染性能

  ② VAO 是一个保存了所有顶点数据属性的状态结合,它存储了顶点数据的格式以及顶点数据所需的 VBO 对象的引用,记录GPU如何从与之配对的VBO中读取数据
   因为 VBO 保存了一个模型的顶点属性信息,每次绘制模型之前需要绑定顶点的所有信息。当数据量很大时,重复这样的动作变得非常麻烦。VAO 可以把这些所有的配置都存储在一个对象中,每次绘制模型时,只需要绑定这个 VAO 对象就可以了。

  另外,VAO 本身并没有存储顶点的相关属性数据,这些信息是存储在 VBO 中的,VAO 相当于是对很多个 VBO 的引用,把一些 VBO 组合在一起作为一个对象统一管理。

  • 简化顶点属性配置流程,避免每次绘制重复设置
  • 绑定VAO后自动恢复关联的VBO和属性配置
  • VAO就像一本说明书,告诉工人(GPU)如何从仓库(VBO)中取出材料,并按什么规格(数据类型、偏移量)组装零件(顶点)

 ③ 索引缓冲对象 EBO(Element Buffer Object 索引缓冲对象),  相当于 OpenGL 中的顶点数组的概念,是为了解决同一个顶点多次重复调用的问题,可以减少内存空间浪费,提高执行效率。当需要使用重复的顶点时,通过顶点的位置索引来调用顶点,而不是对重复的顶点信息重复记录,重复调用。
   EBO 中存储的内容就是顶点位置的索引 indices,EBO 跟 VBO 类似,也是在显存中的一块内存缓冲器,只不过 EBO 保存的是顶点的索引。

为什么使用EBO

使用场景:

  绘制复杂网格模型,同一顶点会被多个图元共享,用索引来标记每个三角形用到哪个顶点,而不用相同顶点重复创建

优点

  1. 节省内存。
  2. 减少顶点处理次数,提升缓存效效率
没有EBO代码,需要重复保存多个顶点数据:

float vertices[] = {
    // 第一个三角形
    0.0f,  0.5f, 0.0f,
   -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    // 第二个三角形
    0.5f, -0.5f, 0.0f,
    1.0f,  0.0f, 0.0f,
    0.0f,  0.5f, 0.0f
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

上面用到的顶点都直接上传GPU了(尽管优点顶点重复使用)。可以很清楚的看到,上面的例子中,两个三角形有一些共用的顶点,但是还是重新写了一遍,就很浪费,所以这时候就要EBO登场了。
-------------------------------------------------------
使用 EBO 的代码

float vertices[] = {
    0.0f,  0.5f, 0.0f,
   -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    1.0f,  0.0f, 0.0f
};
// 用索引来标记每个三角形用到的哪个顶点
unsigned int indices[] = {
    0, 1, 2,
    2, 3, 0
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

unsigned int ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);//绑定ebo,激活ebo
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//向CPU分配并初始化该ebo的内存

用一个indices的数组指定了每个图元使用的顶点的顺序就好了,这样当在有大量重复顶点的时候,就很省了。

为什么使用VAO()?

 VAO ( Vertex Array Object )是OpenGL用来处理顶点数据的一个缓冲区对象,它不能单独使用,都是结合VBO来一起使用的。

当我们使用VBO传入顶点数据时,一般的处理如下:

// 绑定VBO,设置VBO中的数据
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 1. 设置顶点属性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);  
// 2. 使用Shader程序
glUseProgram(shaderProgram);
// 3. 绘制
someOpenGLFunctionThatDrawsOurTriangle();  

  注意,以上不适用VAO也可以,但是:每次都要如上配置:顶点属性以及激活顶点属性。麻烦:

      每当我们绘制一个几何体时,我们需要重复同样的工作(首先绑定缓冲区、然后设置顶点属性)。因为,没有顶点属性的配置,GPU不知道VBO如何使用。

  当需要绘制的物体很多时,这个过程就显得有些耗时。那么我们有没有一种方式来简化这一过程呢?这就是VAO做的事情,它将所有顶点绘制过程中的这些设置和绑定过程集中存储在一起,当我们需要时,只需要使用相应的VAO即可。

  VAO 本质上是状态记录器,是一种管理 OpenGL 顶点属性配置的对象,用于记录 VBO 和 EBO 的绑定状态及顶点属性设置,避免重复配置。(通俗点的讲,就是VAO只是个指针而已,实际干活的人还是VBO和EBO)

使用场景

  1. 场景复杂,有多个对象需要渲染时,使用 VAO 可以减少顶点属性配置的复杂度。
  2. 多次绘制同一个对象,减少状态切换。

优点

1. 减少状态切换。
将所有顶点属性配置打包到一个对象中,后续渲染时只需绑定 VAO 而不是重新配置,避免重复调用 glVertexAttribPointer。
2.简化代码。
管理多个 VBO、EBO,逻辑清晰。
3.提升性能。
减少 OpenGL 状态变更调用的次数。

VAO包含的内容

1. VAO开启或者关闭的状态(glEnableVertexAttribArray和glDisableVertexAttribArray)
2. 使用glVertexAttribPointer对顶点属性进行的设置
3. 存储顶点数据的VBO对象

 使用如下:

//创建VAO
GLuint VAO;
glGenVertexArrays(1, &VAO);
//设置当前VAO,之后所有操作(注意:这些操作必须是上文VAO中包含的内容所注明的调用,其他非VAO中存储的内容即使调用了也不会影响VAO)存储在该VAO中
glBindVertexArray(VAO);
   glBindBuffer(GL_ARRAY_BUFFER, VBO); //设置了VBO
   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//设置VBO中的数据
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); //设置顶点属性(索引为0的属性,与shader中的内容有交互)
    glEnableVertexAttribArray(0); //设置开启顶点属性(索引为0的属性,与shader中的内容有交互)
glBindVertexArray(0); //解绑VAO(解绑主要是为了不影响后续VAO的设置,有点类似于C++中指针delete后置空,是个好习惯)

通过上面的代码就完成了对VAO的设置,当我们需要绘制的时候,使用的代码类似于:

场景绘制:
glUseProgram(shaderProgram); glBindVertexArray(VAO); //(再次使用)绑定我们需要的VAO,会导致上面所有VAO保存的设置自动设置完成 someOpenGLFunctionThatDrawsOurTriangle(); glBindVertexArray(0); //解绑VAO

此外,注意不同Opengl版本的API的变化