OpenGL Vertex Buffer Objects(VBOs)

2023-11-17

分类:  OpenGL2010-05-20 12:53  3714人阅读  评论(13)  收藏  举报

*原创文章转载请注明出处*

 

OpenGL Vertex Buffer Objects(VBOs)

 

Vertex Buffer Objects(VBOs)是一组保存在显存中的数据,这些数据可以是顶点,顶点颜色,顶点法线,顶点索引或贴图坐标等等。由于这些数据都是保存在显存中的,而且可以随时修改数据或整块替换数据,这样就极大的提高了显卡的工作效率和渲染的速度。VBO的概念类似于D3D中的顶点缓冲和索引缓冲的概念。这篇文章将通过实际的例子来说明在openGL中如何使用VBOs,并且和使用传统的glVertex()函数定义顶点和使用glCallList()函数进行比较。

 

现在要渲染一个模型,首先定义该模型的顶点数组。

 

struct myVertex

{

      GLfloat x,y,z;      // vertex

      GLfloat nx,ny,nz;   // noraml

};

 

这里定义了一个结构体数据,包括顶点和法线,它们都是浮点型的,所以该结构体一共占用4*6=24字节的空间。有了顶点结构体后,为了提供顶点间连接的信息,我们还需要定义索引数组。

 

myVertex *vertexData;

GLuint *indexData;

 

这里使用无符号的整型定义了一个定点数组的指针,myVertex *vertexData是用我们定义的顶点结构体定义了一个顶点数据指针。在使用VBO之前,我们先将数据初始化到顶点数组和索引数组中。假设现在顶点数据和索引数组都有数据,现在就可以使用VBO了。使用VBO和使用其他openGL的一些对象差不多,使用前都要先申请和创建。使用VBO也要先创建对象。

 

GLuint BufferName[2];

glGenBuffers(2, BufferName);

 

为了将顶点数据和索引数据能放到对应的缓存中,这里定义了一个保存两个缓存id的BufferName数组。然后使用glGenBuffers()函数申请2个缓存id。申请到id后立即为要使用的缓存分配空间和初始化。

 

glBindBuffer(GL_ARRAY_BUFFERBufferName[0]);

glBufferData(GL_ARRAY_BUFFERvertexSizevertexDataGL_STATIC_DRAW);

 

glVertexPointer(3, GL_FLOAT,24,0);

glNormalPointer(GL_FLOAT, 24, (GLvoid*)12);

 

上面的代码中,glBindBuffer表示绑定一个要使用的buffer对象,该函数有2个参数,该函数的原型为

 

void glBindBuffer(GLenum target, GLuint buffer);

 

 

参数target表示buffer的类型,参数buffer表示id。第一个buffer里要保存顶点数据,所以指定为GL_ARRAY_BUFFER为即可。绑定完一个buffer对象后,然后让这个buffer关联到数据上。这里使用函数glBufferData该函数为绑定的buffer指定要放入的数据,它的原型为

 

void glBufferData(GLenum targetGLsizeiptr sizeconst GLvoiddataGLenumusage);

 

同样参数target表示使用的buffer的类型, size的类型是GLsizeiptr,该类型表示一个指向size的一个指针,在使用之前,先要求得放入buffer中数据的大小。

 

GLsizeiptr vertexSize = number_of_vertex sizeof(myVertex);

 

可以通过上面的代码简单的求出顶点数据共占用的显存空间。data表示要放到该buffer中的顶点数组的指针,usage表示用法,这里指定为GL_STATIC_DRAW表示该buffer只能修改一次,但可多次读取。

 

现在已经在顶点缓存中放入了顶点数据,但是显卡是不知道这些数据中哪些是顶点,哪些是法线等等。于是我们还要告诉显卡哪些数据是用来干什么的。同样openGL中提供了glVertexPointer和glNormalPointer分别来管理不同的数据。于是我们看了上面这样的代码。

 

glVertexPointer(3, GL_FLOAT,24,0);

glNormalPointer(GL_FLOAT, 24, (GLvoid*)12);

 

