OpenGL缓冲区对象之EBO

简介

EBO(Element Buffer Object,也叫IBO:Index Buffer Object)索引缓冲区对象,这个缓冲区主要用来存储顶点的索引信息。
考虑这样一种情况,我们需要绘制一个立方体
Cube
在指定顶点坐标的时候,可以使用以下的一个数组:

GLfloat vertices[] = {
//前
-1,-1,1, //v4
1, -1, 1 //v5
1, 1, 1 //v6
-1, 1, 1 //v7
//左
-1,1,-1 //v0
-1,-1,1 //v4
-1,1,1 //v7
-1,1,-1 //v3
......
};

可以看到事实上整个立方体只有8个顶点,我们存储顶点坐标的数组里出现了大量重复的顶点。最好的方式应该是每个顶点只需要存储一次,当我们需要这些顶点时,只需要调用顶点的索引来引用的需要的顶点数据

这里写图片描述

EBO就是用来存储这些索引数据的地方。

使用

1. 创建EBO

创建EBO的方式与创建VBO类似,都是使用glGenBuffers

void glGenBuffers(  GLsizei n,
    GLuint * buffers);
    //n :创建缓冲区数量
    //buffers:存放这些ID的数组或者变量指针
GLuint eboID;
glGenBuffers(1, &eboID);
2.传入数据

在创建完成EBO之后,需要向EBO中传入索引数据,在传入之前需要绑定将EBO(将eboID设置为当前操作的EBO)

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); //绑定EBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); //传入索引数据到EBO中
3. 绘制几何体

当设置完成之后,可以调用glDrawElements来绘制(如果不使用索引的方式,绘制需要调用的函数是glDrawArrays)

void glDrawElements(    
    GLenum mode,    //绘制模式,可以是GL_TRIANGLES、GL_POINTS等     
    GLsizei count, //绘制顶点的次数
    GLenum type,   //索引数据的类型
    const GLvoid * indices //EBO中的偏移量(如果不使用EBO,那么indices指向的是索引数组的指针)
);

示例程序

示例程序中使用EBO的方式绘制一个四边形

#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "freeglut.lib")


#include <stdio.h>
#include <gl/glew.h>
#include <gl/glut.h>

GLuint eboID;

#define USE_EBO 

GLfloat 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   // 左上角
};

GLuint indices[] = {
    // 起始于0!
    0, 1, 3, // 第一个三角形
    1, 2, 3  // 第二个三角形
};


void ChangeSize(int w, int h)
{
    if (h == 0)
        h = 1;
    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, w*1.0 / h, 0.01, 1000.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void SetupRC()
{
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    glGenBuffers(1, &eboID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

}

void RenderScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);
    glLoadIdentity();
    glTranslatef(0, 0, -5.0);

    //开启VA状态  
    glEnableClientState(GL_VERTEX_ARRAY);

    //绑定数据  
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    //绘制

#ifdef USE_EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboID);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
#else
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices);
#endif
    //关闭VA状态  
    glDisableClientState(GL_VERTEX_ARRAY);

    glutSwapBuffers();
}


int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowSize(800, 600);
    glutCreateWindow("OpenGL");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);

    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }

    SetupRC();

    glutMainLoop();
    return 0;
}

为了简单,没有使用core profile的方式来使用EBO,代码中如果定义USE_EBO,glDrawElements最后一个参数是EBO中的偏移量,否则就是索引数组的指针。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,我来为你解答。 1. OpenGL图形渲染管线 OpenGL图形渲染管线是OpenGL对图形数据进行处理的流程。它包括两个主要部分:顶点处理阶段和片元处理阶段。其中,顶点处理阶段将顶点数据转换成片元数据,片元处理阶段将片元数据转换成最终的图像颜色值。 2. VBO VBO(Vertex Buffer Object)是OpenGL中的一种缓冲区对象,它用于存储顶点数据。使用VBO可以将顶点数据存储到显存中,从而提高渲染效率。 3. VAO VAO(Vertex Array Object)是OpenGL中的另一种缓冲区对象,它用于存储顶点数组状态。使用VAO可以将多个VBO绑定到一个VAO中,从而方便在不同的渲染环境中切换。 4. EBO EBO(Element Buffer Object)也是OpenGL中的一种缓冲区对象,它用于存储顶点索引数据。使用EBO可以减少顶点数据的冗余,从而节省显存空间。 下面是一个简单的用例,演示如何使用VBO、VAO和EBO进行三角形的渲染: ```c++ // 顶点数据 float vertices[] = { // 位置 // 颜色 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f }; // 索引数据 unsigned int indices[] = { 0, 1, 2 }; // 创建VBO、VAO、EBO对象 unsigned int VBO, VAO, EBO; glGenBuffers(1, &VBO); glGenVertexArrays(1, &VAO); glGenBuffers(1, &EBO); // 绑定VBO、VAO、EBO对象 glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // 设置顶点属性指针 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); // 渲染三角形 glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); glBindVertexArray(0); // 删除VBO、VAO、EBO对象 glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); glDeleteVertexArrays(1, &VAO); ``` 上面的代码首先创建了一个顶点数组和一个索引数组,然后创建了VBO、VAO、EBO对象,并将顶点数据和索引数据存储到对应的缓冲区对象中。接着,设置了顶点属性指针,并在渲染时使用glDrawElements函数渲染了三角形。最后,删除了VBO、VAO、EBO对象

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值