在图形学开发中,GLFW 是一个非常轻量级、跨平台的 C 语言开源库。它的核心任务非常纯粹:帮你处理窗口创建、操作系统上下文管理以及用户输入。

如果要写 Vulkan、OpenGL 或 OpenGL ES 程序,不能直接让代码在空无一物的操作系统上画画,必须先向 Windows、Linux 或 macOS 申请一个“窗口”,并捕获键盘鼠标的操作。GLFW 就是干这个脏活累活的。

1. 为什么需要 GLFW?(解决跨平台痛点)#

如果不使用任何第三方库,纯手写一个能在屏幕上弹出来的窗口,代码会变成这样:

  • 在 Windows 上: 调用 Win32 API,写一堆 WNDCLASSEX、CreateWindowEx,还要写一个极其繁琐的 WindowProc 消息循环来处理 Windows 系统的各种消息。
  • 在 Linux 上: 得去和 X11 (Xlib) 或者更现代的 Wayland 协议打交道,处理各种底层的 Display 和 Window 句柄。
  • 在 macOS 上: 得用 Objective-C 或 Swift 去调用 Cocoa 框架。

这会导致图形引擎还没开始写画三角形的代码,就已经被不同操作系统的平台初始化代码淹没了。

GLFW 的出现,把这些平台差异完全抹平了。 无论在什么操作系统上,创建窗口的代码都精简成了统一的一行:glfwCreateWindow。

2. GLFW 的核心职能#

GLFW 的功能非常克制和专一,它只管窗口和输入,不管怎么画画:

  • 窗口管理 (Window Management): 创建和销毁桌面窗口、处理窗口缩放、最大化/最小化、移动、多显示器全屏切换等。
  • 图形上下文管理 (Context Management): 配置和初始化 OpenGL/OpenGL ES 的上下文,或者专门为 Vulkan 提供跨平台的 Surface 创建支持。
  • 输入事件处理 (Input Handling): 极度简单的回调机制。可以轻松捕获键盘按键(按下、抬起、连发)、鼠标移动、鼠标点击、滚轮滚动,甚至还支持手柄/摇杆(Joystick)的输入。
  • 高精度计时器: 提供了一个跨平台的高精度时间函数 glfwGetTime(),非常适合用来计算游戏引擎的帧间隔时间(Delta Time)。

3. 它在 Vulkan 开发中的特殊生态位#

如果是在写 OpenGL,GLFW 会顺便创建好 OpenGL 的渲染上下文(Context)。但在 Vulkan 中,情况发生了一点变化。

Vulkan 是一个完全隐式无关的 API,它默认不感知窗口系统。我们在前面聊过,Vulkan 要想把画面扔到屏幕上,必须借助 WSI(窗口系统集成)扩展(比如 VK_KHR_surface)。

为了创建这个 VkSurfaceKHR,如果纯手写,需要针对 Windows 调用 vkCreateWin32SurfaceKHR,针对 Linux 调用 vkCreateXlibSurfaceKHR。

而 GLFW 为 Vulkan 提供了极好的原生支持,它直接提供了两个极简的 API,完美融入 Vulkan 初始化工作流:

① 剥离 OpenGL 上下文#

在创建窗口前,通过设置 Hint 告诉 GLFW:“我不需要你帮我初始化 OpenGL,我是给 Vulkan 用的”:

1glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 
2GLFWwindow* window = glfwCreateWindow(800, 600, "Vulkan Window", nullptr, nullptr);

② 自动获取 Instance 级别扩展#

我们在初始化 Vulkan VkInstance 时,需要开启平台特定的窗口扩展。GLFW 可以直接把当前操作系统需要的所有全局扩展名称打包:++

1uint32_t glfwExtensionCount = 0;
2const char** glfwExtensions;
3glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
4
5// 随后直接把 glfwExtensions 塞进 VkInstanceCreateInfo 的 enabledExtensionNames 中

③ 一键创建跨平台 Surface#

当选好显卡,准备把窗口和 Vulkan 绑定时,一行代码就能搞定原本需要分平台宏判断(#ifdef _WIN32)的 Surface 创建工作:

1VkSurfaceKHR surface;
2if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS)
3{
4    throw std::runtime_error("failed to create window surface!");
5}

4. GLFW vs SDL2 vs GLUT (横向对比)#

当然还有其他类似的库,它们之间的侧重点各有不同:

库名称

特点与定位

适用场景

GLFW

极其现代、轻量、纯粹。 只专注于窗口和输入,API 设计非常符合现代 C/C++ 程序员的习惯。没有臃肿的历史包袱。

现代图形学学习、自研现代渲染器(Vulkan/OpenGL)、游戏引擎底层窗口封装。

SDL2 / SDL3

巨无霸级别的多媒体库。 除了窗口和输入,它还自带音频播放、线程管理、文件 IO、甚至自带一个 2D 渲染引擎。

跨平台商业游戏开发、模拟器开发(因为它管得极宽)。

GLUT / FreeGLUT

古老、过时的化石库。 控制权在库本身(回调地狱),很难和现代渲染管线及多线程很好地融合。

工业界和现代开发已基本淘汰,仅在一些高校非常老旧的 OpenGL 1.x/2.x 课设中能看到。

总结#

GLFW 是现代图形学开发的“标准敲门砖”。它就像一顶安全帽,把各家操作系统底层最恶心、最繁琐的窗口创建和消息循环脏活全部挡在外面,让我们能够把 100% 的精力优雅地集中在 Vulkan 队列族、交换链、着色器和渲染管线的编写上。

原文:GLFW