创建一个窗口
窗口
在创建窗口之前,首先需要使用glfwInit()来初始化GLFW库,若成功返回GLFW_TRUE,失败返回GLFW_FALSE。如果该函数失败,它还会在返回之前调用glfwTerminate()。如果成功,你应该在应用程序退出之前手动调用glfwTerminate()。在成功初始化但应用程序尚未终止之前,对该函数的额外调用将立即返回GLFW_TRUE。
初始化之后,应使用glfwWindowHint()来配置GLFW。它有两个参数,第一个是需要配置的选项的名称,第二个是选项的值。一般会选择配置GLFW的版本和使用模式。
接下来使用glfwCreateWindow()创建一个窗口对象。

glfwCreateWindow()的前三个参数分别是窗口的宽度、高度和标题;第四个参数是用于全屏显示的监视器(可以为NULL,表示窗口化),第五个参数是与新创建的窗口共享资源的窗口(可以为NULL)。如果窗口创建成功,返回一个指向GLFWwindow对象的指针,否则返回NULL。
创建好窗口之后,我们就需要使用函数glfwMakeContextCurrent()把这个窗口的上下文设置为当前线程的主上下文(一个应用程序可以同时创建多个窗口,每个窗口都有一个对应的上下文)。

视口
视口(Viewport)是指OpenGL渲染的目标窗口上的可见区域。我们用glViewport()设置视口的大小和位置。

注意:OpenGL的宽和高的坐标范围都只有-1到1,它使用glViewport进行位置坐标和屏幕坐标的转换。
当用户改变窗口大小时,视口也应该被调整。glfwSetFramebufferSizeCallback()用于设置帧缓冲大小(帧缓冲是用于存储渲染的图像的内存区域,即绘制区域的高和宽)变化时的回调函数。

回调函数callback可以这样定义:

渲染循环
我们需要程序在关闭前不断绘制图像并能够接受用户输入。因此,需要在程序中添加一个while循环,即渲染循环(Render Loop)。

glfwPollEvents的作用是检查并处理当前窗口的所有待处理事件,例如键盘输入、鼠标输入、窗口大小调整等。
glfwSwapBuffers的作用是交换双缓冲区的内容。在双缓冲机制中,绘图操作实际上是在一个后台缓冲区中进行的,而不是直接在屏幕上绘制。当绘制完成后,glfwSwapBuffers会将后台缓冲区的内容与前台缓冲区进行交换,使得绘制结果能够显示在屏幕上。
——————————————————————————————————————
单缓冲(Single Buffer):在单缓冲机制中,绘制操作直接在屏幕上进行,而不是在后台缓冲区。生成的图像不是一下子被绘制出来的,而是按照从左到右,由上而下逐像素地绘制而成的。这导致绘制较慢或复杂的图形时,可能会产生可见的闪烁现象。这是因为在绘制一帧完成之前,用户可能会看到绘制过程中的不完整或部分绘制的图像。此外,如果在屏幕上的绘制操作正在进行时,用户对窗口进行了移动、最小化或最大化等操作,可能会导致图像撕裂。
双缓冲(Double Buffer):双缓冲使用两个缓冲区——前台缓冲区和后台缓冲区。绘制操作首先在后台缓冲区进行,然后通过交换缓冲区,将后台缓冲区的内容复制到前台缓冲区并显示在屏幕上。这样可以避免闪烁、撕裂等问题,提供更平滑更真实的绘图效果。
——————————————————————————————————————
退出程序
渲染循环结束后需要正确释放和删除已分配的所有资源——通过调用函数glfwTerminate()。