OpenGL缓冲区对象之EBO

来源:互联网 发布:aframe.js下载 编辑:程序博客网 时间:2024/05/22 17:20

简介

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

GLfloat vertices[] = {//前-1,-1,1, //v41, -1, 1 //v51, 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); //绑定EBOglBufferData(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中的偏移量,否则就是索引数组的指针。

0 0
原创粉丝点击