首页

简介

EasyVulkan是一个面向懒人的Vulkan中文教程系列,旨在帮助Vulkan学习者轻松入门,避免踩坑(所谓的面向懒人就是指我帮你把坑先踩了)。
这套教程使用有条理的面向对象编程,或者说,通过对Vulkan中的各种对象和过程进行封装,提高代码复用率,避免过于冗长的代码,以期降低学习难度。
学习这套教程前,你需要自备C++基础及高中程度的数学及英语知识。

这不是技术美术教程,也不是计算机图形学教程(至少目前如此)。

示例代码见我的Github。直接上的解决方案(VS2022,Win10)。
左侧搜索功能仅支持英文关键词。

Why Vulkan?

Vulkan是一个较为底层的图形API,底层一词意味着它难学,但又能提供比诸如OpenGL、DirectX11等高级图形API更出众的性能(但也不可一概而论,在一些简单的场景中高级图形API可能会跑出更高的效率)。
Vulkan相比现有的其他偏底层的图形API(Windows专用的DirectX12、苹果系OS专用的Metal),其代码有着能跨平台编译的优势,但并不保证Vulkan程序总是能与用平台特定图形API写的程序性能相当(尽管这一差距可以非常小或没有差别)。

用Vulkan能干什么?
搞渲染,比如开发渲染引擎、开发GUI等。
用Vulkan能做游戏吗?
能!只不过你要造一整套渲染引擎的轮子,啃一堆微积分和线性代数式子,做一系列其他纷繁复杂的编程。

目录

前两章是Step By Step入门教程,很长,初学者请耐心看完。
然后直接阅读Ch6和Ch7(建议先七后六),按要求阅读Ch3~5。

第四章 着色器

第八章 简单示例

关于转载和联系方式

暂请不要转载原文,在写完前述各章节前可能会不断修改细节。
也不要fork成公有仓库(包括到Gitee/GitCode的情況)。

联系请:
1.捉虫/答疑,发Issue,开新的,或者发在issue#7
2.反馈/交流/答疑,发Discussion。

欢迎以下形式的捉虫:
1.解释错误或代码逻辑错误
2.前言不搭后语
3.突然冒出毫无解释的代码
4.妨碍理解的错别字、多字漏字
一些文本着色错误我会在日后闲得没事时慢慢改正。

