OpenGL系列(三)VBO、VAO

    在OpenGL系列(一)三角形 用到了VBO和VAO,本文对两者进行介绍。

    通过OpenGL的API绘制图形时,需要先定义顶点,如示例中三角形的顶点数组定义如下。

float vertices[] = {// 位置信息         // 颜色信息0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,  // 右下-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,  // 左下0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f   // 顶部};

上面定义的数组存放在内存中,可以被CPU访问,但是GPU访问不了,绘制图形是由GPU执行的,为了能让GPU访问到顶点数据,需要把它们从内存传递到显存中。通过glVertexAtrribPointer可以将数据从传递给GPU,示例如下。

static void
draw(void)
{static const GLfloat verts[3][2] = {{ -1, -1 },{  1, -1 },{  0,  1 }};static const GLfloat colors[3][3] = {{ 1, 0, 0 },{ 0, 1, 0 },{ 0, 0, 1 }};GLfloat mat[16], rot[16], scale[16];/* Set modelview/projection matrix */make_z_rot_matrix(view_rotx, rot);make_scale_matrix(0.5, 0.5, 0.5, scale);mul_matrix(mat, rot, scale);glUniformMatrix4fv(u_matrix, 1, GL_FALSE, mat);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);{glVertexAttribPointer(attr_pos, 2, GL_FLOAT, GL_FALSE, 0, verts);glVertexAttribPointer(attr_color, 3, GL_FLOAT, GL_FALSE, 0, colors);glEnableVertexAttribArray(attr_pos);glEnableVertexAttribArray(attr_color);glDrawArrays(GL_TRIANGLES, 0, 3);glDisableVertexAttribArray(attr_pos);glDisableVertexAttribArray(attr_color);}
}

    以上也是绘制三角形的过程,在绘制之前定义顶点数组verts和颜色数组colors,在调用glDrawArrays绘制之前先通过glVertexAttribPointer将数组传给GPU,最后一个参数是数组的地址。

    这里涉及一个问题,将数据传递到GPU是一个耗时的过程,每次绘制之前都执行数据的传递操作势必会影响整体性能,为了解决这个问题,引入了VBO,VBO是Vertex Buffer Object(顶点缓冲对象)的缩写,用于表示显存中的一个缓冲,该缓冲的数据可以被GPU访问,只要把数据存放到该缓冲中,就不必每次绘制前都执行传递数据的操作了。

    创建VBO并传递数据的流程如下。

    float vertices[] = {// 位置信息         // 颜色信息0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,  // 右下-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,  // 左下0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f   // 顶部};glGenBuffers(1, &VBO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

VBO的使用流程解析如下:

  1. glGenBuffers创建VBO对象,第一个参数表示创建VBO的数量,第二个参数返回创建成功后的VBO的的句柄
  2. glBindBuffer绑定缓冲对象,把VBO绑定到目标GL_ARRAY_BUFFER后,后续对目标GL_ARRAY_BUFFER的操作相当于对被绑定的VBO进行操作
  3. glBufferData把数据载入VBO中,在这一步VBO才开始分配空间来保存顶点数据

    通过创建VBO来保存数据后,数据的传递问题解决了,接下来是GPU如何解析这些数据的问题,GPU需要知道一个顶点包含多少个属性,每个属性的数据类型,大小,偏移等信息,这些需要依赖VAO来解决。

    VAO是Vertex Array Object(顶点数组对象)的缩写,用法流程如下。

glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

VAO的使用流程解析如下:

  1. glGenVertexArrays:创建VAO对象,同样第一个参数表示数量,第二个参数是VAO的句柄
  2. glBindVertexArray:绑定VAO对象,经过绑定后,后续的操作都是针对该VAO。
  3. glEnableVertexAttribArray,启用属性,参数表示编号,0表示第0个属性。
  4. glVertexAttribPointer,把顶点属性设置到VAO中,调用该方法前需要先绑定VBO和VAO,不同的属性可以对应不同的VBO。第一个参数表示属性的编号,如0表示第0号属性,第二个参数表示大小,第三个参数表示类型,第四个参数表示归一化,第五个参数表示步长,也就是两个顶点的起始地址的间隔。第六个表示偏移。

可以把多个属性存放到一个VBO,也可以存放到不同的VBO中。如果存放到同一个VBO中,那么每个顶点的偏移就不一样;如果存放到不同的VBO中,偏移可以都为0。在调用glEnableVertexAttribArray和glVertexAttribPointer之前先调用glBindBuffer可以绑定不同的VBO。

    VBO和VAO都准备好了以后,在准备好着色器的条件下,可以开始绘制,绘制只需绑定VAO即可,代码如下。

void Triangle::onDraw() {if(mShader == nullptr || !mShader->useProgram()) return;glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glClearColor(0.5f,0.6f,0.7f,1.0f);glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 3);glFlush();mShader->unuseProgram();
}

