OpenGl中的VAO、VBO与EBO

2023-10-27 17:50
文章标签 opengl vao vbo ebo

本文主要是介绍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// 绑定 VBOglBindBuffer(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。。。

参考来自:

  • 这个
  • 这个
  • 还有这个

这篇关于OpenGl中的VAO、VBO与EBO的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/287332

相关文章

OPENGL顶点数组, glDrawArrays,glDrawElements

顶点数组, glDrawArrays,glDrawElements  前两天接触OpenGL ES的时候发现里面没有了熟悉的glBegin(), glEnd(),glVertex3f()函数,取而代之的是glDrawArrays()。有问题问google,终于找到答案:因为OpenGL ES是针对嵌入式设备这些对性能要求比较高的平台,因此把很多影响性能的函数都去掉了,上述的几个函数都被移除了。接

OpenGL ES学习总结:基础知识简介

什么是OpenGL ES? OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库。 为桌面版本OpenGL 的一个子集。 OpenGL ES管道(Pipeline) OpenGL ES 1.x 的工序是固定的,称为Fix-Function Pipeline,可以想象一个带有很多控制开关的机器,尽管加工

OpenGL雾(fog)

使用fog步骤: 1. enable. glEnable(GL_FOG); // 使用雾气 2. 设置雾气颜色。glFogfv(GL_FOG_COLOR, fogColor); 3. 设置雾气的模式. glFogi(GL_FOG_MODE, GL_EXP); // 还可以选择GL_EXP2或GL_LINEAR 4. 设置雾的密度. glFogf(GL_FOG_DENSITY, 0

opengl纹理操作

我们在前一课中,学习了简单的像素操作,这意味着我们可以使用各种各样的BMP文件来丰富程序的显示效果,于是我们的OpenGL图形程序也不再像以前总是只显示几个多边形那样单调了。——但是这还不够。虽然我们可以将像素数据按照矩形进行缩小和放大,但是还不足以满足我们的要求。例如要将一幅世界地图绘制到一个球体表面,只使用glPixelZoom这样的函数来进行缩放显然是不够的。OpenGL纹理映射功能支持将

OpenGL ES 2.0渲染管线

http://codingnow.cn/opengles/1504.html Opengl es 2.0实现了可编程的图形管线,比起1.x的固定管线要复杂和灵活很多,由两部分规范组成:Opengl es 2.0 API规范和Opengl es着色语言规范。下图是Opengl es 2.0渲染管线,阴影部分是opengl es 2.0的可编程阶段。   1. 顶点着色器(Vert

OpenGL/GLUT实践:流体模拟——数值解法求解Navier-Stokes方程模拟二维流体(电子科技大学信软图形与动画Ⅱ实验)

源码见GitHub:A-UESTCer-s-Code 文章目录 1 实现效果2 实现过程2.1 流体模拟实现2.1.1 网格结构2.1.2 数据结构2.1.3 程序结构1) 更新速度场2) 更新密度值 2.1.4 实现效果 2.2 颜色设置2.2.1 颜色绘制2.2.2 颜色交互2.2.3 实现效果 2.3 障碍设置2.3.1 障碍定义2.3.2 障碍边界条件判定2.3.3 障碍实现2.3.

OpenGL——着色器画一个点

一、 绘制 在窗口中间画一个像素点: #include <GL/glew.h>#include <GLFW/glfw3.h>#include <iostream>using namespace std;#define numVAOs 1GLuint renderingProgram;GLuint vao[numVAOs];GLuintcreateShaderProgram (){c

试用GLFW并创建OpenGL和DX的环境

介绍GLFW GLFW官网:https://www.glfw.org/ GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan development on the desktop. It provides a simple API for creating windows, contex

鸿蒙(API 12 Beta6版)图形加速【OpenGL ES平台内插模式】超帧功能开发

超帧内插模式是利用相邻两个真实渲染帧进行超帧计算生成中间的预测帧,即利用第N-1帧和第N帧真实渲染帧预测第N-0.5帧预测帧,如下图所示。由于中间预测帧的像素点通常能在前后两帧中找到对应位置,因此内插模式的预测帧效果较外插模式更优。由于第N帧真实渲染帧需要等待第N-0.5帧预测帧生成并送显后才能最终送显,因此会新增1~2帧的响应时延。 OpenGL ES平台 业务流程 基于OpenGL

OpenGL DMA接口

Opengl的DMA版本接口主要作用是解决以前访问opengl对象, 必须先将对象绑定到当前状态机下才能访问的问题,这会导致驱动层需要去频繁的进行对象的引用查找。  比如以前非DMA版本的接口操作顶点数据  glGenBuffers(1, &vbo);glBindBuffer(GL_ARRAY_BUFFER, vbo);glBufferData(GL_ARRAY_BUFFER, sizeof