实验3——绘制四边形(EBO)

复制粘贴运行 

认识总是从低级到高级的,我是小白,处于低级的认识;只会复制粘贴运行。

那就干吧。

计算机图形学_中国大学MOOC(慕课) (icourse163.org)

直接cmake出来,也行

得设置一下启动项目

尝试学习EBO

学不会很正常,是小白的常态,所以,不要有心理负担。

首先,为什么要有EBO?这个东西为什么要存在?

之前已经了解过了一些VAO+VBO的相关函数,勉勉强强能看懂这个代码在干什么了。

完整代码在这里

运行结果是这个

但是这存在一些问题:

4边形,4个顶点就够了,这里却在显存里存了6个顶点,冗余了2个,也就是,50%。

// 四边形的顶点数据
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     // 左上
};

显存,很贵的。。还冗余50%。怎么才能省着用?——EBO诞生了。

有了EBO,存VBO时就可以忽略那些重复的顶点属性了。

VBO顶点属性内容很多(最多16个吧),重复一下,吃不消。。

index,一个数值而已,重复一下,没啥,可以接受。

设计的挺好的……

VAO+VBO+EBO的代码在这里

结果在这里:

 索引也是占空间的,在这种小模型上,EBO说不定起不了作用。但大模型应该EBO就发挥作用了吧。

一些相关链接

网页1

短小精悍的总结

  1. 顶点缓冲对象VBO是在显卡存储空间中开辟出的一块内存缓存区,用于存储顶点的各类属性信息,如顶点坐标,顶点法向量,顶点颜色数据等。在渲染时,可以直接从VBO中取出顶点的各类属性数据,由于VBO在显存而不是在内存中,不需要从CPU传输数据,处理效率更高。所以可以理解为VBO就是显存中的一个存储区域,可以保持大量的顶点属性信息。并且可以开辟很多个VBO,每个VBO在OpenGL中有它的唯一标识ID,这个ID对应着具体的VBO的显存地址,通过这个ID可以对特定的VBO内的数据进行存取操作。
  2. VAO本身并没有存储顶点的相关属性数据,这些信息是存储在VBO中的,VAO相当于是对很多个VBO的引用,把一些VBO组合在一起作为一个对象统一管理。执行VAO绑定之后其后的所有VBO配置都是这个VAO对象的一部分,可以说VBO是对顶点属性信息的绑定,VAO是对很多个VBO的绑定。
  3. EBO中存储的内容就是顶点位置的索引indices,EBO跟VBO类似,也是在显存中的一块内存缓冲器,只不过EBO保存的是顶点的索引
  4. VAO简单理解其实代表的就是模型的数据,当可能需要很多个模型,每个模型对应一个VAO,所以需要有个id来区分,创建vao的时候会返回一个vaoID。VAO中有一个属性列表,默认有16个属性(0 - 15),我们可以为属性指定数据,其中属性可以是顶点位置,颜色,法线,纹理坐标等等我们需要的数据,其中的每一个属性对应的数据其实就来自VBO。

引用自:

(31条消息) OpenGl(1) VAO、VBO、EBO的理解_Coder_Penguin的博客-优快云博客_vao

 

 网页2

这个里面,给出了这几个Object的伪代码

  • 数据结构的定义

还是这个熟悉的图

这段代码,和上面那个图,呼应的。。

struct VertexAttributeState  
{  
    bool                bIsEnabled = false;  
    int                 iSize = 4; //This is the number of elements in each attrib, 1-4.  
    unsigned int        iStride = 0;  
    VertexAttribType    eType = GL_FLOAT;  
    bool                bIsNormalized = false;  
    bool                bIsIntegral = false;  
    void *              pPtrOrBufferObjectOffset = 0;  
    BufferObject *      pBufferObj = 0;  
};  
   
struct VertexArrayObjectState
{  
    BufferObject *pElementArrayBufferObject = NULL;  
    VertexAttributeState attributes[MAX_VERTEX_ATTRIB];  
}  
  • 相关的一些函数的实现
 
static VertexArrayObjectState *pContextVAOState = new VertexArrayObjectState();  
static BufferObject *pCurrentArrayBuffer = NULL;
//绑定缓冲对象 如VBO EBO等
void glBindBuffer(enum target, uint buffer)  
{  
    BufferObject *pBuffer = ConvNameToBufferObj(buffer);  
   
    switch(target)  
    {  
    //绑定VBO 先用一个临时变量存储
    case GL_ARRAY_BUFFER:  
        pCurrentArrayBuffer = pBuffer;  
        break;  
    //绑定EBO 直接更新
    case GL_ELEMENT_ARRAY_BUFFER:  
        pContextVAOState->pElementArrayBufferObject = pBuffer;  
        break;  
    ...  
    }  
}  
//禁用属性
void glEnableVertexAttribArray(uint index)  
{  
    pContextVAOState->attributes[index].bIsEnabled = true;  
}  
//启用属性
void glDisableVertexAttribArray(uint index)  
{  
    pContextVAOState->attributes[index].bIsEnabled = false;  
}  

//链接顶点属性指针
void glVertexAttribPointer(uint index, int size, enum type, boolean normalized, sizei stride, const void *pointer)  
{  
    VertexAttributeState &currAttrib = pContextVAOState->attributes[index];  
   
    currAttrib.iSize = size;  
    currAttrib.eType = type;  
    currAttrib.iStride = stride;  
    currAttrib.bIsNormalized = normalized;  
    currAttrib.bIsIntegral = true;  
    currAttrib.pPtrOrBufferObjectOffset = pointer;  
    //此时才会保存VBO!!
    currAttrib.pBufferObj = pCurrentArrayBuffer;  
}

 通过这段伪代码,有以下认识

  1. bind索引数组就直接改变了vao,而bind顶点数组,改变了内部的顶点缓存指针,而真正的将顶点缓存指针的值写入vao其实是glVertexAttribPointer函数。
  2. 这段代码体现了VBO和顶点属性指针的关系,在绑定VBO后,一定要设置好顶点属性指针,不然就等于白给。
  3. 如果在解绑VAO之前解绑了EBO,那么该VAO存储的EBO就无了,自然绘制不出东西。这个EBO设置的就没意义了。
  4. VAO本来的意义就是这个结构是存储在服务端内存中的(也就是显存中),你只要bind一个VAO就能获得一次drawcall需要的所有信息,所以它快
  5. 绑定顺序:先绑定VAO,然后绑定VBO和EBO,再链接顶点属性指针
  6. 解绑顺序:在绑定VBO并链接顶点属性指针之后,即可解绑该VBO,但是解绑EBO的操作一定要放到解绑VAO的操作之后。就是说,解绑顺序是:VBO(注意要先链接顶点属性指针)、VAO、EBO

引用自:

(20 封私信 / 8 条消息) VAO和EBO解绑定的坑? - 知乎 (zhihu.com)

 (31条消息) OpenGL VAO VBO EBO(IBO)的绑定、解绑问题_csu_xiji的博客-优快云博客

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值