OpenGl中的VAO、VBO与EBO

文章目录

  • VBO(顶点缓冲区对象)
    • VBO的使用
  • EBO(索引缓冲对象)
    • EBO的使用
  • VAO(顶点数组对象)
    • VAO的使用
  • 三者的区别
  • someting。。。

哎,很离谱,上个月学learnopengl学到一半跑去看庄懂老师的视频,结果该还的东西迟早得还,再打开之前的工程有些东西已经记不清楚了,特别是VAO、VBO与EBO这三个东西,之前就总是分不清,这里再做个笔记,以后要是忘了就再回来翻翻好了。

VBO(顶点缓冲区对象)

VAO(Vertex Buffer Object),为顶点缓冲区对象,是显卡存储空间里的一块缓存区(Buffer),用于存储 顶点坐标 / 顶点uv / 顶点法线 / 顶点颜色等数据信息。

  • 在 OpenGL 开发中,用于绘制的顶点数据首先是存储在 CPU 内存中的。
  • 而在调用 glDrawArrays 或者 glDrawElements 等接口进行绘制时,OpenGL 需要将顶点数组数据从 CPU 内存拷贝到 GPU 显存。
  • 所以如果我们的程序里需要多次绘制,那就会触发多次内存拷贝从而带来一些性能消耗。

那怎么解决?

  • 如果我们可以在 GPU 显存中缓存这些顶点数据,就可以大幅减少 CPU 内存到 GPU 显存的数据拷贝的开销,这就是 VBO 和 EBO 出现的原因。
  • VBO 和 EBO 的作用是在 GPU 显存中开辟一块存储空间来缓存顶点数据或者图元索引数据,避免每次绘制时 CPU 内存到 GPU 显存的数据拷贝,从而提升渲染性能。

VBO的使用

// 顶点数据:
GLfloat vertices[] = {
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
};

// 使用 VBO:
GLuint VBO;
glGenBuffers(1, &VBO); // 创建 VBO 对象
glBindBuffer(GL_ARRAY_BUFFER, VBO); // 把新创建的 VBO 绑定到 GL_ARRAY_BUFFER 目标上,同时也绑定到了 OpenGL 渲染管线上
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 将顶点数据 (CPU 内存) 拷贝到 VBO(GPU 显存)

// 绘制:
glDrawArrays(GL_TRIANGLES, 0, 3); // 使用 glDrawArrays 来绘制

整个过程还是比较浅显易懂的:做了一次 CPU 到 GPU 的数据拷贝。


EBO(索引缓冲对象)

EBO(Element Buffer Object),和顶点缓冲对象一样,EBO也是一个缓冲,它专门储存索引,OpenGL调用这些顶点的索引来决定该绘制哪个顶点。

EBO的使用

// 这次我们只定义了 4 个顶点:
GLfloat vertices[] = {
     0.5f,  0.5f, 0.0f, // 右上角
     0.5f, -0.5f, 0.0f, // 右下角
    -0.5f, -0.5f, 0.0f, // 左下角
    -0.5f,  0.5f, 0.0f  // 左上角
};

// 但是通过索引指定了每个三角形的 3 个顶点:
GLuint indices[] = { // 注意索引从 0 开始! 
    0, 1, 3, // 第一个三角形
    1, 2, 3  // 第二个三角形
};

// 使用 VBO:
GLuint VBO;
glGenBuffers(1, &VBO); // 创建 VBO 对象
glBindBuffer(GL_ARRAY_BUFFER, VBO); // 把新创建的 VBO 绑定到 GL_ARRAY_BUFFER 目标上,同时也绑定到了 OpenGL 渲染管线上
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 将顶点数据 (CPU 内存) 拷贝到 VBO(GPU 显存)

// 使用 EBO:
GLuint EBO;
glGenBuffers(1, &EBO); // 创建 EBO 对象
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // 把新创建的 EBO 绑定到 GL_ELEMENT_ARRAY_BUFFER 目标上,同时也绑定到了 OpenGL 渲染管线上
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // 将所有顶点数据 (CPU 内存) 拷贝到 EBO(GPU 显存),并设定按照indices顺序来渲染

// 绘制:glDrawElements替换掉glDrawArrays函数,表示我们要从索引缓冲区渲染三角形
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // 使用 glDrawElements 来绘制
  • glDrawElements函数从当前绑定到GL_ELEMENT_ARRAY_BUFFER目标的EBO中获取其索引。
  • 整个过程比 VBO 略复杂了一点,但是还是很好理解的:去掉重复顶点,通过索引指定绘制顶点,创建 VBO 做一次顶点数据拷贝,创建 EBO 做了一次索引数据拷贝。

VAO(顶点数组对象)

