1.glGenBuffers 官方解释:generate buffer object names
意思是该函数用来生成缓冲区对象的名称。
函数原型:void glGenBuffers(GLsizei n,GLuint * buffers);
第一个参数是要生成的缓冲对象的数量,第二个是要输入用来存储缓冲对象名称的数组
该函数会在buffers里返回n个缓冲对象的名称。
个人理解如下,可以声明一个GLuint变量,然后使用glGenBuffers后,它就会把缓冲对象保存在vbo里,当然也可以声明一个数组类型,那么创建的3个缓冲对象的名称会依次保存在数组里。
GLuint vbo;
glGenBuffers(1,&vbo);
GLuint vbo[3];
glGenBuffers(3,vbo);
注意:这里我用的是VBO做的示范,解释一下,glGenBuffers()函数仅仅是生成一个缓冲对象的名称,这个缓冲对象并不具备任何意义,它仅仅是个缓冲对象,还不是一个顶点数组缓冲,它类似于C语言中的一个指针变量,我们可以分配内存对象并且用它的名称来引用这个内存对象。OpenGL有很多缓冲对象类型,那么这个缓冲对象到底是什么类型,就要用到下面的glBindBuffer()函数了。
glCreateBuffers和glGenBuffers一样,但是前者在opengl4.5开始支持,而后者支持所有版本。
2.glBindBuffer 官方解释:bind a named buffer object
函数原型:
void glBindBuffer(GLenum target,GLuint buffer);
第一个就是缓冲对象的类型,第二个参数就是要绑定的缓冲对象的名称,也就是我们在上一个函数里生成的名称,使用该函数将缓冲对象绑定到OpenGL上下文环境中以便使用。如果把target绑定到一个已经创建好的缓冲对象,那么这个缓冲对象将为当前target的激活对象;但是如果绑定的buffer值为0,那么OpenGL将不再对当前target使用任何缓存对象。
在OpenGL红宝书中给出了一个恰当的比喻:绑定对象的过程就像设置铁路的道岔开关,每一个缓冲类型中的各个对象就像不同的轨道一样,我们将开关设置为其中一个状态,那么之后的列车都会驶入这条轨道。
切记:官方文档指出,GL_INVALID_VALUE is generated if buffer is not a name previously returned form a call to glGenBuffers。换句话说,这个名称虽然是GLuint类型的,但是你万万不能直接指定个常量比如说0,
如果你这样做,就会出现GL_INVALID_VALUE的错误。
glBindBuffer(GL_ARRAY_BUFFER, VBO); //VBO变成了一个顶点缓冲类型
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
OpenGL允许我们同时绑定多个缓冲类型,只要这些缓冲类型是不同的,换句话说,同一时间,不能绑定两个相同类型的缓冲对象。也可以理解为对于一个类型来说,同一时间只能“激活”一个类型,否则就会发生“矛盾”。
为什么呢。首先要理解绑定缓冲类型后,所有该缓冲类型的函数调用都要用来配置该目标缓冲类型,比如顶点缓冲类型GL_ARRAY_BUFFER,glBufferData是通过指定目标缓冲类型来进行数据传输的,而每一个目标缓冲类型再使用前要提前绑定一个缓冲对象,从而赋予这个缓冲对象一个类型的意义,如果绑定了两个相同类型的目标缓冲,数据的配置肯定就会出错。(可以这样想一下,我要把数据存入顶点缓冲区,但是顶点缓冲区可以有很多缓冲对象,我需要传入哪个呢,于是我就要提前绑定一个,之后,我只要向顶点缓冲区内传入数据,这个数据就会自动进入被绑定的那个对象里面)
之后调用glBufferData()传输所需数据,其中第一个参数就是要制定缓冲类型,根据这个类型锁定当前唯一的目标缓冲。
3.缓冲区对象只是OpenGL众多对象中的一种,其实当我们使用其它对象时,都是类似的思路
GLuint vbo;
glGenObject(1,&vbo);
GLuint vbo[3];
glGenObject(3,vbo);
glBindObject(GL_WINDOW_TARGET,vbo[1]);
创建对象,绑定类型,设置数据。