GLFW的使用说明

软件开发大郭
0 评论
/
28 阅读
/
5821 字
10 2023-02

1.编译GLFW生成LIB库文件

由于在Windows平台下初始化OpenGL非常麻烦,不仅需要创建OpenGL上下文,而且更麻烦的是调用OpenGL的GPU驱动的函数(具体多麻烦查看我的博文)。所以推荐使用第三方已经写好的库GLFW,类似的库还有GLUT。
GLFW是跨平台的抽象层,所以同一份代码在Windows和Linux下都可以运行。

GLFW提供了创建窗口,创建OpenGL上下文,管理键盘和鼠标的事件,甚至还提供多线程管理等跨平台的功能。功能越来越多了。

在GLFW官网上,找到他们的源码页,并下载到本地。

进入到glfw目录下

创建build文件夹,然后使用cmake构建出glfw项目文件。

cd glfw
mkdir build
cd build
cmake

用VS打开GLFW.sln

执行项目,执行完毕后,观察src/Release文件夹下多了我们需要的静态链接库文件glfw3.lib

2.使用GLFW库

1.以动态库方式使用

以后使用GLFW库时,在项目中添加包含的头目录和库目录

打开VS开发工具选择下面菜单:
头目录:

"Project>Properties>Configuration Properties>VC++ Directories>General> Include Directories”

添加

"D:\libs\glfw\include"

(上面路劲你根据自己情况填写)

2.以静态库方式使用

在这里我建议直接把静态链接库文件拷贝到项目下。

然后在项目代码中将库文件包含进去。

#pragma comment (lib, “glfw3.lib”)

这样生成的代码就包含静态库的内容了,移植时减少了bug的风险。

代码样例:

#include <GLFW/glfw3.h>
#include <gl/GL.h>
#include <iostream>

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glfw3.lib")

void error_callback(int code, const char* description);

int main(void)
{
    GLFWwindow* window;

    /* Handle GLFW Error */
    glfwSetErrorCallback(error_callback);

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

void error_callback(int code, const char* description)
{
    std::cout << code << ":" << description << std::endl;
}

3. GLFW的基本用法

GLFW初始化和终止

在使用GLFW大部分函数之前需要对GLFW库进行初始化,初始化的工作内容包括检查平台包含的特定功能。GLFW库初始化通过glfwInit进行。

if(!glfwInit())
{
	// handle initialization failure
}

如果初始化成功则会返回GLFW_TRUE、否则返回GLFW_FALSE。
在初始化之前,GLFW函数中只有下面几个函数可以使用,调用其他函数将会报GLFW_NOT_INITALIZED错误。

glfwGetVersion
glfwGetVersionString
glfwGetError
glfwSetErrorCallback
glfwInitHint

在应用程序退出之前应先释放GLFW库占用的系统资源。这可以通过glfwTerminate实现。2.2 GLFW错误处理
有些GLFW函数出错会返回对你解决错误没什么用的错误值,更有甚者有些函数还没返回值。所以处理GLFW的错误就需要独立的通道。在GLFW出现错误时会抛出错误代码,我们可以通过glfwGetError捕获。如下所示:

const char* description;
int code = glfwGetError(&description);
if(code!=GLFW_NO_ERROR)
{
	// display error message...

	// handle error ...
}

字符指针description会指向以UTF-8码形式存储的错误信息内存处。
然而更推荐的做法是设置错误回调函数glfwSetErrorCallback。这样每次glfw出现错误都会调用回调函数。

glfwSetErrorCallback(error_callback);

void error_callback(int code, const char* description)
{
    // display error...
}

创建窗口和OpenGL上下文

GLFW库通过glfwCreateWindow函数进行创建OpenGL上下文和创建窗口。创建之前若想定制自已想要的窗口和上下文而不是系统默认的,可通过window hint设置属性。你可以创建多个窗口和上下文,但是,仅被make current的窗口和上下文是起作用的。要想查询已经创建好的窗口和上下文属性,可通过glfwGetWindowAttrib、glfwGetWindowSize、glfwGetFramebufferSize查询。

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
if (!window)
{
    // Window or context creation failed
}

上面代码设置了OpenGL上下文的最低版本,如果机器不满足最低版本的限制,将会创建失败。
如果不在需要一个窗口了,摧毁它。

glfwDestroyWindow(window);

Make Context Current

使用OpenGL的API必须有而且只能有一个OpenGL上下文被设置成Current。
OpenGL上下文就是一个个状态机,显卡驱动程序只对Current上下文起作用。

GLFW设置current的语句和Windows的很像。

glfwMakeContextCurrent(window);

注:如果你是通过glad或gl3w来使用OpenGL,你就必需在使用它们之前拥有一个current context。

检查窗口关闭的标识

在GLFW中,每个窗口都有一个标识,用来标记窗口是否应该被关闭。当用户关闭了一个窗口,该标记就被设置成了1,所以窗口并没有被关闭,你需要时刻检查这个标记。
检查的方式是通过函数glfwWindowShouldClose。
返回的就是窗口关闭的标识值。

while (!glfwWindowShouldClose(window))
{
    // Keep running
}

你也可以设置窗口的回调函数,每次关闭窗口时都会触发该函数。

如下所示:

glfwSetWindowCloseCallback(window, window_close_callback);
...
void window_close_callback(GLFWwindow* window)
{
    glfwSetWindowShouldClose(window, 0);
}

键盘事件响应

GLFW提供了设置键盘响应的回调函数glfwSetKeyCallback,如下所示:

glfwSetKeyCallback(window, key_callback);

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GLFW_TRUE);
}

交换缓冲区与处理事件

GLFW创建的窗口有两个缓冲区,前缓冲区和后缓冲区,渲染是在后缓冲区上进行的,一旦缓冲区满了,就需要交换前后缓冲区,通过glfwSwapBuffers(window)。
事件发生时,并不是立即得到处理的,而是暂时挂起。这些挂起的事件需要定期处理,通常在缓冲区交换的每一帧后完成。

如下所示:

/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();

参考资料

https://www.glfw.org/docs/latest/quick.html#quick_steps

    暂无数据