函数glVertexPointer中,第一个参数表示顶点的维数,比如2维,3维或4维。第二个参数表示顶点的类型,第三个参数表示每隔多少字节顶点数据开始重复,最后一个参数表示顶点开始位置的偏移。由于我们顶点每个是24字节,并且连续保存在显存中,于是每隔24字节就开始重复。函数glNormalPointer中,第一个参数表示法线的数据类型,第二参数还是表示每隔多少字节开始重复,最后一个参数表示法线开始位置的偏移量。由于在顶点数据中前12字节是顶点坐标,后12个字节才是法线,于是法线数据开发的偏移量就是12个字节。我们可以通过下面的图清楚的看到这些数据之间的关系。

 

 

Fig1 顶点数据在显存中的存储

 

顶点数据处理完后,接下来就是顶点索引数据了。和顶点数据一样,要使用索引缓存,也要先绑定索引到buffer中。

 

glBindBuffer(GL_ELEMENT_ARRAY_BUFFERBufferName[1]);

glBufferData(GL_ELEMENT_ARRAY_BUFFERindexSizeindexDataGL_STATIC_DRAW);

 

使用索引缓存的话,在glBindBuffer函数中,target就要选择GL_ELEMENT_ARRAY_BUFFER,然后绑定到第二个buffer。之后同样用函数glBufferData将索引数据放到buffer中。这里的indexSize也是Glsizeiptr类型。

 

GLsizeiptr indexSize = number_of_face*3*sizeof(GLuint);

 

上面的代码可以求出索引缓存的大小,由于mesh的一个三角形使用3个顶点索引,所以索引缓存的大小是三角形的个数乘以3再乘以索引数据类型所占的字节数。

有了所有这些数据后,最后在渲染的时候,我们就可以使用函数glDrawElements绘制对象了。

 

glEnableClientState(GL_VERTEX_ARRAY);

     

glDrawElements(GL_TRIANGLESnumber_of_face*3, GL_UNSIGNED_INT,  0);

 

glDisableClientState(GL_VERTEX_ARRAY);

 

绘制前开开启客户端处理功能。函数glDrawElements中,第一个参数表示索引那种图元来连接。第二个参数表示要渲染多少个这种图元,第三个参数表示索引的数据类型,最后一个参数表示开始索引开始位置的偏移量。

 

Fig2 渲染的模型

 

在Fig2中可以看到渲染的一个模型,该模型的顶点数为219483个,三角形数为435667个。要渲染这样一个顶点数有20万,三角形数有40万的模型来说,如果用传统的glVertex函数来设置顶点的话,渲染一帧的画面就要大约调用该函数3*40=120万次,如果要达到30FPS的话,那么每秒要调用函数大约3*40*30 =3600万次,这样多的函数调用次数相当耗时。

 

Fig3 各种渲染方法帧数对比

 

现在为了对比进行试验,试验用电脑配置采用Inter Core2 6600处理器,2G内存和NVIDIA GeForce8600GT显卡。 试验的结果可以从Fig3中看到,纵轴表示帧数。 实际试验中发现,使用glVertex函数渲染方法,平均只能达到1FPS,这远远低于实时渲染的要求。为了提高性能,也可以使用Display List,在openGL中可以使用glGenList,glNewList和glCallList函数,在同样环境下运行程序,渲染帧数有了明显改善,达到平均16FPS的水平,虽然和采用glVertex的方法比性能提高了16倍,但是仍然达不到实时渲染的要求。最后采用VBO的方法,在相同环境下运行程序,这次帧数到达了60FPS,约为采用Display List方法的4倍,完全可以达到实时渲染的要求。从试验中可以看到,采用VBO能够明显提高性能。

 

 

*原创文章转载请注明出处*

