简介

通过接下来几章的课程,我们会建立一个图形渲染管线来绘制我们的第一个三角形。图形渲染管线就是一步一步地把你的顶点和纹理变成渲染目标上的像素的一系列操作。下面是它的简要图示:

简介 - 图1

“输入装配器”(input assembler)从指定的缓存中收集原生的顶点数据,并可能使用一个顶点缓冲来重复某些元素,而不是重复顶点本身。

“顶点着色器”(vertex shader)针对的是每个顶点,并且通常使用变换来把顶点坐标从模型空间转换到屏幕空间。它也会把每个顶点的数据传送给管线的下一阶段。

“曲面细分着色器”(tessellation shaders)允许你根据特定规则对图形进行细分以提高网格品质。它经常用在生成类似砖墙或者楼梯那种离得越近看起来就越粗糙的表面。

“几何着色器”(geometry shader)针对的是每个图元(三角形、线、点),它可以丢弃一些图元,或者输出更多的图元。它与曲面细分着色器有些相似,但是更加灵活。不过,在现在的程序中已经不太用这个着色器了,因为在大多数显卡上它的性能不怎么好,尤其是英特尔的集成显卡。

“光栅化”(rasterization)阶段把图元离散成“片段”。片段是填充在帧缓冲上的像素元素。任何处于屏幕外的片段都将被丢弃,并且由顶点着色器输出的数据会被插值到片段中,就像图中那样。通常,在这一步,那些位于其它片段后面的片段也会被深度测试丢弃。

“片段着色器”(fragment shader)针对的是每一个被保留的片段,并且确定片段要写入到哪些帧缓冲中,以及片段要使用哪些颜色和深度值。它可以使用由顶点着色器插值过的数据,比如顶点坐标和光照法线,来完成这些工作。

“颜色混合”(color blending)阶段把不同的片段混合之后映射到帧缓冲的同一个像素上。片段可以简单地彼此覆盖、相加或者基于透明度进行混合。

图中绿色的阶段被称为“固定功能”(fixed-function)阶段。这些阶段允许你通过参数调整它们的行为,但是它们工作的方式是被预定义好了的。

另一部分,图中橙色的阶段是programmable(可编程)的,这意味着你可以上传你自己的代码给显卡来显式执行你想执行的操作。例如,这允许你使用片段着色器执行从贴图与光照到光线追踪的任何操作。这些程序同时运行在GPU的许多核心上来处理许多对象,例如并行处理顶点与片段。

如果你之前使用过OpenGL或者Direct3D那种老式API,那么你大概习惯于通过glBlendFuncOMSetBlendState来改变管线设置。Vulkan中的图形渲染管线基本上都是完全不可变的,因此如果你想更改着色器、绑定不同的帧缓冲或者是更改混合方式,你就必须得重新创建渲染管线。缺点是你必须创建很多管线来表示你想在渲染操作中执行的不同的阶段组合。不过,因为管线中所有的操作都是渲染前就已经明确的,驱动程序就能更好地对它们进行优化。

可编程阶段中的某些阶段是可选的,这取决于你想怎么做。比如,如果你只是在画一个简单的图形的话,曲面细分阶段和几何阶段是可以禁用的。如果你只关心深度值,那么你可以禁用片段着色器阶段,这对阴影贴图的生成很有帮助。

在下一章我们会首先创建两个显示三角形所必需的可编程阶段:顶点着色器和片段着色器。固定功能,比如混合模式、视口和光栅化,的配置,将会在大下章讲解。Vulkan中配置图形渲染管线的最后一个部分涉及到指定帧缓冲的输入与输出。

创建一个createGraphicsPipeline函数,然后在initVulkan函数里的createImageViews之后调用它。在接下来的几章里我们会编写这个函数。

  1. void initVulkan() {
  2. createInstance();
  3. setupDebugCallback();
  4. createSurface();
  5. pickPhysicalDevice();
  6. createLogicalDevice();
  7. createSwapChain();
  8. createImageViews();
  9. createGraphicsPipeline();
  10. }
  11. ...
  12. void createGraphicsPipeline() {
  13. }

C++代码