【写在前面】
首先,要说明的是:这个系列将使用 glfw + glad 作为基本的窗口系统和 opengl 扩展,编译器则为 VS2013。
其次,本篇从获取、编译、链接 glfw + glad 库讲起,然后建立 glfw 环境,并保证它能够正确地创建 OpenGL 上下文并显示窗口,所以已经搭建好环境的可以直接跳过本篇。
【正文开始】
1. 配置 GLFW,从官网上下载:https://www.glfw.org/download.html,我这里建议直接下载二进制版本:
解压后得到:
接下来打开你的 VS目录下的VC文件夹,将 glfw-3.2.1.bin.WIN32\include\ 下的 GLFW 文件夹拷贝至 VC\include\ 下,然后根据你的 VS 版本选择相应的 lib-vc2013 (我的是2013),将其中的 glfw3.lib 和 glfw3dll.lib 拷贝至 VC\lib\ 下,而 glfw3.dll 放到C:\Windows\System32\ 下,至此,glfw 已经配置完成。
2. 配置 GLAD,glad 是运行时获取 OpenGL 函数地址的一个扩展库(类似于 glew ),首先还是从官网下载:https://glad.dav1d.de/,然后选择 gl 版本为 3.3 (后面可能为4.x),模式选择为核心模式:
点击最下方的生成按钮,得到:
点击 glad.zip,下载压缩文件,然后解压得到:
和 glfw 一样,将 include\ 下的 glad 文件夹和 KHR文件夹 拷贝至 VC\include\ 下,将 src\glad.c 拷贝至你的工程目录下,至此,glad 已经配置完成。
3. 新建一个项目,并链接 opengl 和 glfw 库,在属性->配置属性->链接器->输入->附加依赖项中加入 opengl32.lib 和glfw3.lib:
4. 开始创建第一个OpenGL窗口:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
这里直接上代码了,首先 #include <glad/glad.h> 和 #include <GLFW/glfw3.h>,注意:glad.h 必须在 glfw.h 之前包含(否则会重复包含),#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") 这一行不是必要的,我只是为了关闭 Consolas 窗口。
接下来是 main 函数:
int main(int argc, char **argv)
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(600, 500, "OpenGL-Start", nullptr, nullptr);
if (window == nullptr)
{
std::cerr << "Failed to Create GLFW Window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader(GLADloadproc(glfwGetProcAddress)))
{
std::cerr << "Failed to Initliaze GLAD";
glfwTerminate();
return -1;
}
glfwSetWindowSizeCallback(window, [](GLFWwindow *window, int width, int height)
{
glViewport(0, 0, width, height);
});
glfwSetKeyCallback(window, [](GLFWwindow *window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwTerminate();
});
while (!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
首先,我们在 main 函数中调用 glfwInit() 函数来初始化 glfw ,然后通过 glfwWindowHint() 函数来设置我们需要的OpenGL 版本为 3.3,以及使用核心模式( Core )。
接下来我们使用 glfwCreateWindow() 创建一个窗口指针,(噢忘了说,glfw 所有的函数都有注释,在其声明的上方可以看到),创建完窗口我们就可以使用 glfwMakeContextCurrent() 通知 glfw 将我们窗口的上下文设置为当前线程的主上下文了。
然后我们开始载入 OpenGL 的函数地址,通过 gladLoadGLLoader() 函数,它需要传入一个函数指针,glfw 提供的函数为glfwGetProcAddress(),这里直接把它传入。
再就是设置一些回调函数,glfwSetWindowSizeCallback() 和 glfwSetKeyCallback() ,它们在窗口大小改变和有按键事件时调用相应的函数,我这里在窗口大小改变时重置 OpenGL 视口,在按下 Esc 键时结束程序。
- glfwWindowShouldClose() 函数在我们每次循环的开始前检查一次GLFW是否被要求退出,如果是的话该函数返回
true
然后渲染循环便结束了,之后为我们就可以关闭应用程序了。- glfwPollEvents() 函数检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。
- glfwSwapBuffers() 函数会交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上。
最后,销毁窗口并结束程序,看一下效果图(只是一个灰绿色的空窗口而已):
【结语】
其实 glfw + glad 还是稍微有点繁琐的,所以使用起来难免有很多不方便的地方,后面我将会进行一些简单的封装,这样就能减少很多不必要的工作,然后接下来还是要把注意力转移到 render 中,毕竟那才是真正的核心。
整个系列教程的源码在我的 Github 上可以找到,地址是:https://github.com/mengps/OpenGL-Totural,会不定时进行更新~~