OpenGL学习记录(2) 显示窗口的绘制
Axin Lv1

本文是OpenGL学习记录的第二篇,在上一篇我们完成了GLFW以及GLEW的安装,和CMakeLIst文件的设置。在本篇中,将使用OpenGL进行窗口的绘制,以校验相关支持库是否能正常工作。

头文件的引入

由于使用了GLFW和GLEW,因此需要先引入相关头文件:

1
2
#include <GL/glew.h>
#include <GLFW/glfw3.h>

为了将有关信息打印出来还需引入输入输出库:

1
#include <iostream>

GLFW以及GLEW的初始化

在使用GLFW和GLEW之前,需要先将他们进行初始化操作,并且进行GLFW相关信息的配置。

这一系列操作我们在main函数的开始进行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main() {
// GLFW初始化
if(!glfwInit()){
printf("Init GLFW failed.");
return -1;
}
//
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

// GLEW初始化
glewExperimental = true;
if (glewInit() != GLEW_OK) {
printf("Init Glew failed.");
glfwTerminate();
return -1;
}

...

return 0;
}

其中,我们使用 glfwWindowHint函数配置当前代码所运行的OpenGL最高版本以及最小版本,并且使用核心模式。

在GLEW的初始化中需要先将glewExperimental置为true,然后再进行初始化。

窗口的创建

在初始化完毕后,我们可以使用glfwCreateWindow函数创建一个窗口对象,并且将此窗口设置为当前线程的主上下文。

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
int main() {
// GLFW初始化
if(!glfwInit()){
printf("Init GLFW failed.");
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

// init GLEW
glewExperimental = true;
if (glewInit() != GLEW_OK) {
printf("Init Glew failed.");
glfwTerminate();
return -1;
}

GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL window", nullptr, nullptr);

if (window == nullptr) {
printf("Open window failed.");
glfwTerminate();
return -1;
}

glfwMakeContextCurrent(window);

...

return 0;
}

其中,glfwCreateWindow函数的前两个参数表示窗口的宽和高,第三个参数表示窗口的标题,后两个参数在此暂时忽略。

视口及循环渲染

在创建完窗口后,还需设置视口(viewport)的大小,视口表示OpenGL渲染窗口的大小。

OpenGL幕后使用glViewport中定义的位置和宽高进行2D坐标的转换,将OpenGL中的位置坐标转换为你的屏幕坐标。例如,OpenGL中的坐标(-0.5, 0.5)有可能(最终)被映射为屏幕中的坐标(200,450)。注意,处理过的OpenGL坐标范围只为-1到1,因此我们事实上将(-1到1)范围内的坐标映射到(0, 800)和(0, 600)。

同时还可以增加一个回调函数,使得调整窗口大小后,视口的大小也相应做出改变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}

int main() {
...

glViewport(0, 0, 800, 600);

glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

return 0;
}

在完成视口的设置后,可以增加一个while循环使得窗口不会立即被关闭,从而在窗口中可以进行相应的画面渲染。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main() {
...

glViewport(0, 0, 800, 600);

glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

while (!glfwWindowShouldClose(window)) {
// 交换buffer
glfwSwapBuffers(window);
glfwPollEvents();
}

glfwTerminate();

return 0;
}

循环使用!glfwWindowShouldClose(window)作为判断条件,在我们每次循环的开始前检查一次GLFW是否被要求退出,如果是的话该函数返回true然后渲染循环便结束了,之后为我们就可以关闭应用程序了。

glfwPollEvents函数检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。

  • 本文标题:OpenGL学习记录(2) 显示窗口的绘制
  • 本文作者:Axin
  • 创建时间:2022-03-20 12:59:56
  • 本文链接:https://izhang.xin/2022/03/20/OpenGL学习记录(2) 显示窗口的绘制/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!