图形管线概述

在接下来的章节,我们将开始配置图形管线来渲染我们的三角形。图形管线是一系列将我们提交的顶点和纹理转换为渲染目标上的像素的操作。它的简化过程如下:

input assembler获取顶点数据,顶点数据的来源可以是应用程序提交的原始顶点数据,或是根据索引缓冲提取的顶点数据。

vertex shader对每个顶点进行模型空间到屏幕空间的变换,然后将顶点数据传递给图形管线的下一阶段。

tessellation shaders根据一定的规则对几何图形进行细分,从而提高网格质量。通常被用来使类似墙面这类不光滑表面看起来更自然。

geometry shader可以以图元(三角形,线段,点)为单位处理几何图形,它可以剔除图元,输出图元。有点类似于tessellation shader,但更灵活。但目前已经不推荐应用程序使用它,geometry shader的性能在除了Intel集成显卡外的大多数显卡上表现不佳。

rasterization阶段将图元离散为片段。片段被用来在帧缓冲上填充像素。位于屏幕外的片段会被丢弃,顶点着色器输出的顶点属性会在片段之间进行插值,开启深度测试后,位于其它片段之后的片段也会被丢弃。

fragment shader对每一个未被丢弃的片段进行处理,确定片段要写入的帧缓冲,它可以使用来自vertex shader的插值数据,比如纹理坐标和顶点法线。

color blending阶段对写入帧缓冲同一像素位置的不同片段进行混合操作。片段可以直接覆盖之前写入的片段,也可以基于之前片段写入的信息进行混合操作。

image

使用绿色标识的阶段也被叫做固定功能阶段。固定功能阶段允许通过参数对处理过程进行一定程度的配置。

使用橙色标识的阶段是可编程阶段,允许我们将自己的代码加载到显卡,进行我们想要的操作。这使得我们可以实现许多有趣的效果。我们加载到显卡的代码会被GPU并行处理。

如果读者使用了一些旧的图形API,可能会对glBlendFunc和OMSetBlendState之类的函数比较熟悉,这些函数可以对图形管线进行一定的设置。而在Vulkan中,图形管线几乎完全不允许进行动态设置,如果我们想使用其它着色器,绑定其它帧缓冲,以及改变混合函数,都需要重新创建管线。这就迫使我们必须提前创建所有我们需要使用的图形管线,虽然这样看起来不太方便,但这给驱动程序带来了很大的优化空间。

图形管线的部分可编程阶段不是必需的。比如对于tessellation和geometry shader阶段,如果我们只是画一个简单的三角形,完全没有必要使用它们。如果我们只是需要生成阴影贴图的深度值,我们也可以不使用fragment shader。

在下一章节,我们首先创建两个对于在屏幕上绘制三角形必需的可编程阶段:vertex shader和fragment shader。对于固定功能的设置,比如混合模式,视口,光栅化会在下一章节之后进行。最后,我们开始图形管线中帧缓冲的配置工作。

我们添加一个叫做createGraphicsPipeline的函数,并在initVulkan函数中的createImageViews函数调用之后调用它。接下来的章节我们主要在createGraphicsPipeline这个函数中进行代码编写。

void initVulkan() {
    createInstance();
    setupDebugCallback();
    createSurface();
    pickPhysicalDevice();
    createLogicalDevice();
    createSwapChain();
    createImageViews();
    createGraphicsPipeline();
}

        ...

void createGraphicsPipeline() {

}

本章节代码:

C++:

https://vulkan-tutorial.com/code/08_graphics_pipeline.cpp