使用Visual Studio一劳永逸式配置OpenGL开发环境(GLFW3+GLAD)
引子
OpenGL版本众多,需要引入额外的第三方库才能很好的满足我们平时渲染的需求,对于刚开始学习的同学们比较麻烦。
我也多次遇到很多落后的配置教程,浪费了时间不说,也会自己技术和现代OpenGL的技术脱节。
在当前的时间点(2018年),学习OpenGL如果还从glBegin()和glEnd()那一套就太落伍了,这个教程是为了示范如何配置OpenGL3.3以上的环境。
另外推荐学习OpenGL的教程:LearnOpenGL,可能需要*,有中文翻译版。
如果你想快速的开始学习OpenGL,这里有配置好的环境:(直接使用VS2015及以上版本打开,Win7/10实测均可)
超链接:资源
(目录结构中用到的所有的头文件、lib、dll也都在该链接中)
目录结构
我们配置的这个环境不光是只负责存放代码和第三方lib,还有一些shader文件和资源文件,因此需要构建一个良好的目录结构。
配置完整的目录结构如下:
文件名 | 备注 |
---|---|
src | 存放代码 |
external\include | 第三方库的头文件,包含stb_image.h, glad.h, glfw.h ,assimp.h等 |
external\lib | 第三方库的lib |
external\dll | 第三方库的dll |
resources | 资源文件夹,里面包括image,model,audiod等文件夹 |
vsbuild | 项目文件夹,表示一个vs项目,打开该目录下的vsbuild.sln即可 |
重点介绍一下external\include下的文件夹
- glm OpenGL的数学库,定义了很多关于向量、矩阵的操作,简洁迅速。
- glfw 跨平台的对窗口资源的一个抽象库。
- glad 针对不同的显卡驱动有不同的OpenGL实现,glad帮助我们隐藏这些差别欢快的使用OpenGL。
- stb_image 轻量级的读取图片的库
- assimp 轻量级读取模型的库
可以说,我们包含了除了物理引擎和声音控制的所有常用组件。
现在我们从头开始构造这个目录结构。
首先找一个空白的文件夹,在其中新建如下目录结构:
这里我们不创建vsbuild,而是由vs来帮我们完成这件事情。
打开Visual Studio,新建一个空项目,项目名称为vsbuild,项目的地址为创建src、resources、external的同级目录:
创建完毕后:
接下来我们就要配置lib、include引入到我们的项目中。
右键vsbuild项目,打开属性页面:
找到C/C++ Genral
(注意,仅当你新建一个.cpp文件之后才会出现C/C++选项)
编辑右侧的附加目录:
注意 SolutionDir 是一个宏,表示的是vsbuild所在的目录,那么根据相对路径我们可以找到external\include。
(键入的信息是 $(SolutionDir)..\external\include)。
同理,选中Linker的General的附加库目录
打开编辑:
此外,还要打开Linker的Input的目录,输入下面的值:
表示我们需要
glfw3.lib
glad.lib
stb_image.lib
assimp.lib
这四个库,而这四个库的目录是在 $(SolutionDir)..\external\lib
(这里我把glad和stb_image编译成了静态库)
最后,因为assimp需要动态链接,我们需要把相应的dll引入到我们的项目中。
最简便的方法如下:
选中调试,编辑环境条目:
这行字符串的含义是在调试模式下,将external\dll目录临时添加到环境变量中,这样我们就可以成功的动态链接了。
在配置完毕后,粘贴下面的代码到Source.cpp,运行。
#include <glad\glad.h>
#include <glfw\glfw3.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif
// glfw window creation
// --------------------
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: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}
最后显示出如下窗口说明你配置成功了。