VAO(Vertex Array Object),VAO是所有顶点数据的状态集合。它存储了顶点数据的格式以及顶点数据所需的缓存对象的引用,任何随后的顶性调用都会储存在这个VAO中。

  • 通过对 VBO、EBO 的使用,我们可以减少 CPU 到 GPU 内存拷贝来提高性能。
  • 但是如果我们需要绘制大量的顶点和物体时,每次绘制都需要绑定正确的缓冲对象并为每个物体配置所有顶点属性,这样一大堆操作很是麻烦。
  • 是否可以用一种对象来储存这些状态配置,使得我们需要的时候直接绑定这个对象就可以切换到正确的状态呢?这就是 VAO 要解决的问题。
  • 如果说 VBO、EBO 是通过 GPU 显存的缓存来减少内存拷贝从而提升性能,那么 VAO 则略有不同:VAO 的主要作用是用于管理 VBO 或 EBO,减少 glBindBuffer、glEnableVertexAttribArray、glVertexAttribPointer 这些调用操作,高效地实现在顶点数组配置之间切换。

VAO的使用

// 顶点数据:
GLfloat vertices[] = {
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
};

// 创建 VBO:
GLuint VBO;
glGenBuffers(1, &VBO); // 创建 VBO 对象

// 创建 VAO:
GLuint VAO;
glGenVertexArrays(1, &VAO); // 创建 VAO 对象,注意这里用的是 glGenVertexArrays

// 在绑定 VAO 后操作 VBO,当前 VAO 会记录 VBO 的操作,我们下面用缩进表示操作 VBO 的代码:
glBindVertexArray(VAO); // 绑定 VAO,注意这里用的是 glBindVertexArray
    // 绑定 VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    // 把顶点数组复制到缓冲中供 OpenGL 使用
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 
    // 设置顶点属性指针
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid *) 0);
    glEnableVertexAttribArray(0);
// 解绑 VAO
glBindVertexArray(0);

// ...省略其他代码...

// 会被调用多次的绘制代码:
glBindVertexArray(VAO); // 绑定使用 VAO 绘制
glDrawArrays(GL_TRIANGLES, 0, 3); // 使用 glDrawArrays 来绘制
glBindVertexArray(0); // 解绑 VAO

上面的代码相比我们用 VBO 绘制三角形的代码还是复杂一些的,上面的代码可以理解为:使用 VAO 记录 VBO 的操作相当于创建了一个快捷方式,后面直接用 VAO 快捷方式绘制。


三者的区别

  • VAO中存储着VBO的信息和EBO的信息。
  • VBO和EBO存储的都是顶点的信息。
  • 一个VAO对应一个物体
  • 一个VBO对应一个物品的所有属性(顶点坐标、颜色等,除顶点索引外)。
  • 一个EBO仅对应一个物品的一种属性(顶点索引属性)。

在这里插入图片描述

someting。。。

参考来自:

  • 这个
  • 这个
  • 还有这个

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/47190.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序使用ECharts的示例详解

目录 安装 ECharts 组件使用 ECharts 组件图表延迟加载 echarts-for-weixin 是 ECharts 官方维护的一个开源项目,提供了一个微信小程序组件(Component),我们可以通过这个组件在微信小程序中使用 ECharts 绘制图表。 echarts-fo…

蓝桥杯专题-真题版含答案-【贪吃蛇长度】【油漆面积】【绘制圆】【高次方数的尾数】

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 👉关于作者 专注于Android/Unity和各种游…

Ansible 自动化运维

目录 ansible 环境安装部署ansible 命令行模块inventory 主机清单 Ansible是一个基于Python开发的配置管理和应用部署工具,现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点,Pubbet和Saltstack能实现的功能,Ansible基本上都可…

Wireshark抓包分析教程(ubuntu版本)

安装 first,多亏我们的C知道,成功安装了wireshark, Steps are as following: 添加wireshark的软件源(PPA:personal package archive(档案)) sudo apt-add-repository ppa:wireshark-dev/stable ppa:wireshark-dev/stable 是一个…

PHP数组转对象和对象转数组

PHP数组转对象和对象转数组 <?php function array_to_object($arr){$obj new stdClass();foreach ($arr as $key > $val) {if (is_array($val) || is_object($val)) {$obj->$key array_to_object($val);} else {$obj->$key $val;}}return $obj; } function o…

Kyuubi入门简介

一、官方简介 HOME — Apache Kyuubi 二、概述 1、一个企业级数据湖探索平台 2、一个高性能的通用JDBC和SQL执行引擎 3、一个基于spark的查询引擎服务 三、优点 1、提供hiveserver2查询spark sql的能力&#xff0c;查询效率更为高效&#xff0c;首次构建连接时会持续保持连…

洛必达法则和分部积分的应用之计算数学期望EX--概率论浙大版填坑记

如下图所示&#xff0c;概率论与数理统计浙大第四版有如下例题&#xff1a; 简单说就是&#xff1a;已知两个相互独立工作电子装置寿命的概率密度函数&#xff0c;将二者串联成整机&#xff0c;求整机寿命的数学期望。 这个题目解答中的微积分部分可谓是相当的坑爹&#xff0c;…

