OpenGL 4.0中数据缓冲VBO,VAO,EBO的使用总结
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的使用总结的更多相关文章
- OpenGL 4.0 GLSL 基础教程概览——VAO和VBO常用操作接口
(一) OpenGL 4.3 最新渲染管线图 从OpenGL 2.0 到 OpenGL 3.0变化非常大,但从OpenGL 3.0 到OpenGL 4.0 变化不是太大. 着色器程序直接运行在GPU ...
- LearnOpenGL学习笔记(三)——VBO,VAO,EBO理解
在opengl中所有的数据都要放在显存中,我们通过一定的手段去管理它,既要提供地方存放它,还要提供方法去正确地提取它们,去使用它们,opengl通过VAO,VBO,EBO这些手段来解决这些问题. (一 ...
- yii2.0中数据缓存之增删改查
public function actionSss(){ /* * 获取到缓存 * 这里是获取的是根目录下 的common/main.php中的缓存类组件 * */ $cache=\Yii::$app ...
- 解决EF 4.0 中数据缓存机制
EF4.0默认开启缓存机制,如果想要禁用缓存机制的话,则须加上一句话:_db.CreateObjectSet().MergeOption = MergeOption.OverwriteChanges; ...
- yii2.0 中数据查询中 or、in、between 及session的使用
1 HTML: 2 3 <div> 4 <form class="form-inline " method="get" action=&quo ...
- libevent中数据缓冲区buffer分析
很多时候为了应对数据IO的"慢"或者其他原因都需要使用数据缓冲区.对于数据缓冲,我们不陌生,但是对于如何实现这个缓冲区,相信很多时候大家都没有考虑过.今天就通过分析libevent ...
- OpenGL中VA,VAO,VBO和EBO的区别
1,顶点数组(Vertex Array) VA,顶点数组也是收集好所有的顶点,一次性发送给GPU.不过数据不是存储于GPU中的,绘制速度上没有显示列表快,优点是可以修改数据. 4.VBO(Vertex ...
- Cocos2d-x中使用OpenGL ES2.0编写shader
这几天在看子龙山人的关于OpenGL的文章,先依葫芦画瓢,能看到些东西,才能慢慢深入了解,当入门文章不错,但是其中遇到的一些问题,折腾了一些时间,为了方便和我一样的小白们,在这篇文章中进行写补充. O ...
- 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 ...
- unix中数据缓冲区高速缓冲的设计
目录 1. 概述 2. 缓冲区的设计 2.1 缓冲区头部 2.2 缓冲区的结构 2.3 缓冲区的检索算法 2.3. 申请一个缓冲区算法 getblk 2.3.2 释放一个缓冲区算法 brelse 2. ...
随机推荐
- 基于 OAuth2.0 协议的单点登录系统方案设计
一.什么是单点登录? 单点登录(Single Sign On),简称为 SSO,是比较流行的企业业务整合的解决方案之一.SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用 ...
- Flutter TextField开始输入中文的时候,被打断导致错误输入字母问题
一.Bug样例 建立一个web demo flutter run -d chrome --web-renderer html 出现问题: 输入中文的时候,比如打字 hao, 第一个字母h会先输入,变成 ...
- NOIP模拟53
我在时光斑驳深处,聆听到花开的声音. 前言 这套题好像是随便拼接起来的,来自三套不同的题,最后一道还是学长出的(nb 场上为数不多的几次死磕一道题正解,大概有三个小时吧(惭愧,前两个小时看错题了,一直 ...
- containerd 源码分析:创建 container(三)
文接 containerd 源码分析:创建 container(二) 1.2.2.2 启动 task 上节介绍了创建 task,task 创建之后将返回 response 给 ctr.接着,ctr 调 ...
- python的一些常用编码技巧(持续更新)
语法问题 我常用的库函数 1 copy库 import copy copy.deepcopy() 2.list库 from typing import List 获取迭代对象的第一个值 方法一:使用l ...
- MySQL创建表的时候建立联合索引的方法
1.MySQL创建表建立联合索引的步骤 在MySQL中,联合索引(也称为复合索引或多列索引)是基于表中的多个列创建的索引.这种索引可以提高多列查询的性能,特别是当查询条件涉及这些列时.下面是一个详细的 ...
- 别想宰我,怎么查看云厂商是否超卖?详解 cpu steal time
据说有些云厂商会超卖,宿主有 96 个核心,结果卖出去 100 多个 vCPU,如果这些虚机负载都不高,大家相安无事,如果这些虚机同时运行一些高负载的任务,相互之间就会抢占 CPU,对应用程序有较大影 ...
- 网络诊断工具traceroute的使用
在 Linux 系统中,traceroute 是一个网络诊断工具,用于确定数据包从你的计算机到目标主机(如一个网站或远程服务器)所经过的路由路径. 如果你的系统中没有安装 traceroute,你可以 ...
- undefined,null 和 undeclared 有什么区别?
a.null表示"没有对象",即该处不应该有值,转为数值时为0.典型用法是:作为函数的参数,表示该函数的参数不是对象.作 为对象原型链的终点. b.undefined表 ...
- 第四届物联网与机器学习国际学术会议(IoTML 2024)
[ACM独立出版,高录用,见刊检索快速稳定]第四届物联网与机器学习国际学术会议(IoTML 2024) [IoTML 2023会后三个半月内完成EI检索]2024 4th International ...