OpenGL理解(一)

    OpenGL是一个3d库和显卡操作工具,每一种显卡都有其OpenGL库,而所有显卡提供的接口却是相同的,说白了,OpenGL允许我们用相同的程序控制不同的显卡,这样我们就可以只编写一次程序,在多个显卡上运行了。

  • 顶点数组对象:Vertex Array Object,VAO
  • 顶点缓冲对象:Vertex Buffer Object,VBO
  • 索引缓冲对象:Element Buffer Object,EBO或Index Buffer Object,IBO

    OpenGL主要做的,就是把3d坐标转换为2d坐标,这个转换过程是特别适合成千上万的小处理核心共同做相似的工作,也就是并发性特别强,这就是显卡存在的目的,也叫GPU,每一个GPU上的程序都是相似的,我们把这个小程序称为Shader。
    而编写在GPU上运行的shader程序有专门的编程语言,类似这样的:

#version 330 core
layout (location = 0) in vec3 aPos;

void main() {
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}

    很像C语言,这段代码就是放到GPU上运行的,我们把这段代码放到C语言的字符串中,然后在C语言里调用函数把它编译,运送到GPU上,然后执行操作了。

    自己编写shader程序的好处就是可以随便控制图像的显示,缺点就是比较难,令人不幸的是,在现代的OpenGL中,没有默认的shader程序,必须我们自己编写。

    光有程序不行,还必须要有数据,有数据才能描述一个物体形状,OpenGL是一个3D库,因此我们要指定一个3d的顶点坐标,例如:

    float vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f };

    在C语言中,数组永远都是一维数组,我们还需要配置OpenGL如何解释这个数组,并且指定其如何发送到显卡上的shader程序,发送到GPU上,其实就是发送到GPU的内存上,也就是显存,如何控制显存上的数据,就用到VBO了,用VBO来操作。

    用函数glGenBuffers来生成一个VBO,生成VBO之后,还需要绑定VBO,glBindBuffer(GL_ARRAY_BUFFER, VBO); 就是绑定的函数,绑定到哪里呢?按照我的理解,OpenGL函数库就一个,vbo你想创造几个就创造几个,但OpenGL用哪一个呢?所以就用这个函数绑定,再用OpenGL其他函数时,默认就使用的这个VBO来操作显存,然后使用glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);函数,将之前定义好的数据也与OpenGL函数库绑定,这样我们就把数据送到了显存中。

    我们编译好shader程序还不行,跟C语言一样,它也需要链接,链接完才能创建一个程序对象。创建一个程序对象用glCreateProgram(),链接用glLinkProgram。

    程序编好了,我们就使用它,用glUseProgram(shaderProgram);函数。

    但程序是编完了,我们还没有给它指定数据,虽然我们已经把数据放到显存里了,但是面对成千的GPU,我们如何分配这些数据呢?所以我们需要对GPU解释这些数据。到底谁用哪一个。因此我们就需要链接程序和数据。

    我们已经指定OpenGL要使用的函数了,因此再给OpenGL指定显存上的数据就可以了,用下面的函数:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

    这两个函数同时也会解释程序会如何使用这些数据,然后使用绘制函数someOpenGLFunctionThatDrawsOurTriangle();完成绘制。

    这里也会有一个问题,如果每个物体都需要这样,那么面对成百上千的物体,我们都需要编译程序,绑定数据吗?并不是,我们可以把我们制作好的这些存起来,而不是随时用,随时编译执行。

    这也就是VAO存在的意义,我们可以把专门作用于一个物体的函数和数据存在这个VAO里,把作用于另一个物体的函数和数据放在另一个VAO里,什么时候用,什么时候用哪个VAO的函数就行了。

    要想使用VAO,需要进行函数和数据的绑定,数据的操作用VBO来做,数据和函数的一起操作就用VAO来做,就这样,一个物体一个VAO,在画的时候,我说过,OpenGL函数的特点就是,它更像是一个类实例而不是一个类,函数只能够使用一次,因此我们用完一个VAO,然后移除它,换下一个VAO,等到所有VAO画完了,物体也就都画完了。

    用下面的函数绘制:
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
最后出现如下画面,就算成功了:
OpenGL理解(一)_第1张图片













 

你可能感兴趣的:(OpenGL)