* 本文用作学习learnOpenGL.com的备忘
1. Hello Triangle
- Rendering pipeline(蓝色部分可编写shader程序):
- some primitives:
GL_LINES
: Vertices 0 和1 是一条线,Vertices 2 and 3 是一条线,依次类推。GL_LINE_STRIP
: 所有相邻点组成一条线。GL_LINE_LOOP
: 相邻点连线,最后一个点和第一个点也连线。GL_TRIANGLES
: Vertices 0, 1, and 2 成三角形,Vertices 3, 4, and 5成三角形,以此类推。GL_TRIANGLE_STRIP
: 所有相邻三个点组成三角形,举例:(0,1,2)(1,2,3) … -GL_TRIANGLE_FAN
: 第一个点和剩余任意两个相邻点组成三角形,举例:(0, 1, 2) (0, 2, 3), (0, 3, 4)…
- Vertex buffer objects (VBO) 存储GPU上的vertices。使用VBO可以实现向GPU批量传送数据。
- OpenGL中每个buffer都有一个唯一ID,使用
glGenBuffers
给一个buffer生成一个ID。之后需要使用glBindBuffer
绑定该buffer的类型。最后使用glBufferData
向buffer传送数据:
unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData
的最后一个参数:
GL_STATIC_DRAW
: 数据不经常变化GL_DYNAMIC_DRAW
: 数据经常变化GL_STREAM_DRAW
: 每次render数据都变化
- 要使用shader,需要创建shader对象并赋予一个ID,声明其源码字符串并编译:
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
- 将多个shader链接到一个shader program对象。首先创建该对象,然后链接:
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
- 每次需要render时,使用
glUseProgram
执行shader program:
glUseProgram(shaderProgram);
- 使用
glVertexAttribPointer
声明解析vertices数据的方式,然后使用glEnableVertexAttribArray
启用vertices数据:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
其中:
- glVertexAttribPointer
和glEnableVertexAttribArray
的第一个参数指明shader中layout
的location
- glVertexAttribPointer
的第二个参数指明vertex attribute元素个数,比如此处vertex attribute是个vec3
(代表x,y,z坐标),那么填3
- 第三个参数为数据类型;第四个不解释;第五个为数据量;第六个为offset
10. OpenGL中强制使用vertex array object (also known as VAO) 来存储解析方式(也就是必须要有VAO)。假设没有不这样做,每次render都需要一大坨代码:
// 0. copy our vertices array in a buffer for OpenGL to use
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 1. then set the vertex attributes pointers
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 2. use our shader program when we want to render an object
glUseProgram(shaderProgram);
// 3. now draw the object
someOpenGLFunctionThatDrawsOurTriangle();
有了VAO,可以配置一次,以后每次render之前绑定VAO即可。
生成VAO方法如下:
unsigned int VAO;
glGenVertexArrays(1, &VAO);
配置VAO方法如下:
// ..:: Initialization code (done once (unless your object frequently changes)) :: ..
// 1. bind Vertex Array Object
glBindVertexArray(VAO);
// 2. copy our vertices array in a buffer for OpenGL to use
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 3. then set our vertex attributes pointers
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
以后每次需要render时,只需要:
// ..:: Drawing code (in render loop) :: ..
// 4. draw the object
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
someOpenGLFunctionThatDrawsOurTriangle();
- element buffer object(EBO)用于使用数据的索引来render。
生成EBO方法,并绑定数据方法如下:
unsigned int EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
- 在绑定VAO之后绑定的VBO和EBO被认为是该VAO的VBO和EBO,所以现在render的代码如下:
// ..:: Initialization code :: ..
// 1. bind Vertex Array Object
glBindVertexArray(VAO);
// 2. copy our vertices array in a vertex buffer for OpenGL to use
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 3. copy our index array in a element buffer for OpenGL to use
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 4. then set the vertex attributes pointers
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
[...]
// ..:: Drawing code (in render loop) :: ..
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
glBindVertexArray(0);