OpenGL 开发环境配置:Visual Studio 2017 + GLFW + GLEW
Step1:Visual Studio 2017
Why
开发环境,后面编译GLFW 和 GLEW也要用
How
这里使用的是Visual Studio 2017的 Community 版本,直接官网下载,注册,就可以免费用。
2017版本在安装界面里注意要勾选c++相关选项,否则默认不安装c++组件。
当然,较早版本(2015,2013,2010什么的)也是可以的。
Step2:CMake
Why
后面几步要用到的东西需要手动编译(用Visual Studio编译),但是下载下来的都是源码,并没有Visual Studio能直接打开的解决方案(.sln)或者项目(.vcproj)文件。
所以要下载Cmake帮忙创建VS工程文件。
How
下载地址:https://cmake.org/download/
我选择的是“Windows win64-x64 Installer”(64位Windows安装包),也可以选择 “Windows win32-x86 Installer”(32位Windows安装包)
默认安装即可。
Step3:准备文件夹
在硬盘某个目录(例如C盘根目录下)创建一个文件夹,用来放后面生成的一系列文件。
我在C盘根目录下创建了一个OpenGLStuff的文件夹,里面创建了两个空文件夹:libs和headers。
现在还没什么用,后面才需要用到。
Step4:GLFW
Why?
"GLFW是一个C写的专门用于OpenGL开发的库,它只提供把物体渲染到屏幕所需的必要功能。"
个人理解,主要是创建一个窗口,让我们可以使用OpenGL在窗口上绘制,还可以响应事件。
不用GLFW的话可以使用Win32、MFC、Qt等直接创建窗口。但是一般都推荐使用GLFW。
How?
下载地址:http://www.glfw.org/download.html
下载页面里提供了两类,一类是源码(Source Package 和 Git Repository),一类是已经编译好的windows平台的文件(32-bit Windows binary 和 64-bit Windows binary)。
选择后者会省事很多,不用折腾手动编译,下面的很多步骤就可以略过了,这里只说前者的手动编译方法。
选择Source Package 或者 Git Repository下载,我下载到的版本是glfw-3.2.1.
解压到本地的任意文件夹(不需要放在第三步创建的OpenGLStuff文件夹里,但是我仍放在了这里,这不是必须的,只是随意放的,编译完成后都可以删除掉)。
打开解压后的文件夹,打开其中的include,看到一个GLFW文件夹,把这个文件夹复制到第三步创建的文件夹OpenGLStuff/headers中。
打开Cmake(cmake-gui)图形化界面,Where is the source code: 选择解压到的文件夹路径,例如我的是: C:/OpenGLStuff/glfw-3.2.1。 Where to build the binaries: 任意找一个空的文件夹放就行,我这里按照其他教程的习惯,在glfw-3.2.1目录下创建了一个Build文件夹。
然后点下面的Configure按钮,这时弹出窗口提示选择创建什么工程,这里选择Visual Studio 15 2017,然后点“Finish”。
稍等片刻后出现很多红色的选项,不用管,直接点下面的“Generate”,一瞬间,VS工程就创建好了(在Where to build the binaries指定的目录下)。
可以直接点旁边的"Open Project"按钮,会自动调用VS2017打开刚才创建的工程(实际上是解决方案.sln)。如果不小心关闭了Cmake,也可以直接去build目录下找到GLFW.sln,双击打开。
打开后发现这个解决方案里包含的工程真不少,实际上我们需要的是GLFW3/glfw这个工程。右键这个工程,查看属性,可以看到预设的是编译成静态库文件,输出的路径以及文件名也都默认配置好了。
好了,只是看看,实际上不需要做任何修改,关闭这个窗口。
右键GLFW3/glfw工程,点击“生成”。稍过片刻,如果“输出”窗口中没有报错,应该可以正常生成一个glfw3.lib静态库文件。生成位置参看上图。
把这个文件拷贝到第三步创建的OpenGLStuff/libs文件夹里。
Step5:GLEW
Why?
摘抄的解释: "由于OpenGL是一种标准/规范,它需要由驱动制造商在驱动中来实现这份特定的显卡支持规范。因为有许多不同版本的OpenGL驱动,OpenGL的大多数函数在编译时(compile-time)是未知状态的,需要在运行时(run-time)来请求。这就是开发者的任务了,开发者获取他/她所需要的函数的地址,把它们储存在函数指针中以备后用。获取这些地址是依系统而定的"
这个过程很麻烦,而GLEW帮我们做了这个事情。所以我们需要GLEW。
一个替代方案是使用GLAD,过程简单,网上下载,不用编译,具体方案参考:https://learnopengl.com/#!Getting-started/Creating-a-window 这个页面中的GLAD部分。(更新: GLAD似乎有很多兼容问题,还是建议使用GLEW).这里就不细说了,这里只写死磕GLEW的过程……
HOW?
过程跟GLFW很类似。
下载地址:http://glew.sourceforge.net/
同样,官网提供了两种方案,一种是源码,一种是编译好的,当然,我们还是说最麻烦的办法,使用源码手动编译,所以我下载的是Source: ZIP,我下载到的版本是glew-2.1.0
下载后解压,同样,先把include文件夹下的GL文件夹拷贝到 OpenGLStuff/headers 下
我们看到解压后的文件夹里有build文件夹,打开一看,里面也有一些vs的工程,但是用2017打开都会出些问题,所以还是自己用cmake编译吧
打开cmake的图形化界面,过程类似GLFW,就不再重复了,只不过为了和其他工程区分开,我在build文件夹下新建了一个vs2017文件夹,把camke中的Where to build the binaries目录指定在这里,然后创建vs工程。
打开创建好的vs2017/glew.sln解决方案后,也有几个子工程,其中glew是生成动态链接库dll的工程,glew_s是生成静态链接库lib的工程,我们这里使用静态链接库。
分别在Debug和Release配置下构建glew_s,会生成两个lib文件,名称可能根据不同的版本有所差异,具体名称可以看工程属性的常规>输出目录以及目标文件名。
把生成的lib文件拷贝到OpenGLStuff/libs文件夹下。
Step6:创建测试工程
创建一个空的VC++工程,打开其属性设置页面。
如下进行设置:
设置完成后,向工程添加一个cpp文件,粘贴如下代码:
#include <iostream> // GLEW #define GLEW_STATIC #include <GL/glew.h> // GLFW #include <GLFW/glfw3.h> // Function prototypes void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); // Window dimensions const GLuint WIDTH = 800, HEIGHT = 600; // The MAIN function, from here we start the application and run the game loop int main() { std::cout << "Starting GLFW context, OpenGL 3.3" << std::endl; // Init GLFW glfwInit(); // Set all the required options for GLFW glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Create a GLFWwindow object that we can use for GLFW's functions GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr); if (window == nullptr) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); // Set the required callback functions glfwSetKeyCallback(window, key_callback); // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions glewExperimental = GL_TRUE; // Initialize GLEW to setup the OpenGL Function pointers if (glewInit() != GLEW_OK) { std::cout << "Failed to initialize GLEW" << std::endl; return -1; } // Define the viewport dimensions glViewport(0, 0, WIDTH, HEIGHT); // Game loop while (!glfwWindowShouldClose(window)) { // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions glfwPollEvents(); // Render // Clear the colorbuffer glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // Swap the screen buffers glfwSwapBuffers(window); } // Terminate GLFW, clearing any resources allocated by GLFW. glfwTerminate(); return 0; } // Is called whenever a key is pressed/released via GLFW void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { std::cout << key << std::endl; if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); }
保存,运行,即可看到一个窗口出现。
说明此前的配置都正确了。
说明
我们的过程采用的是glfw和glew的静态库lib文件,也可以采用动态链接库.dll文件,但是两者取其一即可