更新履历

  • 24.07.02 修正Ch3-2 图像与缓冲区中,“在内存区不具有host-coherent属性时,调整映射范围”的代码(感谢issue#7中的反馈)。


  • 24.06.25 Ch8-5 sRGB色彩空间与开启HDR完成(就差一点点内容却拖了很久...),除了末尾的内容外,增加了关于scRGB的说明。


  • 24.06.04 Ch1-3和Ch1-4页面上汇总的代码中,因复制粘贴错误漏了graphicsBase::Base().AddDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);,补上。


  • 24.05.25 修正05.12更新的错误:即时帧中的fence.WaitAndReset();应该放渲染循环开头而非最后(批量修改需谨慎啊!),并修正获取到的交换链图像索引是乱序时的说明(总结:乱序的话就不必考虑即时帧了)。


  • 24.05.12 Ch3-8 查询完成。

  • 24.05.12 fence.WaitAndReset();的位置移动到了渲染循环最后,原因见Ch2-1 Rendering Loop

  • 24.05.12 修正即时帧代码中因复制粘贴错误多出的一行。

  • 24.05.12 更改了一些有歧义的叙述。


  • 24.05.05 修正关于gl_ClipDistance的说明,简单总结:gl_ClipDistance的作用在栅格化前应用。

  • 24.05.05 略微简化了Ch6-0中的叙事(原先有段代码的解释写得我自己都看不懂-_-||)。


  • 24.04.29 Ch8-4 预乘Alpha完成。

  • 24.04.29 原本CreateRpwf_Screen(...)中有个防止函数重复执行的判定逻辑:
    if (rpwf.renderPass) outStream << std::format("警告信息,略"); else { /*...*/ } return rpwf;
    如今一来觉得这个防呆设计属实没必要,二来这里“防止重复执行”忽视了需重建逻辑设备的情况,遂改之。

  • 24.04.29 接上一条,将各CreateRpwf_后缀(...)函数中的ExecuteOnce(rpwf);语句挪动了位置,这条语句在原先的代码中起前述的“防呆设计”作用,不过我定义ExecuteOnce这个宏的原本目的并不在此(见:Ch2-2)。


  • 24.04.21 在Ch5-2 2D贴图及生成Mipmap中增加关于摩尔纹的说明。


  • 24.04.17 输入附件示例:Ch8-3 延迟渲染完成。


  • 24.04.14 修正issue#7中提到的bug

  • 24.04.14 修正+消歧义Ch3-3Ch4-3中对MSAA和sample shading的说明。


  • 24.04.07 新增Ap1-1 运行期编译GLSL


  • 24.04.05 在Ch8-2 深度测试和深度可视化中非常简单地演示了一下深度边界测试。


  • 24.04.03 Ch3-1 同步原语中新增对VkEvent的说明。

  • 24.04.03 修正对gl_SampleMaskIn的说明:片段着色器中gl_SampleMaskIn的数值根据是否开启sample shading有所不同。


  • 24.04.02 Ch8-2 深度测试和深度可视化完成。

  • 24.04.02 修正对深度偏移的说明:深度偏移作用于经视口变换后的深度,非NDC深度。

  • 24.04.02 修正对设备内存的说明,简单总结:根据要求的内存属性,设备内存的底层可能是计算机主存,可能是显存。


  • 24.03.30 用于在渲染循环中提交命令缓冲区的函数SubmitCommandBuffer_Graphics(...),原先提交信息中的waitDstStage由常量指定,现改为由参数指定以增加函数的灵活性。

  • 24.03.30 Ch8-1 离屏渲染中:
    “srcStageMask指定为VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT是多余的,因为有信号量来同步”,改为“因为有栅栏来同步”。

  • 24.03.30 Ch2-2 创建渲染通道和帧缓冲中增加对子通道依赖的dstStageMask的说明(代码里写了“//不早于提交命令缓冲区时等待semaphore对应的waitDstStageMask”结果被自己无视了-_-||),并相应修正前后文。


  • 24.03.27 Ch8-1 离屏渲染完成。


  • 24.03.26 Ch7-4 初识Push Constant中对vkCmdPushConstants(...)增加了些说明。

  • 24.03.26 修正笔误:贴图坐标的第三个分量是叫做s分量,先前写了w。

  • 24.03.26 在Ch4-1中,修正对NDC坐标系的说明(原先写了“投影变换后得到NDC坐标”,三维渲染中投影变换后的是剪裁空间坐标)+简述了NDC坐标系与剪裁空间和屏幕空间的关系。


  • 24.03.24 Ch6-2 动态渲染中增加了多线程录制命令的简单示例。


  • 24.03.23 Ch6-2 动态渲染完成。

  • 24.03.23 修正Ch6-1 无图像帧缓冲中,Vulkan最高版本只有1.0时开启该设备特性的说明(总结:开不了,这特性在1.1以后才出现)。


  • 24.03.22 简略地说明了一下创建描述符布局时,指定不可变更的采样器的效果。

  • 24.03.22 网站主页精简 + 版式变更(有显示异常的话请汇报)。


  • 24.03.21 Ch6-1 无图像帧缓冲完成。


  • 24.03.20 Ch6-0 使用新版本特性完成。

  • 24.03.20 将静态成员函数的着色改成了与通常函数不同的颜色。

  • 24.03.20 修正Ch3-4 渲染通道和帧缓冲中关于帧缓冲宽度、高度、图层数的说明,帧缓冲的宽高和图层数可以与图像附件的宽高和图层数不同(前者各项小于等于后者各项且大于0)。


  • 24.03.18 Ch5-3 2D贴图数组完成。


  • 24.03.01 新增Ch7-3 初识实例化绘制

  • 24.03.01 Ch7-7 使用贴图完成。


  • 24.02.19 Ch2-1 Rendering Loop中变更了“等待栅栏”和“获取交换链图像”的顺序(更新Vulkan SDK后才检查出问题),顺带简要说明了同步和异步。


  • 24.02.13 Ch5-2 2D贴图及生成Mipmap完成。


  • 24.02.04 根据先前所写的关于内存屏障的说明,修正Ch7-6 拷贝图像到屏幕 #CmdCopyBufferToImage中关于内存屏障的部分说明(-_-||)。


  • 24.01.25 进一步修正并细化说明内存屏障的作用


  • 24.01.13 Ch7-6 拷贝图像到屏幕 完成,同时修正了先前(在完成Ch7-6前便已上传的该节的示例)代码中的一些错误。


  • 24.01.09 详细说明了内存依赖:内存屏障的作用

  • 24.01.09 改正了VK_DEPENDENCY_VIEW_LOCAL_BIT的简短说明


  • 24.01.07 根据Vulkan标准更新后的章节划分,修正了到renderdoc的超链接。

  • 24.01.07 略微增加了一些说明。

  • 24.01.07 改正一些typo。


  • 23.10.13 新增Ch3-7 采样器


  • 23.03.14 修正几处笔误。


  • 23.01.11 修改了一些函数名和类名。

  • 23.01.11 示例代码中,增加了一些数学函数备用。

  • 23.01.11 删了个在参数中间省略默认参数renderArea的函数renderPass::CmdBegin(...),这种不良习惯容易导致bug!并相应修改代码。

  • 23.01.11 Ch1-4最后应该要更新TerminateWindow(),"若需要重建逻辑设备"末尾应该要向graphicsBase::CreateDevice()增加一小段执行回调函数的代码,原本忘记了现在补上。在"创建和销毁交换链时的回调函数"末尾添加了关于使用range-based for循环执行回调函数的注释。


  • 22.11.30 新增关于线性图像中填充字节的说明,见stagingBuffer的部分。


  • 22.11.24 基础部分重写完毕。