顶点着色器

顶点着色器对输入的每个顶点进行处理。它可以接收顶点属性作为输入,比如世界坐标,颜色,法线和纹理坐标。它的输出包括顶点最终的裁剪坐标和需要传递给片段着色器的顶点属性,比如颜色和纹理坐标。这些值会被插值处理后传给顶点着色器。

裁剪坐标是一个来自顶点着色器的四维向量,它的四个成分会被除以第四个成分来完成规范化。规范化后的坐标被映射到帧缓冲的坐标空间,如下图所示:

image

如果读者对计算机图形学有所了解,应该对此比较熟悉。如果读者之前使用过OpenGL,可能会注意到这里的Y坐标和OpenGL的Y坐标是相反方向的,Z坐标现在的范围和Direct3D相同,为0到1。

对于我们的要绘制的三角形,不需要使用任何变换操作,我们直接将三角形的三个顶点的坐标作为规范化设备坐标来生成下图的三角形:

image

我们可以直接将顶点着色器输出的裁剪坐标的第四个成分设置为1,然后作为规范设备坐标。这样裁剪坐标到规范设备坐标就不会对坐标进行任何变换。

通常,顶点坐标被存储在一个顶点缓冲中,但对于Vulkan来说,创建顶点缓冲,然后填入数据要进行很多操作。为了尽快让我们的三角形显示在屏幕上,我们暂时先直接将顶点坐标写入顶点着色器,就像这样:

#version 450
#extension GL_ARB_separate_shader_objects : enable

out gl_PerVertex {
    vec4 gl_Position;
};

vec2 positions[3] = vec2[](
                vec2(0.0, -0.5),
                vec2(0.5, 0.5),
                vec2(-0.5, 0.5)
);

void main() {
    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
}

着色器的main函数对于每个顶点执行一次。GLSL内建的gl_VertexIndex变量包含了当前顶点的索引。这一索引通常来说是用来引用顶点缓冲中的顶点数据,但在这里,我们用它来引用我们在着色器中硬编码的顶点数据。我们输出的裁剪坐标由代码中的positions数组给出了前两个成分,剩余两个成分被我们设置为了0.0和1.0。为了让着色器代码可以在Vulkan下工作,我们需要使用GL_ARB_separate_shader_objects扩展。