1.窗口
创建GLFW窗口对象
GLFWwindow* window = glfwCreateWindow(800, 600, "opengl",NULL,NULL);
- 800:width
- 600:height
- “opengl”:title
初始化GLEW
1 2 3 4 5 6 7
| glewExperimental = true;//设置 GLEW 的实验性模式 if (glewInit() != GLEW_OK) { printf("Init GLEW failed"); glfwTerminate(); return -1; }
|
窗口渲染框架:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #define GLEW_STATIC #include<GL/glew.h> #include<GLFW/glfw3.h> #include<cstdio> #include<iostream> void processInput(GLFWwindow* window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)//GLFW_KEY_ESCAPE:表示esc键,glfwGetKey:获取窗口中键的状态 { glfwSetWindowShouldClose(window, true); } } int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //创建GLFW窗口对象 GLFWwindow* window = glfwCreateWindow(800, 600, "opengl",NULL,NULL); glfwMakeContextCurrent(window);//将当前需要渲染的窗口设置为window //初始化GLEW glewExperimental = true;//设置 GLEW 的实验性模式 if (glewInit() != GLEW_OK) { printf("Init GLEW failed"); glfwTerminate(); return -1; }
glViewport(0, 0, 800, 600); while (!glfwWindowShouldClose(window))//判断窗口是否被关闭,未关闭则一直循环 { processInput(window); glClearColor(0.5f, 0.2f, 0.3f, 1.0f);//定义一种颜色(rgba四通道),每个通道取值为0~1. glClear(GL_COLOR_BUFFER_BIT); //GL_COLOR_BUFFER_BIT:颜色缓冲,glClear:将颜色缓冲填充成glClearColor设置的颜色 glfwSwapBuffers(window);//交换双缓冲,渲染先在后台缓冲区进行,之后再与前台缓冲区交换 //使用双缓冲是为了避免用户看到不完整的、中间过程的渲染结果 glfwPollEvents();//检查有没有触发什么事件(比如键盘输入、鼠标移动等) } glfwTerminate();//释放 GLFW 库分配的资源和清理 GLFW 环境 return 0; }
|
2.三角形
图形渲染管线:

2.1 定义并绑定VAO
VAO(Vertex Array Object):**保存了一系列的VBO配置和顶点属性指针,它负责告诉GPU,VBO中的信息到底该以几个为一组,对VBO起到解释的作用。
注:一个VAO可以对应多个VBO

1 2 3
| unsigned int VAO;//也可以是unsigned int VAO[n],n为VAO的个数 glGenVertexArrays(1, &VAO); glBindVertexArray(VAO);
|
2.2 定义并绑定VBO
VBO(Vertex Buffer Object):用于存储实际的顶点数据,可以包含顶点坐标、法线、颜色等信息。
1 2 3 4 5 6
| unsigned int VBO; glGenBuffers(1, &VBO); //绑定VBO glBindBuffer(GL_ARRAY_BUFFER, VBO); //数据传输到缓冲区,GL_STATIC_DRAW:静态绘制,顶点数据不会被修改 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
2.3 创建顶点着色器
顶点着色器:对每个输入顶点的坐标进行计算和变换
1 2 3 4 5 6 7
| //vertexShaderSource const char* vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "void main()\n" "{\n" " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" "}\0";
|
1 2 3 4 5 6
| //创建顶点着色器对象 unsigned int vertexShader; vertexShader = glCreateShader(GL_VERTEX_SHADER); //设置顶点着色器源代码并编译 glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); glCompileShader(vertexShader);
|
2.4 创建片段着色器
片段着色器:用于对每个屏幕上的像素(片段)进行处理,决定最终的颜色。
1 2 3 4 5 6
| //fragmentShaderSource const char* fragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "void main(){\n" "FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);}\n ";
|
1 2 3 4 5 6
| //创建片段着色器对象 unsigned int fragmentShader; fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //设置源代码并编译 glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); glCompileShader(fragmentShader);
|
2.5 创建着色器程序
1 2 3 4 5 6
| unsigned int shaderProgram; shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); //将附加到着色器程序的各个着色器连接在一起,以形成一个完整的着色器程序。 glLinkProgram(shaderProgram);
|
2.6 配置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 \* sizeof(float), (void\*)0);
0
: 指定顶点着色器中的顶点属性位置(location)。在顶点着色器代码中,使用 layout(location = 0)
来定义的。
3
: 指定每个顶点属性包含的分量数量,这里是3,表示三维坐标x、y、z。
GL_FLOAT
: 指定顶点属性的数据类型,这里是浮点数。
GL_FALSE
: 指定是否要归一化数据,对于浮点数数据,通常设置为GL_FALSE。
3 * sizeof(float)
: 指定相邻顶点属性之间的偏移量(以字节为单位)。这里表示每个顶点的大小为3个浮点数,所以偏移量为3 * sizeof(float)。
(void*)0
: void*无类型指针,指定第一个顶点属性在缓冲区中的偏移量。这里表示从缓冲区的开头开始使用。
glEnableVertexAttribArray(0);
:启用顶点属性数组,OpenGL会按照之前配置的顶点属性指针从缓冲区中读取数据。
1 2
| glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0);
|
2.7 绘制三角形
glDrawArrays(GL_TRIANGLES, 0, 3);
:
GL_TRIANGLES
表示渲染的图元类型,这里是三角形。
0
是起始顶点的索引,表示从顶点数组的第一个顶点开始渲染。
3
是顶点的数量,表示渲染三个顶点。
1 2 3
| glUseProgram(shaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3);
|
2.8 绘制多边形
注意:opengl的绘制顺序是逆时针(右手系),当启用背面剔除时,背面将不可见。
1 2
| glEnable(GL_CULL_FACE); glCullFace(GL_BACK);
|
EBO(索引缓冲对象):用于优化和节省内存
1 2 3 4
| unsigned int indices[] = { 0, 1, 2, // 第一个三角形 2, 1, 3 // 第二个三角形 };
|
1 2 3 4 5
| //定义并绑定EBO unsigned int EBO; glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
绘制:
1 2 3 4 5
| glUseProgram(shaderProgram); glBindVertexArray(VAO); /*glDrawArrays(GL_TRIANGLES, 0,3);*/ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
2.9 线框模式
启用线框模式:
1
| glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
取消线框模式:
1
| glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|