主题推荐
opengl buffer 高性能 处理器 对象
猜你在找
openGL CG 系列教程07 – Toon Shader
完成端口Iocp与Epoll的区别
LINK fatal error C1047 解决方法
linux互斥信号量pthread_mutex的两个问题
写程序的时候用什么字体
Direct2D向Dx11说"Hello"
API入门系列之三 -那迷惑人的Windows字符和字符指针类型
API入门系列之四 -相当简单的SDK程序
站在巨人的肩膀上开发游戏2 -- Orx入门引导及Hello World
多重采样MultiSample下的FBO反锯齿
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenGL Vertex Buffer Objects(VBOs) 的相关文章

  • _MM_TRANSPOSE4_PS 在 GCC 中导致编译器错误?

    我第一次在 GCC 而不是 MSVC 中编译我的数学库 并经历了所有的小错误 我遇到了一个根本没有意义的错误 Line 284 error lvalue required as left operand of assignment 284号
  • Opengl 视频纹理

    我正在使用 Visual Studio 10 在 Windows 上用 C 开发 opengl 应用程序 目前我在立方体上使用静态纹理 但我想集成视频纹理 你知道我可以使用哪个库来打开和解密视频吗 查看 ffmpeg libavformat
  • glm 中矩阵值的顺序不正确?

    我开始使用GLM http glm g truc net通过 OpenGL 3 和 GLSL 进行数学运算的库 我需要正交投影来绘制 2D 图形 所以我编写了这个简单的代码 glm mat4 projection 1 0 projectio
  • 如何计算正切和副法线?

    谈谈OpenGL着色语言 GLSL 中的凹凸贴图 镜面高光之类的东西 I have 顶点数组 例如 0 2 0 5 0 1 0 2 0 4 0 5 法线数组 例如 0 0 0 0 1 0 0 0 1 0 0 0 世界空间中点光源的位置 例如
  • 为什么我的 CAOpenGLLayer 更新速度比之前的 NSOpenGLView 慢?

    我有一个在 Mac OS X 上渲染 OpenGL 内容的应用程序 最初它渲染到 NSOpenGLView 然后我将其更改为渲染到 CAOpenGLLayer 子类 当我这样做时 我看到了巨大的性能损失 帧速率减半 鼠标响应能力降低 卡顿
  • 纹理采样:根据LOD值计算BIAS值

    GL ES 2 0 中的功能纹理2DLod在片段着色器中不可用 我需要移植 GLSL 着色器 在 GL ES 2 0 中我只能使用二维纹理 sampler2D 采样器 vec2 坐标 浮点数bias 告诉我如何计算 a 的值bias相当于已
  • 如何在多采样纹理上渲染帧缓冲区对象?

    我目前有一个使用多个通道的渲染引擎 其中图像的各个部分在纹理上渲染 然后使用着色器进行组合 它有效 现在我想激活多重采样 我在这里读到 http www opengl org wiki Framebuffer Object Examples
  • 带有 std::vector 的 VBO

    我用 C 和 OpenGL 编写了一个模型加载器 我用过std vectors 来存储我的顶点数据 但现在我想将其传递给glBufferData 但是数据类型却截然不同 我想知道是否有办法可以相互转换std vector至已记录的const
  • 使用 gl_FragColor 与 vec4 颜色?

    似乎有很多不明确的地方gl FragColor被弃用 例如 它缺失在GLSL 4 40 规范 https www khronos org registry OpenGL specs gl GLSLangSpec 4 40 pdf 但它包含在
  • OpenGL纹理渲染与原始不匹配

    我正在尝试使用 OpenGL 渲染纹理 我用作测试的纹理是白色背景上的一堆黑色矩形 如下所示 然而 在渲染时 纹理似乎被复制并叠加在其自身之上多次 我使用以下方法设置场景 std string vertexSource ShaderLoad
  • Shader的功能参数表现

    我试图了解如何在着色器语言中实现传递参数 我读过几篇文章和文档 但仍然有一些疑问 特别是我试图理解与C 函数调用 特别强调性能 之间略有差异HLSL Cg and GLSL但我猜下划线的实现非常相似 到目前为止我所理解的 除非另有说明 函数
  • 为贝塞尔曲线中的每个点绘制切线

    我设法绘制了一条贝塞尔曲线 如下所示 glColor3f 0 1 0 glBegin GL LINE STRIP for int i 3 i lt nPt i 3 glColor3f 0 0 0 for float k 0 k lt NLI
  • 之前对 GL.Color3 的调用使我的纹理使用了错误的颜色

    制作 2D OpenGL 游戏 渲染帧时 我需要首先绘制一些计算的四边形几何体 然后绘制一些纹理精灵 当我的渲染方法主体仅绘制精灵时 一切正常 但是 当我尝试在精灵之前绘制几何四边形时 精灵的纹理会更改为之前使用的最后一个 GL Color
  • OpenGL 缓冲区、glFlush 和 glutSwapBuffers()

    使用之间有什么区别吗 glutInitDisplayMode GLUT SINGLE GLUT RGB with glFlush and glutInitDisplayMode GLUT DOUBLE GLUT RGB with glutS
  • 如何在 OpenGL 中绘制镜像某些东西的镜子?

    根据我的理解 要在 OpenGL 中进行镜像 您基本上需要绘制场景 然后将所有内容翻转并再次绘制 只是使其通过镜子可见 从而在镜子中创建完美翻转的图像 但我看到的问题是 执行此操作时 唯一可以看到其他镜子的镜子是在前一个镜子之后渲染的镜子
  • cocos2D 或 IwGame

    我开始为 Android 开发游戏应用程序 但随着我的进步 我决定切换到跨平台环境 性能非常重要 因为后台有一些复杂的音频处理 经过几天研究该主题后 我得出的结论是 最成功的选择是 Marmalade SDK 现在我需要决定是使用IwGam
  • 与 SSE 比较 16 字节字符串

    我有 16 字节的 字符串 它们可能更短 但您可能会假设它们在末尾用零填充 但您可能不会假设它们是 16 字节对齐的 至少不总是 如何编写一个例程将它们与 SSE 内在函数进行比较 是否相等 我发现这个代码片段可能会有帮助 但我不确定它是否
  • glTranslatef 不在 glBegin .. glEnd 中工作

    我正在尝试并排绘制不同颜色的两个方块 我的问题是我无法让 glTranslatef 将第二个方块向右移动 第二个方块只是绘制在第一个方块上 void display void glClear GL COLOR BUFFER BIT glMa
  • GLSL memoryBarrierShared() 有用吗?

    我想知道 memoryBarrierShared 的用处 事实上 当我查找屏障功能的文档时 我读到 对于计算着色器中任何给定的静态屏障实例 单个工作组内的所有调用都必须进入该实例 然后才能允许任何调用继续超出该实例 这确保了在给定的屏障静态
  • 光照不适用于 gluSphere

    这是一个简单的问题 我有点羞于寻求帮助 我正在对 gluSphere 进行简单调用来渲染球体 但是 即使我很确定我正确添加了法线和照明 它也无法正确照亮 但是 如果我添加纹理 模型会正常点亮 但它似乎总是平滑的 并且我无法将其更改为平面 这

