Opengl是大家常用的一个API,我们用它绘制数据的时候需要使用vao,vbo,ebo等对象,绘制方式分为 vao绘制,ebo绘制等。使用不同api还能分为普通调用以及Instance绘制。

首先申请vao,vbo和以及他们两者的绑定:

 这里注意的是,百度百科上说的最多支持四个位置,我测试了一下,7到8个顶点属性都没问题,比如Position,Texcoord,Color,Normal等等,需要排列好。

其实他们的绑定有两种方式,第一种是vao搭配多个vbo,每一个vbo代表顶点的一种属性,比如vbo[0] 代表位置,vbo[1]代表纹理坐标。。代码如下:

//位置
glGenBuffers(1, &vbo0);
glBindBuffer(GL_ARRAY_BUFFER, vbo0);
glBufferData(GL_ARRAY_BUFFER, 3 * 4 * sizeof(GLfloat), posCube, GL_STATIC_DRAW); glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
//纹理
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), texCube, GL_STATIC_DRAW); glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); //法线
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glBufferData(GL_ARRAY_BUFFER, 3 * 4 * sizeof(GLfloat), normalCube, GL_STATIC_DRAW); glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), nullptr); //法线
glGenBuffers(1, &vbo3);
glBindBuffer(GL_ARRAY_BUFFER, vbo3);
glBufferData(GL_ARRAY_BUFFER, 3 * 4 * sizeof(GLfloat), normalCube2, GL_STATIC_DRAW); glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), nullptr); //法线
glGenBuffers(1, &vbo4);
glBindBuffer(GL_ARRAY_BUFFER, vbo4);
glBufferData(GL_ARRAY_BUFFER, 3 * 4 * sizeof(GLfloat), normalCube3, GL_STATIC_DRAW); glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), nullptr); //法线
glGenBuffers(1, &vbo5);
glBindBuffer(GL_ARRAY_BUFFER, vbo5);
glBufferData(GL_ARRAY_BUFFER, 3 * 4 * sizeof(GLfloat), normalCube4, GL_STATIC_DRAW); glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), nullptr);

第二种关联方式:则一个vao搭配一个vbo,这种传递方式类似于把结构体数组或者内存的数据传递给vbo。 内存排布 是这样的:位置纹理法线位置纹理法线  。位置是float x3,纹理floatx2,法线float x3,

解析的时候就是 顶点1: 位置纹理法线 顶点2位置纹理法线,他们会有间隔

struct MyVertex
{
vec3 pos;
vec2 tex;
vec3 normal;
}; //顶点定义
for (int i = 0; i < 4; i++)
{
MyVertex v;
v.pos.x = posCube[i * 3 + 0];
v.pos.y = posCube[i * 3 + 1];
v.pos.z = posCube[i * 3 + 2]; v.tex.s = texCube[i * 2 + 0];
v.tex.t = texCube[i * 2 + 1]; v.normal.x = normalCube2[i * 3 + 0];
v.normal.y = normalCube2[i * 3 + 1];
v.normal.z = normalCube2[i * 3 + 2];
eboBuffers.push_back(v);
} glGenVertexArrays(1, &vao);
glBindVertexArray(vao); glGenBuffers(1, &vbo0);
glBindBuffer(GL_ARRAY_BUFFER, vbo0); glBufferData(GL_ARRAY_BUFFER, eboBuffers.size()* sizeof(MyVertex), eboBuffers.data(), GL_STATIC_DRAW);
int stride = sizeof(MyVertex);
glEnableVertexAttribArray(0); //根据属性数量来顶,这里开启三个 0 1 2
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)offsetof(MyVertex, pos));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)offsetof(MyVertex, tex));
glVertexAttribPointer(2, 3, GL_FLOAT, GL_TRUE, stride, (GLvoid*)offsetof(MyVertex, normal));

VAO绘制:

glBindVertexArray(vao);
glDrawArrays(GL_QUADS, first, count); //第一个是起始位置,第二个是顶点数量

EBO的绘制:

  ebo的好处是可以省大量的内存,只需要调用顶点所在的索引(id)即可完成绘制,因为

  在有了vao,vbo的申请以及他们的内存关联之后,ebo开始工作。

  ebo绘制有两种方式

1)先申请在绘制

  

//申请:
glGenBuffers(1, &eboId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLubyte), vIdx, GL_STATIC_DRAW); //vidx 即绘制索引数组 GLubyte vIdx[] = { 0,1,2,1,2,3 }; //绘制:
glBindVertexArray(vao);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_BYTE, 0); //最后一个参数是0,因为已经绑定了vao,ebo

2. 直接使用数组

    //清除已绑定的ebo
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_BYTE, vIdx); //传入索引数组内存以及顶点数量

最后绘制在Shader中的展示(ebo,vbo调用均一样): Normal2,Normal3,Normal4 是用来测试顶点属性数量用的,支持6个属性没问题

uniform mat4 proj;
uniform mat4 view;
uniform mat4 model; layout (location = 0) in vec3 Position; //layout (locatiopn=0)一定要写,否则识别会出问题
layout (location = 1) in vec2 Texcoord;
layout (location = 2) in vec3 Normal;
layout (location = 3) in vec3 Normal2;
layout (location = 4) in vec3 Normal3;
layout (location = 5) in vec3 Normal4; out vec3 Color; void main()
{ Color = Normal4;
gl_Position = proj * view *model* vec4(Position,1);
}