DDL\DML

查询字段 1、查询指定字段 select 字段1, 字段2 ,...] from 表名; select ename, sal from emp; select ename from emp; 2、查询全部字段 select * from 表名; select * from emp; 条件查询 使用 where 语句&#xff0c;放在 from 后 select * from emp where 条件…

PostgreSQL 的事务管理和并发控制机制解析

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

Prompt Engineering论文梳理(主要为2022年)

AutoPrompt &#xff08;EMNLP2020&#xff09; Shin T, Razeghi Y, Logan IV R L, et al. Autoprompt: Eliciting knowledge from language models with automatically generated prompts[J]. arXiv preprint arXiv:2010.15980, 2020. 基本架构&#xff0c;original input t…

关联分析-Apriori

关联分析-Apriori 1. 定义 关联分析就是从大规模数据中&#xff0c;发现对象之间隐含关系与规律的过程&#xff0c;也称为关联规则学习。 2. 相关概念 2.1 事务、项与项集 订单号购买商品0001可乐、薯片0002口香糖、可乐0003可乐、口香糖、薯片 以上面的订单为例&#xf…

elasticsearch使用记录

参考文章&#xff1a;https://elasticsearch-py.readthedocs.io/en/v8.8.2/ 参考文章&#xff1a;https://cuiqingcai.com/6214.html 参考文章&#xff1a;https://www.cnblogs.com/cupleo/p/13953890.html elasticsearch版本&#xff1a;8.8.2(软件包发行版) python版本&#…

MySQL 读写分离

目录 一、什么是读写分离&#xff1f; 二、为什么要读写分离呢&#xff1f; 三、什么时候要读写分离&#xff1f; 四、主从复制与读写分离 五、MySQL 读写分离原理 六、企业 使用MySQL 读写分离场景 1&#xff09;基于程序代码内部实现 2&#xff09;基于中间代理层实现…

React重新渲染的触发机制及其优化策略

React是一个用于构建用户界面的JavaScript库&#xff0c;它的核心特点之一是使用虚拟DOM&#xff08;Virtual DOM&#xff09;来实现高效的组件渲染。那组件重新渲染的机制是如何呢&#xff1f;基于这些机制&#xff0c;如果进行优化呢&#xff1f; 虚拟DOM是一个用JavaScript对…

"科技与狠活"企业级无代码开发MES系统,一周实现数字化

随着科技的不断发展&#xff0c;企业级无代码开发平台成为了一种新型的解决方案&#xff0c;能够有效降低软件开发门槛&#xff0c;提升开发效率。在制造业领域&#xff0c;MES系统&#xff08;Manufacturing Execution System&#xff09;作为一种关键的生产管理工具&#xff…

C# 全局响应Ctrl+Alt+鼠标右键

一、简述 某些应用&#xff0c;我们希望全局自定义热键。按键少了会和别的应用程序冲突&#xff0c;按键多了可定用户操作不变。因此我计划左手用CtrlAlt&#xff0c;右手用鼠标右键呼出我自定义的菜单。 我使用键盘和鼠标事件进行简单测试&#xff08;Ctrl鼠标右键&#xff…

[SQL系列] 从头开始学PostgreSQL 自增 权限和时间

[SQL系列] 从头开始学PostgreSQL 事务 锁 子查询_Edward.W的博客-CSDN博客https://blog.csdn.net/u013379032/article/details/131841058上一篇介绍了事务&#xff0c;锁&#xff0c;子查询 事务有点像是原子操作&#xff0c;需要有完整性&#xff0c;要么全都完成了&#xff…

2023年深圳杯数学建模A题影响城市居民身体健康的因素分析

2023年深圳杯数学建模 A题 影响城市居民身体健康的因素分析 原题再现&#xff1a; 以心脑血管疾病、糖尿病、恶性肿瘤以及慢性阻塞性肺病为代表的慢性非传染性疾病&#xff08;以下简称慢性病&#xff09;已经成为影响我国居民身体健康的重要问题。随着人们生活方式的改变&am…

flutter开发实战-RepaintBoundary实现Widget截图功能

flutter开发实战-RepaintBoundary实现Widget截图功能 在开发中&#xff0c;遇到需要使用截图&#xff0c;像iOS可以截图UIView获取到UIImage&#xff0c;在flutter中可以使用RepaintBoundary实现截图功能 相机拍摄的图片&#xff1a; RepaintBoundary截图后的图片 一、Re…

Docker 全栈体系(七)

Docker 体系&#xff08;高级篇&#xff09; 五、Docker-compose容器编排 1. 是什么 Compose 是 Docker 公司推出的一个工具软件&#xff0c;可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml&#xff0c;写好多个容器之间的调…