本文档主要使用glfw和glad进行开发,主要是对文档简介 - LearnOpenGL CN (learnopengl-cn.github.io)的学习笔记
1、环境搭建
本文档主要在vs2022环境下,使用glfw和glad进行开发,在前文中列出了详细的环境配置参考。为了方便使用这里编写了一个简要快速的自用配置方法。在VS022内的程序包外,需依照前文的教程下载好glad。
(1)配置glfw
glfw库选择项目-管理NuGet程序包-浏览-搜索glfw下载即可。
(2)glad配置
将下载好的glad包解压放到项目文件夹中(其实放哪都一样)。下载完成后右键项目,选择属性-C/C++-附加包含目录,输入glad文件夹下的include文件夹所在位置。随后将glad-scr-glad.c文件复制到源文件下。输入头文件不报错那就是没问题。如果打开属性栏里面没有C/C++的属性,在源文件里面新建一个cpp就好了。
两位的头文件:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
基本环境搭建完毕。
2、窗口创建
(1)glfw初始化
glfwInit(); //初始化GLFW库
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //指定了OpenGL上下文的版本为3.3。
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //指定了OpenGL的核心(profile)模式,这意味着只能使用现代的OpenGL功能,而不是旧版功能。
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //苹果操作系统(macOS)上设置OpenGL的前向兼容性模式
#endif
(2)创建窗口
glfwCreateWindow
是 GLFW 库中用于创建窗口的函数。参数和功能如下:
①SCR_WIDTH
和 SCR_HEIGHT
: 这两个参数分别表示所创建窗口的宽度和高度。
②"LearnOpenGL"
: 这是窗口的标题,将显示在窗口的标题栏上。
③NULL
和 NULL
: 这两个参数分别表示要将窗口与另一个窗口共享上下文和帧缓冲,通常情况下我们不需要这样做,所以将它们设置为 NULL。
然后判断窗口创建是否成功,如果创建失败则打印报错,同时调用glfwTerminate()函数,用于释放 GLFW 库所分配的所有资源并终止 GLFW 库的运行。写到这一步调试时已经可以看见窗口,但会立刻退出关闭。
//创建窗口,五个参数分别为:窗口的宽度、高度、窗口标题、窗口模式(默认窗口、全屏窗口、窗口)、共享上下文(默认不共享)
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL) //检查是否创建窗口成功
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
(3)初始化GLAD
给GLAD传入用来加载系统相关的OpenGL函数指针地址的函数。
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
(4)窗口输入函数定义(可选)
①esc退出函数
这是 glfwGetKey()
函数的调用,它用于检查特定窗口中某个键是否被按下。第一个参数 window
是你要检查的窗口的指针,第二个参数 GLFW_KEY_ESCAPE
是指定要检查的键,这里是esc 键。
void processInput(GLFWwindow* window) //处理输入
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) //当按下ESC键时,关闭窗口
glfwSetWindowShouldClose(window, true);
}
②窗口回调函数
我们需要告诉OpenGL渲染窗口的尺寸大小,即视口(Viewport),这样OpenGL才只能知道怎样根据窗口大小显示数据和坐标。我们可以通过调用glViewport函数来设置窗口的纬度(Dimension)
void framebuffer_size_callback(GLFWwindow* window, int width, int height) { //通常需要调整视口(Viewport)的大小
glViewport(0, 0, width, height); //视口设置函数,别是视口的左下角坐标(通常为(0, 0)),以及视口的宽度和高度。
}
(5)循环窗口
这里需要注意 glfwSwapBuffers(window); 函数不能遗漏。
glfwSwapBuffers函数是GLFW库中的一个函数,用于交换前后缓冲区的内容,以显示最新的渲染结果。在 GLFW 中,默认情况下是使用双缓冲来避免闪烁和提供更平滑的图形渲染效果(也可以通过glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_FALSE);函数修改为单缓冲模式)。
双缓冲模式下,当我们使用图形库(如OpenGL)绘制场景时,所有的绘制操作都是在后台缓冲区进行的,而用户实际看到的图像则是前台缓冲区的内容。当一帧图像渲染完成后,通过交换缓冲区的操作,将后台缓冲区的内容交换到前台缓冲区,从而实现了平滑的图像显示,避免了闪烁和图像不完整的情况。
while (!glfwWindowShouldClose(window)) //这是一个GLFW函数,用于检查窗口是否应该关闭。当用户关闭窗口时,这个函数返回true,否则返回false。
{
processInput(window); //用于处理输入
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); //函数设置清除颜色,即在每次渲染循环开始时,OpenGL会用这个颜色来清除屏幕
glClear(GL_COLOR_BUFFER_BIT); //清除颜色缓冲区,以清除之前渲染的内容,以便进行新的渲染
glfwSwapBuffers(window); //交换缓冲区,将渲染结果显示到屏幕上
glfwPollEvents(); //这个函数用于处理窗口事件,比如键盘输入、鼠标移动等。
}
3、完整代码
完整代码如下:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
using namespace std;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
// 设置窗口大小
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main()
{
glfwInit(); //初始化GLFW库
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //指定了OpenGL上下文的版本为3.3。
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //指定了OpenGL的核心(profile)模式,这意味着只能使用现代的OpenGL功能,而不是旧版功能。
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //苹果操作系统(macOS)上设置OpenGL的前向兼容性模式
#endif
//创建窗口,五个参数分别为:窗口的宽度、高度、窗口标题、窗口模式(默认窗口、全屏窗口、窗口)、共享上下文(默认不共享)
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL) //检查是否创建窗口成功
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window); //设置当前窗口的上下文
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
//加载GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
while (!glfwWindowShouldClose(window)) //这是一个GLFW函数,用于检查窗口是否应该关闭。当用户关闭窗口时,这个函数返回true,否则返回false。
{
processInput(window); //用于处理输入
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); //函数设置清除颜色,即在每次渲染循环开始时,OpenGL会用这个颜色来清除屏幕
glClear(GL_COLOR_BUFFER_BIT); //清除颜色缓冲区,以清除之前渲染的内容,以便进行新的渲染
glfwSwapBuffers(window); //交换缓冲区,将渲染结果显示到屏幕上
glfwPollEvents(); //这个函数用于处理窗口事件,比如键盘输入、鼠标移动等。
//当我们使用图形库(如OpenGL)绘制场景时,所有的绘制操作都是在后台缓冲区进行的,而用户实际看到的图像则是前台缓冲区的内容。当一帧图像渲染完成后,通过交换缓冲区的操作,将后台缓冲区的内容交换到前台缓冲区,从而实现了平滑的图像显示,避免了闪烁和图像不完整的情况。
}
glfwTerminate(); //用于释放 GLFW 库所分配的所有资源并终止 GLFW 库的运行
return 0;
}
void processInput(GLFWwindow* window) //处理输入
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) //当按下ESC键时,关闭窗口
glfwSetWindowShouldClose(window, true);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) { //窗口大小变化回调函数
glViewport(0, 0, width, height); //视口设置函数,别是视口的左下角坐标(通常为(0, 0)),以及视口的宽度和高度。
}
运行结果如下,会显示一个绿色背景的窗口: