Vulkan是一个现代的图形和计算API,它为跨平台的高性能实时3D图形提供了底层访问。然而,Vulkan的学习曲线非常陡峭,因为它的API冗长,并且需要立即理解一些复杂的概念,以及许多第三方辅助库可能会让大多数人感到不知所措。
在寻找示例和教程的过程中,惊讶地发现几乎没有什么资源,直到找到了Sascha Willems编写的一套优秀的教程。事实上,它们如此出色,认为这可能是为什么很少有人尝试编写类似教程的原因。无论如何,决定通过这些基础示例,重写它们,同时创建一个辅助库来抽象掉所有常见的代码。
当时,有整理代码并在这里发布文章的想法,但像许多想法一样,它被现实所取代。去年有一些空闲时间,所以重新审视了代码,整理了它,并为示例添加了一些基本的描述,这就是这篇文章。
Vulkan Playground是一个高级库,它使得编写简单的着色器变得非常容易,并且将Vulkan对象封装到C++类中,这有助于看到Vulkan API各部分之间的交互。
它不是一个功能完整的3D库或超级优化的生产级代码。
要了解它能够做什么,最简单的方法是查看Sascha的基础示例集。原始示例很棒,因为所有代码基本上都在一个文件中,这对初学者来说可能有点多,而在这里,这些示例被分解成子步骤,并附有简单的解释。每个示例只有一两页代码,使得很容易看出示例背后的高级思想。
安装最新的Windows Vulkan SDK。
安装Visual Studio 2019社区版,确保选择了C++。
运行Visual Studio 2019并选择“克隆仓库”。然后输入位置为“https://github.com/SuperflyJon/VulkanPlayground”,更改路径(如果需要),然后点击“克隆”。
注意:可能需要在“工具”->“选项”->“CMake设置页面”中设置名为“从不自动运行配置步骤”的选项,以阻止Visual Studio尝试在文件上运行cmake。
或者,手动克隆仓库,并从examples子文件夹中打开Examples.sln文件。
按F5或选择一个“调试/开始…”菜单选项来构建和运行示例。
打开Visual Studio 2019,选择“创建新项目”,在语言过滤器中选择“C++”,选择“控制台应用”,然后按“下一步”。
在下一个对话框中,输入一个名称,例如“MyTriangle”,并选择一个存储文件的位置,然后按“创建”。
现在,通过将下拉菜单从“x86”更改为“x64”来更改配置为64位。
从主菜单中选择“视图/其他窗口/属性管理器”,以显示属性管理器窗口。右键单击此窗口中的MyTriangle项目,并选择“添加现有属性表…”。
浏览到拥有Vulkan Playground库代码的位置下的Scripts文件夹,并选择VulkanPlayground.props文件。
现在用以下代码替换编辑器中的代码:
#include <VulkanPlayground/Includes.h>
int main() {
class HelloWorldApp : public VulkanApplication {
void UpdateScene(VulkanSystem& system, float) override {
PrintString(10, 50, U"Hello, World!");
}
} app;
WindowSystem::RunWindowed(200, 100, "Hello World!", app);
}
如果尝试构建此代码,代码应该可以编译,但会抱怨未解析的外部引用,现在将添加来自Vulkan Playground库的代码。
从主菜单中选择“文件/添加/现有项目…”。浏览到Vulkan Playground源位置,并从VulkanPlaygroundLibrary文件夹中选择VulkanPlayground.vcxproj项目文件。
现在需要链接到该库。右键单击三角形项目下的“引用”项,并选择“添加引用…”,点击复选框,然后点击“确定”。
现在按F5构建并运行此测试,应该得到一个带有“Hello world!”的窗口:
现在知道事情可以工作了,用以下代码替换测试代码,它将绘制一个三角形:
#include <VulkanPlayground/Includes.h>
int main() {
class TriangleApp : public VulkanApplication {
void SetupObjects(VulkanSystem& system, RenderPass& renderPass, VkExtent2D workingExtent) override {
pipeline.LoadShader(system, "Triangle");
pipeline.SetupVertexDescription({ { 1, Attribs::Type::Position, VK_FORMAT_R32G32_SFLOAT} });
CreatePipeline(system, renderPass, pipeline, workingExtent, "TriangleSimple");
system.CreateGpuBuffer<float>(system, vertexBuffer, { -0.8f, 0.8f, 0.0f, -0.8f, 0.0f, -0.8f }, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, "Triangle data");
}
void DrawScene(VkCommandBuffer commandBuffer) override {
pipeline.Bind(commandBuffer);
vertexBuffer.Bind(commandBuffer);
vkCmdDraw(commandBuffer, (uint32_t)vertexBuffer.GetBufferSize() / pipeline.GetStride(), 1, 0, 0);
}
Pipeline pipeline;
Buffer vertexBuffer;
} app;
WindowSystem::RunWindowed(300, 200, "Triangle", app);
}
这段代码相当直接,SetupObject()首先加载三角形着色器文件(很快就会创建)。然后示例设置了期望传递浮点数对的管线,数据在这个示例中是硬编码的。DrawScene()绑定管线和缓冲区,并调用Vulkan命令vkCmdDraw来绘制三角形。
现在添加着色器文件。右键单击解决方案资源管理器中的MyTriangle项目,并选择“添加/新建项…”。将“Source.cpp”替换为“Triangle.vert”在名称框中,然后点击“添加”。
将以下简单的顶点着色器代码粘贴到编辑器中:
#version 450
layout(location = 1) in vec2 inPosition;
void main() {
gl_Position = vec4(inPosition, 0.0, 1.0);
}
重复这些步骤添加另一个名为Triangle.frag的文件,并在该文件中输入以下代码:
#version 450
layout(location = 0) out vec4 outFragColour;
// 0 = colour attachment number
void main() {
outFragColour = vec4(vec3(0.8), 1.0);
}
现在再次运行项目(F5),应该看到第一个Vulkan三角形:
如果正在运行调试构建,应该在控制台窗口中看到大量的输出,暗示着幕后正在进行的一些工作。
如果在上述说明中遇到麻烦,那么在源下载中有一个示例项目,只需打开Example\Triangle文件夹中的Triangle.sln文件并点击“运行”,应该看到一个三角形。
可以使用这个简单的三角形示例作为创建自己的Vulkan示例的起点。
有一些第三方库正在使用,完整详细信息在外部文件夹中的details.txt文件中。
这里有一个深入的Vulkan API入门教程,如果想深入了解细节。