OpenGL 4.0中数据缓冲VBO,VAO,EBO的使用总结的更多相关文章

  1. OpenGL 4.0 GLSL 基础教程概览——VAO和VBO常用操作接口

    (一) OpenGL  4.3 最新渲染管线图 从OpenGL 2.0 到 OpenGL 3.0变化非常大,但从OpenGL 3.0 到OpenGL 4.0 变化不是太大. 着色器程序直接运行在GPU ...

  2. LearnOpenGL学习笔记(三)——VBO,VAO,EBO理解

    在opengl中所有的数据都要放在显存中,我们通过一定的手段去管理它,既要提供地方存放它,还要提供方法去正确地提取它们,去使用它们,opengl通过VAO,VBO,EBO这些手段来解决这些问题. (一 ...

  3. yii2.0中数据缓存之增删改查

    public function actionSss(){ /* * 获取到缓存 * 这里是获取的是根目录下 的common/main.php中的缓存类组件 * */ $cache=\Yii::$app ...

  4. 解决EF 4.0 中数据缓存机制

    EF4.0默认开启缓存机制,如果想要禁用缓存机制的话,则须加上一句话:_db.CreateObjectSet().MergeOption = MergeOption.OverwriteChanges; ...

  5. yii2.0 中数据查询中 or、in、between 及session的使用

    1 HTML: 2 3 <div> 4 <form class="form-inline " method="get" action=&quo ...

  6. libevent中数据缓冲区buffer分析

    很多时候为了应对数据IO的"慢"或者其他原因都需要使用数据缓冲区.对于数据缓冲,我们不陌生,但是对于如何实现这个缓冲区,相信很多时候大家都没有考虑过.今天就通过分析libevent ...

  7. OpenGL中VA,VAO,VBO和EBO的区别

    1,顶点数组(Vertex Array) VA,顶点数组也是收集好所有的顶点,一次性发送给GPU.不过数据不是存储于GPU中的,绘制速度上没有显示列表快,优点是可以修改数据. 4.VBO(Vertex ...

  8. Cocos2d-x中使用OpenGL ES2.0编写shader

    这几天在看子龙山人的关于OpenGL的文章,先依葫芦画瓢,能看到些东西,才能慢慢深入了解,当入门文章不错,但是其中遇到的一些问题,折腾了一些时间,为了方便和我一样的小白们,在这篇文章中进行写补充. O ...

  9. OpenGL ES 2: debugging, and improvements to VAO, VBO

    OpenGL ES 2: debugging, and improvements to VAO, VBO http://www.altdevblogaday.com/2013/10/12/opengl ...

  10. unix中数据缓冲区高速缓冲的设计

    目录 1. 概述 2. 缓冲区的设计 2.1 缓冲区头部 2.2 缓冲区的结构 2.3 缓冲区的检索算法 2.3. 申请一个缓冲区算法 getblk 2.3.2 释放一个缓冲区算法 brelse 2. ...

随机推荐

  1. NOIP模拟89(多校22)

    T1 谜之阶乘 解题思路 二分答案,发现 \(a-b\) 至多为 19,毕竟 \(20!\) 已经大于 \(10^{18}\) 了. 对于每一种可能的差值,每一次二分 \(b+1\) 直接枚举乘积进行 ...

  2. java中以字符分隔的字符串与字符串数组的相互转换

    1.字符串数组拼接成一个以指定字符(包括空字符)分隔的字符串--String.join(),JDK8的新特性 String[] strArray = {"aaa","bb ...

  3. [SWPUCTF 2021 新生赛]easyrce

    这道题比较简单,打开环境一看就只需要构造一个get传参的命令就行,我们就看一下有些什么文件,构造payload: ?url=system ("ls /"); 看到有个 flllll ...

  4. LeetCode 719. 找出第 k 小的距离对 (Java)

    题目: 给定一个整数数组,返回所有数对之间的第 k 个最小距离.一对 (A, B) 的距离被定义为 A 和 B 之间的绝对差值. 示例 1: 输入:nums = [1,3,1]k = 1输出:0 解释 ...

  5. P1737

    problem \(\text{task 1}\) 要求: 输入:\(a,b\). 输出:\(-2a-2b\). 数据范围:\(|a|,|b| \le 10^9\). 做法: 先把 \(-2\) 提出 ...

  6. fontawesome-webfont.woff:1 Failed to load resource: the server responded with a status of 404 ()

    fontawesome-webfont.woff2:1 Failed to load resource: the server responded with a status of 404 ()fon ...

  7. 文件系统(六):一文看懂linux ext4文件系统工作原理

    liwen01 2024.06.09 前言 Linux系统中的ext2.ext3.ext4 文件系统,它们都有很强的向后和向前兼容性,可以在数据不丢失的情况下进行文件系统的升级.目前ext4是一个相对 ...

  8. koishi常用插件推荐

    今天给大家做一个常用插件的推荐 以下将插件归为几个大类,按类型推荐 1. 日常相关 点歌 插件名:koishi-plugin-music-downloadvoice-api 功能介绍: 语音点歌 - ...

  9. 如何更改.NET中的默认时区?

    除了"在操作系统中修改时区信息,然后重启.NET应用程序,使其生效"之外.如何在不修改操作系统时区的前提下,修改.NET中的默认时区呢? 这是一位 同学兼同事 于5月21日在技术群 ...

  10. 未能加载文件或程序集“netstandard,Version=2.0.0.0, Culture=neutral,PublicKeyToken=cc7b13ffcd2ddd51”或它的某一个依赖项 解决

    未能加载文件或程序集"netstandard,Version=2.0.0.0, Culture=neutral,PublicKeyToken=cc7b13ffcd2ddd51"或它 ...