在接下来的几章中,我们将设置一个图形管道,该管道被配置为绘制第一个三角形。图形管道是一系列操作,将网格的顶点和纹理一直传递到渲染目标中的像素。下面显示了一个简化的概述:
input assembler 从指定的缓冲区收集原始顶点数据,还可以使用索引缓冲区重复某些元素,而不必复制顶点数据本身。
vertex shader 针对每个顶点运行的,通常应用变换将顶点位置从模型空间转换到屏幕空间。它还沿管道传递逐顶点数据。
tessellation shaders 允许您基于某些规则细分几何体,以提高网格质量。这通常用于使砖墙和楼梯等表面在附近时看起来不那么平坦。
geometry shader 几何着色器在每个基本体(三角形、直线、点)上运行,可以丢弃它或输出比传入的更多的基本体。这与细分着色器类似,但更灵活。然而,它在今天的应用程序中使用得并不多,因为除了英特尔的集成GPU之外,大多数显卡的性能都不太好。
rasterization 光栅化阶段将基本体离散化为片段。这些是它们在帧缓冲区中填充的像素元素。任何落在屏幕之外的碎片都将被丢弃,顶点着色器输出的属性将在碎片之间进行插值,如图所示。通常,由于深度测试,其他原始碎片后面的碎片也会被丢弃。
fragment shader 将为每个幸存的片段调用片段着色器,并确定将片段写入哪个帧缓冲区以及使用哪个颜色和深度值。它可以使用来自顶点着色器的插值数据来实现这一点,顶点着色器可以包括纹理坐标和照明法线等内容。
color blending 应用操作来混合映射到帧缓冲区中相同像素的不同片段。片段可以简单地相互覆盖、相加或基于透明度混合。
带有绿色的阶段称为固定功能阶段。这些阶段允许您使用参数调整其操作,但它们的工作方式是预定义的。
另一方面,橙色的阶段是可编程的,这意味着您可以将自己的代码上传到显卡,以准确应用所需的操作。例如,这允许您使用片段着色器来实现从纹理和照明到光线跟踪器的任何功能。这些程序在许多GPU内核上同时运行,以并行处理许多对象,如顶点和碎片。
如果您以前使用过OpenGL和Direct3D等较旧的API,那么您将习惯于使用glBlendFunc和OMSetBlendState等调用随意更改任何管道设置。Vulkan中的图形管道几乎是完全不可变的,因此如果要更改着色器、绑定不同的帧缓冲区或更改混合函数,必须从头开始重新创建管道。缺点是必须创建许多管道,以表示渲染操作中要使用的所有不同状态组合。然而,因为您将在管道中执行的所有操作都是预先知道的,所以驱动程序可以更好地进行优化。
某些可编程阶段是可选的,具体取决于您要执行的操作。例如,如果您只是绘制简单的几何图形,则可以禁用细分和几何阶段。如果只对深度值感兴趣,则可以禁用片段着色器阶段,这对于生成阴影贴图非常有用。
在下一章中,我们将首先创建将三角形放到屏幕上所需的两个可编程阶段:顶点着色器和片段着色器。固定的功能配置,如混合模式、视口、光栅化将在之后的章节中设置。在Vulkan中设置图形管道的最后一部分涉及输入和输出帧缓冲区的规范。
在initVulkan中创建一个在createImageViews之后立即调用的createGraphicsPipeline函数。我们将在接下来的章节中讨论这个函数。
void initVulkan() {
createInstance();
setupDebugMessenger();
createSurface();
pickPhysicalDevice();
createLogicalDevice();
createSwapChain();
createImageViews();
createGraphicsPipeline();
}
...
void createGraphicsPipeline() {
}