OpenGL进阶 | glDrawArrays与glDrawElements

        glDrawArrays直接从顶点缓冲对象(VBO)中读取顶点数据,而glDrawElements使用一个元素缓冲对象(EBO)来指定顶点的索引。那么什么是EBO呢?

1.ElementArrayBufferObject

        ElementArrayBufferObject,简称EBO,用来节省内存开销。     

        在渲染3D场景时,通常需要绘制许多三角形或其他类型的图元,这时候存在顶点数据公用的现象,为了减少数据的重复,可以使用索引数组来定义顶点的顺序,这使得顶点可以在多个图元中共享。ElementArrayBufferObject就是用来存储这些索引数据的。

        通常情况下,我们使用一个顶点缓冲对象(VertexBufferObject)存储顶点数据,然后使用一个元素数组缓冲对象(ElementArrayBufferObject)存储顶点的索引。

2.举个例子

(1)使用glDrawArrays

        glDrawArrays是WebGL中的一个绘制函数,用于绘制几何图形。它从当前的顶点缓冲对象中读取顶点数据,并按照指定的参数进行绘制。这个函数绘制的图形是由顶点数据直接确定的,没有使用到顶点索引。

void Init()
{
    float data[] = {
        -0.2f,-0.2f,-0.6f,1.0f,
        0.2f,-0.2f,-0.6f,1.0f,
        -0.2f,0.2f,-0.6f,1.0f
    };

    glGenBuffers(1, &vbo);                                                   //需要1个VBO,把vbo写入到显卡进去,供后续操作
    glBindBuffer(GL_ARRAY_BUFFER, vbo);                                      //把vbo设置到卡槽上
    //glBufferData(GL_ARRAY_BUFFER,sizeof(float)*12, nullptr,GL_STATIC_DRAW);//只在GPU上开辟内存不传数据
    glBufferData(GL_ARRAY_BUFFER,sizeof(float)*12,data,GL_STATIC_DRAW);      //将数据从cpu传到Gpu,此后data数据可删除。
    glBindBuffer(GL_ARRAY_BUFFER, 0);                                        //卡槽重新绑定,防止误操作

    //读取shader源码到GPU程序
    //...
    //读取shader变量
    //...
}
void Draw()
{
    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //设置Uniform变量
    //...

    glBindBuffer(GL_ARRAY_BUFFER, vbo);  //将顶点缓冲对象绑定到OpenGL的顶点缓冲区(GL_ARRAY_BUFFER)
    glEnableVertexAttribArray(positionLocation);  //启用位置属性索引为positionLocation的顶点属性数组
    glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4, 0);   //定义位置属性
    glDrawArrays(GL_TRIANGLES, 0, 3);    //执行绘制操作。该函数指定了绘制的模式、起始顶点索引和顶点数量。
    glBindBuffer(GL_ARRAY_BUFFER, 0);    //解绑顶点缓冲对象
}

(2)使用glDrawElements

        使用glDrawElements时,我们需要事先创建一个元素缓冲对象(EBO),并将顶点索引数据存储在其中。这些索引指定了顶点在顶点缓冲对象中的顺序,从而确定了绘制的顺序。通过使用索引,我们可以共享顶点数据,减少存储空间和数据传输量,并允许更复杂的图形绘制。

        使用glDrawElements相比于glDrawArrays的主要优势在于它允许更高效地绘制具有共享顶点的复杂图形。

void Init()
{
    float data[] = {
        -0.2f,-0.2f,-0.6f,1.0f,
        0.2f,-0.2f,-0.6f,1.0f,
        -0.2f,0.2f,-0.6f,1.0f
    };

    glGenBuffers(1, &vbo);                                                   //需要1个VBO,把vbo写入到显卡进去,供后续操作
    glBindBuffer(GL_ARRAY_BUFFER, vbo);                                      //把vbo设置到卡槽上
    //glBufferData(GL_ARRAY_BUFFER,sizeof(float)*12, nullptr,GL_STATIC_DRAW);//只在GPU上开辟内存不传数据
    glBufferData(GL_ARRAY_BUFFER,sizeof(float)*12,data,GL_STATIC_DRAW);      //将数据从cpu传到Gpu,此后data数据可删除。
    glBindBuffer(GL_ARRAY_BUFFER, 0);                                        //卡槽重新绑定,防止误操作

    unsigned int indices[] = { 
        0, 1, 2,       // 第一个三角形 
    };
 
    glGenBuffers(1, &ebo);                                                   //创建1个EBO,并将标识符存储在ebo变量中
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);                               //将EBO绑定到GL_ELEMENT_ARRAY_BUFFER目标
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 3, indices, GL_STATIC_DRAW); //将索引数据从CPU传输到GPU
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);                                 //将索引数据从CPU传输到GPU
    //读取shader源码到GPU程序
    //...
    //读取shader变量
    //...
}
void Draw()
{
    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //设置Uniform变量
    //...

    glBindBuffer(GL_ARRAY_BUFFER, vbo);  //将顶点缓冲对象绑定到OpenGL的顶点缓冲区(GL_ARRAY_BUFFER)
    glEnableVertexAttribArray(positionLocation);  //启用位置属性索引为positionLocation的顶点属性数组
    glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4, 0);   //定义位置属性
    glBindBuffer(GL_ARRAY_BUFFER, 0);    //解绑顶点缓冲对象

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烫青菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值