OpenGL学习笔记(七):创建第一个Qt5.9.3 OpenGL工程模版(与平台无关)
原博主博客地址: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
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;
}
编译时遇到错误,找不到一些函数:
原博主博客地址:http://blog.csdn.net/qq21497936
本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78884842
上一篇: C语言基础之字符串