当前位置: 首页 > news >正文

初识OpenGL (-)EBO元素缓冲对象(Element Buffer Object)

1. EBO元素缓冲对象(Element Buffer Object)

EBO是一个缓冲区,就像一个顶点缓冲区对象一样,它存储 OpenGL 用来决定要绘制哪些顶点的索引。

1.1 索引绘制(Indexed Drawing)

索引缓冲对象(Index Buffer Object,IBO)

eg. 假设我们不再绘制一个三角形而是绘制一个矩形。我们可以绘制两个三角形来组成一个矩形(OpenGL主要处理三角形)。

//顶点数据一致,导致浪费
float 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,  // 右下角
    -0.5f, -0.5f, 0.0f, // 左下角
    -0.5f, 0.5f, 0.0f   // 左上角
};

->

float vertices[] = {
    // 注意索引从0开始! 
    0.5f, 0.5f, 0.0f,   // 右上角
    0.5f, -0.5f, 0.0f,  // 右下角
    -0.5f, -0.5f, 0.0f, // 左下角
    -0.5f, 0.5f, 0.0f   // 左上角
};

step1. 创建元素缓冲对象:

unsigned int EBO;
glGenBuffers(1, &EBO);

step2. 绑定EBO,用glBufferData把索引复制到缓冲里。同样,和VBO类似,我们会把这些函数调用放在绑定和解绑函数调用之间,缓冲的类型为GL_ELEMENT_ARRAY_BUFFER。

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
注意:我们传递了GL_ELEMENT_ARRAY_BUFFER当作缓冲目标。

step3. 用glDrawElements来替换glDrawArrays函数,表示我们要从索引缓冲区渲染三角形。

使用当前绑定的索引缓冲对象中的索引进行绘制:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

参数一: 指定绘制模式
参数二: 绘制顶点的个数,这里填6,也就是说我们一共需要绘制6个顶点。
参数三: 索引的类型,这里是GL_UNSIGNED_INT。
参数四: 指定EBO中的偏移量(或者传递一个索引数组,当不在使用索引缓冲对象的时候),但是我们会在这里填写0。

glDrawElements函数从当前绑定到GL_ELEMENT_ARRAY_BUFFER目标的EBO中获取其索引。这意味着我们每次想要使用索引渲染对象时都必须绑定相应的EBO,这又有点麻烦。碰巧顶点数组对象也跟踪元素缓冲区对象绑定。在绑定VAO时,绑定的最后一个元素缓冲区对象存储为VAO的元素缓冲区对象。然后,绑定到VAO也会自动绑定该EBO。

当目标是GL_ELEMENT_ARRAY_BUFFER的时候,VAO会储存glBindBuffer的函数调用。这也意味着它也会储存解绑调用,所以确保没有在解绑VAO之前解绑索引数组缓冲,否则它就没有这个EBO配置了。

step5. 代码

// ..:: 初始化代码 :: ..
// 1. 绑定顶点数组对象
glBindVertexArray(VAO);
// 2. 把我们的顶点数组复制到一个顶点缓冲中,供OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 3. 复制我们的索引数组到一个索引缓冲中,供OpenGL使用
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 4. 设定顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

[...]

// ..:: 绘制代码(渲染循环中) :: ..
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
运行程序会获得下面这样的图片的结果。左侧图片看应该起来很熟悉,而右侧的则是使用线框模式(Wireframe Mode)绘制的。
线框矩形可以显示出矩形的确是由两个三角形组成的。

线框模式(Wireframe Mode)

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)函数配置OpenGL如何绘制图元。
参数一: 表示打算将其应用到所有的三角形的正面和背面
参数二:用线来绘制。

之后的绘制调用会一直以线框模式绘制三角形,直到我们用glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)将其设置回默认模式。

相关文章:

  • typescript真的有学习的必要吗?
  • PyTorch Lightning入门教程(二)
  • 【滤波跟踪】基于变分贝叶斯卡尔曼滤波器实现目标跟踪附matlab代码
  • C++ mutex 与 condition_variable
  • 基础 | Spring - [单例创建过程]
  • K8S集群Pod资源自动扩缩容方案
  • SPPNet
  • java多线程-多线程技能
  • 网课查题接口 该怎么搭建
  • Elasticsearch学习-- 聚合查询
  • 网课搜题公众号接口
  • ubuntu18.04.1LTS 编译安装ffmpeg详解
  • 接口幂等问题:redis分布式锁解决方案
  • 算法与数据结构(第一周)——线性查找法
  • 修改docker 修改容器配置
  • [ JavaScript ] 数据结构与算法 —— 链表
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • react 代码优化(一) ——事件处理
  • Solarized Scheme
  • Vue 动态创建 component
  • Vue2.0 实现互斥
  • web标准化(下)
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 我与Jetbrains的这些年
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • hi-nginx-1.3.4编译安装
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • #数学建模# 线性规划问题的Matlab求解
  • (2)STM32单片机上位机
  • (30)数组元素和与数字和的绝对差
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (十一)图像的罗伯特梯度锐化
  • .NET Core WebAPI中封装Swagger配置
  • .NET企业级应用架构设计系列之技术选型
  • .NET序列化 serializable,反序列化
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • @Documented注解的作用
  • @Query中countQuery的介绍
  • @Transient注解
  • @zabbix数据库历史与趋势数据占用优化(mysql存储查询)
  • [ CTF ] WriteUp-2022年春秋杯网络安全联赛-冬季赛
  • [ vulhub漏洞复现篇 ] Apache Flink目录遍历(CVE-2020-17519)
  • [android] 请求码和结果码的作用
  • [BZOJ3223]文艺平衡树
  • [CQOI 2010]扑克牌
  • [CTO札记]如何测试用户接受度?
  • [delphi]保证程序只运行一个实例
  • [iOS]-网络请求总结
  • [Oh My C++ Diary]结构体变量的声明
  • [RK-Linux] RK3399支持M.2 NVMe SSD启动