随机推荐

  • 19.STM32睡眠模式

    1 低功耗模式 就是CPU不需要继续执行时候 可以利用低功耗模式来节省功耗 3种低功耗模式 1 睡眠模式内核停止 外设 系统时钟仍然运行 2 停止模式 所有时钟停止 电源工作 但寄存器和SRAM内容保存 3 待机模式 所有内核电源关闭 只有
  • nmake 的 makefile

    宏定义 有些宏定义未用到 ROOT C Program Files x86 Microsoft Visual Studio 8 VC 系统include以及lib根目录 ROOT INCLUDE ROOT Include ROOT atlm
  • Python:Matplotlib数据可视化

    Python Matplotlib数据可视化 一 基础语法与常用参数 1 1基础语法与绘图风格 1 1 1创建画布与创建子图 1 1 2添加画布内容 1 1 3保存与展示图形 1 1 4绘图风格 2 1动态rc参数 2 1 1 线条常用的r
  • 静默安装VC_redist.x64.exe

    始 为了使vs17开发的程序在新装的win10系统跑起来 过程 1 到微软官网 下载运行时库vc redist Download Visual C Redistributable Packages for Visual Studio 201
  • c语言协程[1]_基础协程实现

    协程的本质是利用程序语言语法来实现逻辑上的多任务的编程 很多年前 我在小单片机上一直想跑操作系统 奈何Flash和RAM一直没有合适的 后来想自己怼个操作系统 结果拖延症犯了 到现在也无果 rtt freertos真香 后来一直在想有啥更好
  • devtools热更新报错 javax.management.InstanceAlreadyExistsException: org.springframework.boot:type=Admin

    项目场景 spring boot version 2 4 2 spring cloud version 2020 0 1 spring cloud alibaba version 2021 1 问题描述 在配置过devtools热更新之后
  • (zz)I/O PAD design

    http tw myblog yahoo com Calvin Horng article mid 1272 next 1257 l f fid 5 同事設計一塊電路板 不知道為什麼一通電 主要的IC開始發燙起來 我看了一看IC的Datas
  • fastreport designer.exe界面设置为中文

    fastreport 安装好后 界面默认是英文 在安装时我明明选择了安装中文语言包的 打开designer exe后显示的还是英文 原来要显示中文是需要设置designer exe的 设置如下 1 菜单栏 File gt Select La
  • C语言系列:6、结构

    C语言系列 6 结构 文章目录 C语言系列 6 结构 1 结构的基本知识 2 结构和函数 3 结构数组 4 指向结构的指针 5 自引用结构 6 表查找 7 类型定义 8 联合 9 位字段 结构是一个或多个变量的集合 这些变量可能为不同的类型
  • KEIL仿真调试问题

    Q1 如何使用keil调试程序 A1 第一个表示跳转到下一个程序状态 第二个表示跳转到下一行 在主程序中的时候也是直接跳转到主程序的下一行 第三个表示 watch窗口可以查看变量的数值 Q2 使用MDK进行软件设计时没有使用ST官方的模板而
  • js中async与await详解

    引言 JavaScript 是一门基于事件驱动和异步编程的语言 而异步编程是 JavaScript 中最常用的编程方式之一 在异步编程中 我们通常使用回调函数或 Promise 对象来处理异步操作的结果 而在 ES2017 中 引入了 as
  • JDBC连接mysql数据库

    JDBC连接mysql数据库 JDBC 使用java语言操作关系数据库的一套API 是一套标准接口 可以操作不同的关系型数据库 先复习一下 在idea里面输出hello public static void main String args
  • 在Docker中安装Gitea

    目录 在Docker中安装Gitea 1 拉取最新Gitea官方镜像 2 实例化一个Gitea容器 3 Gitea需要数据源 因此使用mysql作为后端数据库 4 在mysql中创建一个新数据库 起名gitea 5 访问Gitea主页htt
  • 每日刷题-6

    目录 一 选择题 二 算法题 1 Fibonacci数列 2 合法括号序列判断 一 选择题 1 解析 内联函数是一种可以提高函数执行效率的方法 它的原理是编译时在函数调用点直接展开函数体的代码 从而避免了函数调用的开销 但是 内联函数也有一
  • 单链表排序操作

    单链表排序操作 单链表是常见的一种数据结构 它由一系列节点组成 每个节点包含一个数据元素和一个指向下一个节点的指针 在实际开发中 我们经常需要对单链表进行排序操作 以满足不同的需求 在进行单链表的排序操作时 我们可以采用多种方法 下面将介绍
  • 10个值得前端收藏的CSS3动效库(工具)

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 现在的网站和App的设计中越来越重视用户体验 而优秀的动效则能使你的应用更具交互性 从而吸引更多用户的使用 我一般会在网站中加入一些简单而一致的动效 我所用的技术则是用SA
  • Python 3.打开摄像头,保存AVI视频 OpenCV Linux

    import cv2 import numpy as np from matplotlib import pylab as plt img cv2 imread pic1 png 2 plt imshow img cmap gray int
  • C练题笔记之:Leetcode-565. 数组嵌套

    题目 索引从0开始长度为N的数组A 包含0到N 1的所有整数 找到最大的集合S并返回其大小 其中 S i A i A A i A A A i 且遵守以下的规则 假设选择索引为i的元素A i 为S的第一个元素 S的下一个元素应该是A A i
  • 栈的 创建,入栈,出栈,清空栈,遍历栈 的实现

    数据结构 的学习视频 https www bilibili com video av6159200 from search seid 6709590585276522157 一 算法 栈 数据进出 类向箱子放东西和拿东西 先进后出 或者说后
  • OpenGL Vertex Buffer Objects(VBOs)

    OpenGL Vertex Buffer Objects VBOs 分类 OpenGL2010 05 20 12 53 3714人阅读 评论 13 收藏 举报 buffer float list struct 存储 工作 原创文章转载请注明