原博主博客地址:http://blog.csdn.net/qq21497936
本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78884842
《OpenGL学习笔记(五):创建OpenGL工程模板前的所有准备工作》:
http://blog.csdn.net/qq21497936/article/details/78778078
《OpenGL学习笔记(六):创建第一个VS2015 OpenGL工程模板(与平台无关)》:
http://blog.csdn.net/qq21497936/article/details/78786844
OpenGL学习笔记(七):创建第一个Qt5.9.3 OpenGL工程模版(与平台无关)
前话
前面介绍了OpenGL相关知识,开始动手实现,前面两章节说明的环境是Microsoft Visual Studio 2015,本章节目标仍是建立一个最简单的OpenGL工程,包括GLFW库,GLAD,Qt配置。
在QtCreator上运行一个最简单的OpenGL的程序。
GLFW库
GLFW是一个专门针对OpenGL的C语言库,它提供了一些渲染物体所需的最低限度的接口。它允许用户创建OpenGL上下文,定义窗口参数以及处理用户输入。
下载GLFW库
源代码下载地址:http://download.csdn.net/download/qq21497936/10154537
使用cmake编译
CMake是一个工程文件生成工具。用户可以使用预定义好的CMake脚本,根据自己的选择(像是Visual Studio, Code::Blocks, Eclipse)生成不同IDE的工程文件。
Cmake下载地址:http://download.csdn.net/download/qq21497936/10154545
解压后直接使用cmake-gui.exe
解压之前下载的glfw-3.2.1,然后再目录下建立一个C:/qt-glfw-3.2.1-build文件夹,该文件夹是我们编译成目标文件所存放的文件夹。
CMake需要一个源代码目录和一个存放编译结果的目标文件目录,如下图:
点击Configure(设置)按钮,让CMake读取设置和源代码,选择我们的工程目标生成为MinGW Makefiles。
CMake配置会报错,报错和解决方式如下图,添加QMAKE_MAKE_PROGRAM环境变量
这里我们使用默认设置,再次点击Configure(设置)按钮保存设置。保存之后,点击Generate(生成)按钮。
可能出现的错误:丢失libwinpthread-1.dll
在mingw文件夹的bin下有这个库(也可去网上下载),将其拷贝到C:/windows/system32下(尽管本人是64位系统),使用管理员打开cmd,若未使用管理员注册时会出现注册失败不兼容等信息,一定要使用管理员。
regsvr32 libwinpthread-1.dll
点击Generate(生成)按钮,生成的工程文件夹将会在C:/qt-glfw-3.2.1-build文件夹中,如下图:
编译
打开cmd,切换到build目录下,然后使用ming32-make即可。
特别注意,编译出来的东西与之前vs编译出来的完全不一样,包括目录结构,本次编译出来的文件内容如下,libglfw3.a即是我们要的库:
GLAD库
OpenGL只是一个标准/规范,具体的实现是由驱动开发商针对特定显卡实现的。由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。所以任务就落在了开发者身上,开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用。取得地址的方法因平台而异。
// 定义函数原型 typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*); //找到正确的函数并赋值给函数指针 GL_GENBUFFERS glGenBuffers = (GL_GENBUFFERS)wglGetProcAddress("glGenBuffers"); // 现在函数可以被正常调用了 GLuint buffer; glGenBuffers(1, &buffer);
可以看到代码非常复杂,而且很繁琐,我们需要对每个可能使用的函数都要重复这个过程。幸运的是,有些库能简化此过程,其中GLAD是目前最新,也是最流行的库。
配置GLAD
GLAD是一个开源的库,它能解决我们上面提到的那个繁琐的问题。GLAD的配置与大多数的开源库有些许的不同,GLAD使用了一个在线服务。在这里我们能够告诉GLAD需要定义的OpenGL版本,并且根据这个版本加载所有相关的OpenGL函数。
步骤5后会自动下载,下载解压后,将glad的include目录加入到包含头文件路径中,将src源文件直接添加现有项到当前工程中。
建立Qt C++空项目
新建一个工程Demo,创建项目选择“其他项目”- “Emptyqmake Project”建立工程(what?连main.cpp也没有,就是这样的,需要我们鼠标右键点击项目添加C++文件),在空工程中加入main.cpp源文件(what?不一定要取名main.cpp,随便取个符合规则名字,关键是里面要加入main函数,main函数才是程序的入口)。
导入GLFW头文件和库
打开.pro文件,添加头文件和库文件,如下图
main.cpp中输入源码,源码如下:
#include <iostream> #include <process.h> #include <GLFW/glfw3.h> #include <glad/glad.h> #include <windows.h> void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } // 在GLFW中实现一些输入控制,使用GLFW的glfwGetKey函数 void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } int main() { glfwInit(); /* 请确认您的系统支持OpenGL3.3或更高版本,否则此应用有可能会 崩溃或者出现不可预知的错误。如果想要查看OpenGL版本的话, 在Linux上运行glxinfo,或者在Windows上使用其它的工具(例如 OpenGL Extension Viewer)。如果你的OpenGL版本低于3.3,检 查一下显卡是否支持OpenGL 3.3+(不支持的话你的显卡真的太老 了),并更新你的驱动程序,有必要的话请更新显卡。 */ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 如果使用的是Mac OS X系统,你还需要加下面这行代码到你的 // 初始化代码中这些配置才能起作用 //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 创建一个窗口对象,这个窗口对象存放了所有和窗口相关的数据, // 而且会被GLFW的其他函数频繁地用到 // glfwCreateWindow函数需要窗口的宽和高作为它的前两个参数。 // 第三个参数表示这个窗口的名称(标题),最后两个参数暂时忽略。 // 函数会返回一个GLFWwindow对象,我们会在其它的GLFW操作中使用到。 GLFWwindow* window = glfwCreateWindow(800, 600, "QQ:21497936", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); // GLAD是用来管理OpenGL的函数指针的,所以在调用任何OpenGL的函数 // 之前我们需要初始化GLAD。 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } // 还需要注册这个函数,告诉GLFW我们希望每当窗口调整大小的时候调用这个函数。 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // 我们必须告诉OpenGL渲染窗口的尺寸大小,即视口(Viewport), // 这样OpenGL才只能知道怎样根据窗口大小显示数据和坐标。 // 可以通过调用glViewport函数来设置窗口的维度(Dimension)。 // OpenGL幕后使用glViewport中定义的位置和宽高进行2D坐标的转 // 换,将OpenGL中的位置坐标转换为你的屏幕坐标。例如,OpenGL // 中的坐标(-0.5, 0.5)有可能(最终)被映射为屏幕中的坐标(200,450)。 // 注意,处理过的OpenGL坐标范围只为-1到1,因此我们事实上 // 将(-1到1)范围内的坐标映射到(0, 800)和(0, 600)。 glViewport(0, 0, 800, 600); // 在我们主动关闭它之前不断绘制图像并能够接受用户输入。因此, // 需要在程序中添加一个while循环,我们可以把它称之为渲染循环(Render Loop), // 它能在我们让GLFW退出前一直保持运行。 while (!glfwWindowShouldClose(window)) { // 捕捉输入 processInput(window); // 清空颜色缓冲 // 添加渲染指令,背景RGBA的A不生效 glClearColor(1.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); // 检查并调用事件,交换缓冲(执行交换缓存才会更新新数据到界面) glfwSwapBuffers(window); glfwPollEvents(); } // 当渲染循环结束后我们需要正确释放/删除之前的分配的所有资源。 glfwTerminate(); return 0; }
编译时遇到错误,找不到一些函数:
原因是使用到gdi库,解决方法是,添加系统GDI库:
模版运行效果
模版下载地址
http://download.csdn.net/download/qq21497936/10171209
原博主博客地址:http://blog.csdn.net/qq21497936
本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78884842