和GLFW交互

Vulkan可以在完全没有窗口的情况下工作,通常,在离屏渲染时会这样做。但一般而言,还是需要一个窗口来显示渲染结果给用户。接下来,我们要完成的就是窗口相关操作。

首先替换代码中的#include <vulkan/vulkan.h>为:

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

上面的代码将GLFW库的定义包含进来,而GLFW库会自动包含Vulkan库的头文件。接着,我们添加一个叫做initWindow的函数来初始化GLFW,并在run函数中调用它:

void run() {
        initWindow();
        initVulkan();
        mainLoop();
        cleanup();
    }

private:
    void initWindow() {

    }

initWIndow函数首先调用了glfwInit函数来初始化GLFW库,由于GLFW库最初是为OpenGL设计的,所以我们需要显式地设置GLFW阻止它自动创建OpenGL上下文:

glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

窗口大小变化地处理需要注意很多地方,我们会在以后介绍它,暂时我们先禁止窗口大小改变:

glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);

接着,我们添加了一个GLFWwindow* window变量存储我们创建的窗口句柄:

window =glfwCreateWindow(800, 600, "Vulkan", nullptr, nullptr);

glfwCreateWindow函数的前三个参数指定了要创建的窗口的宽度,高度和标题。第四个参数用于指定在哪个显示器上打开窗口,最后一个参数与OpenGL相关,对我们没有意义。

硬编码窗口大小不是一个好习惯,所以我们定义了两个常量,以便之后可以方便地修改它们:

const int WIDTH = 800;
const int HEIGHT = 600;

现在,我们地initWindow函数看起来应该像这样:

void initWindow() {
    glfwInit();

    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);

    window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
}

为了确保我们的程序在没有发生错误和窗口没有被关闭的情况下可以一直运行,我们在mainLoop函数中添加了下面的事件循环:

void mainLoop() {
    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();
    }
}

上面的代码应该非常直白,每次循环,检测窗口的关闭按钮是否被按下,如果没有被按下,就执行事件处理,否则结束循环。在之后的章节,我们会在这一循环中调用渲染函数来渲染一帧画面。

一旦窗口关闭,我们就可以开始结束GLFW,然后清除我们自己创建的资源,这在cleanup函数中进行:

void cleanup() {
    glfwDestroyWindow(window);

    glfwTerminate();
}

至此,我们就编写完成了一个可以使用Vulkan API的窗口程序骨架。

本章节代码:

C++:

https://vulkan-tutorial.com/code/00_base_code.cpp