从上面的绘制流程可以看除,调用glDrawArrays绘制之前,只需调用glBindVertexArray绑定VAO即可,无须再传递顶点数据,从而提供了效率。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端 html格式转md格式插件使用介绍

1.html-to-markdown npm install html-to-markdown 不支持vue32.Marked npm install marked 不支持table转换 官网 https://marked.js.org/3.html-to-md npm i html-to-md import html2md from html-to-md console.log(html2md(<strong><em>strong and italic…

RabbitMQ学习笔记(一)RabbitMQ部署、5种队列模型

文章目录 1 认识MQ1.1 同步和异步通讯1.1.1 同步通讯1.1.2 异步通讯 1.2 技术对比 2 RabbitMQ入门2.1 RabbitMQ单机部署2.2 RabbitMQ基本结构2.3 RabbitMQ队列模型2.3.1 简单队列模型&#xff08;Simple Queue Model&#xff09;2.3.2 工作队列模型&#xff08;Work Queue Mode…

visual studio打包qt算子时,只生成dll没有生成lib等文件

问题&#xff1a;在visual studio配置了qt项目&#xff0c;并打包成dll&#xff0c;原则上会生成一堆文件&#xff0c;包括dll,lib等文件。 解决办法&#xff1a; 挨个右击源代码的所有头文件-》属性-》项类型。改成qt头文件形式&#xff0c;如下。

【JAVA】Java中MyBatis的QueryWrapper的使用

文章目录 前言一、函数解释二、代码实现三、总结 前言 在Java开发中&#xff0c;我们常常需要使用ORM框架来简化数据库操作。MyBatis是一个流行的ORM框架&#xff0c;而MyBatis-Plus是它的一个增强版&#xff0c;提供了更多的便利功能。在这篇博客中&#xff0c;我们将探讨如何…

事务详讲(本地及分布式)

本地事务在分布式的问题: 因为在分布式服务中,难免一个接口中会有很多调用远程服务的情况,这个就非常容易出现问题,以下是一个详细的例子: 例如,你为了保证事物的一致性等要求,所以,你方法上只写了Transactional,但你的业务中又需要调用其他微服务的方法(Feign),这时就容易出现…

XML读写

XML初识 一、背景 自己写的从网页获取内容的小工具&#xff0c;那个网页是涉及到一个模拟器的启动。启动模拟器需要等五分钟才能读取数据。如果每次读都启动模拟器等待&#xff0c;等待时间较久&#xff0c;我在想应该在硬盘中将已经启动过模拟器的标志位写到xml文件中。所以…

【机器学习】Qwen1.5-14B-Chat大模型训练与推理实战

目录 一、引言 二、模型简介 2.1 Qwen1.5 模型概述 2.2 Qwen1.5 模型架构 三、训练与推理 3.1 Qwen1.5 模型训练 3.2 Qwen1.5 模型推理 四、总结 一、引言 Qwen是阿里巴巴集团Qwen团队的大语言模型和多模态大模型系列。现在&#xff0c;大语言模型已升级到Qwen1.5&…

使用 Scapy 库编写 ICMP 重定向攻击脚本

一、介绍 ICMP重定向攻击&#xff08;ICMP Redirect Attack&#xff09;是一种网络攻击&#xff0c;攻击者通过发送伪造的ICMP重定向消息&#xff0c;诱使目标主机更新其路由表&#xff0c;以便将数据包发送到攻击者控制的路由器或其他不可信任的设备上。该攻击利用了ICMP协议…

springboot配置集成RedisTemplate和Redisson,使用分布式锁案例

文章要点 自定义配置属性类集成配置RedisTemplate集成配置分布式锁Redisson使用分布式锁简单实现超卖方案 1. 项目结构 2. 集成RedisTemplate和Redisson 添加依赖 依赖的版本与继承的spring-boot-starter-parent工程相对应&#xff0c;可写可不写 <!--spring data redis…

Spring boot 集成mybatis-plus

Spring boot 集成mybatis-plus 背景 Spring boot集成mybatis后&#xff0c;我们可以使用mybatis来操作数据。然后&#xff0c;我们还是需要写许多重复的代码和sql语句&#xff0c;比如增删改查。这时候&#xff0c;我们就可以使用 mybatis-plus了&#xff0c;它可以极大解放我…

沐风老师3DMAX顶点切线控制插件VertexTangants安装使用方法

3DMAX顶点切线控制插件VertexTangants安装使用方法 3DMAX顶点切线控制插件VertexTangants&#xff0c;用于轻松控制图形顶点切线的工具。 【主要功能】 -脚本具有获取选定顶点的自动检测功能&#xff0c;您可以随时使用“获取按钮”获取选定顶点。 -有一个用于激活撤消的ON按…

项目资源管理

目录 1.概述 2.六个过程 2.1. 规划资源管理 2.2. 估算活动资源 2.3. 获取资源 2.4. 建设团队 2.5. 管理团队 2.6. 控制资源 3.应用场景 3.1.十个应用场景 3.2.软件开发项目 3.2.1. 资源规划 3.2.2. 资源分配 3.2.3. 资源获取 3.2.4. 资源优化 3.2.5. 资源监控与…

如何在外网http访问内网邮件server?

不少公司选择用winmail搭建部署内部邮箱服务器&#xff0c;对于邮件管理员&#xff0c;不但需要在局域网内&#xff0c;常常需要在外网也能访问到邮箱服务管理。winmail本身系统功能可以开启http访问管理&#xff0c;但当需要在外网http访问内网邮箱服务时&#xff0c;需要用到…

vue3通过Vite实现工程化

1. vue3简介 Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。无论是简单还是复杂的界面&#xff0c;Vue 都可以胜任。官网为:Vue.js - 渐进…

在python中连接了数据库后想要在python中通过图形化界面显示数据库的查询结果,请问怎么实现比较好? /ttk库的treeview的使用

在Python中&#xff0c;你可以使用图形用户界面&#xff08;GUI&#xff09;库来显示数据库的查询结果。常见的GUI库包括Tkinter&#xff08;Python自带&#xff09;、PyQt、wxPython等。以下是一个使用Tkinter库来显示数据库查询结果的简单示例。 首先&#xff0c;你需要确保…

Web学习篇(二)

命令执行漏洞 一、常用的函数 1、eval() 例: eval(string $code) 把字符串code作为PHP代码执行 2、assert() assert( mixed $assertion [, string $description ]) 检查一个断言是否为 FALSE,如果 assertion 是字符串,它将会被 assert()当做 PHP 代码来执行。 3、p…

秋招突击——算法打卡——6/3——复习{最低通行费、(状态压缩DP)小国王}——新做:{罗马数字转整数、最长公共前缀}

文章目录 复习背包模型——最低通行费题目内容实现代码 &#xff08;状态压缩DP&#xff09;小国王检查状态本身是否存在两个连续的1计算所有的合法状态已经所有合法状态之间的转移动态规划过程 新作罗马数字转整数个人实现实现代码 参考做法实现代码 最长公共前缀个人实现参考…

【车载开发系列】删除DTC操作步骤(VacanoVSB实现)

【车载开发系列】删除DTC操作步骤(VacanoVSB实现) 【车载开发系列】删除DTC操作步骤(VacanoVSB实现) 【车载开发系列】删除DTC操作步骤(VacanoVSB实现)Step1:Internal Behavior Editor对应Step2:CSWC删除1)删除InnerView関数12)删除InnerView関数23)删除InnerView関…

Docker无法stop或者rm指定容器

Docker无法stop或者rm指定容器 今日准备重启一下docker 容器部署的 Nginx 时&#xff0c;使用的命令是 docker exec -it ir-nginx nginx -s reload 结果发现无法重启报错 然后想着关闭再启动&#xff0c;结果发现 docker restart 、docker stop 、docker kill 、docker exec 都…

【科学文献计量】使用Endnote软件打开中国知网导出的文献期刊解析不正确问题解决

使用Endnote软件打开中国知网导出的文献期刊解析不正确问题解决 问题解决问题 新建一个Endnote的材料库,然后把下载好的中国知网文献数据(知网数据导出的是Endnote格式样式)导入进来。找到文件所在路径,导入的类型选择是“Endnote import”,然后点击确定,界面结果如下 …