8

我对图形编程比较陌生,而且我刚刚阅读了一些书籍并且一直在浏览教程,所以如果这似乎是一个愚蠢的问题,请原谅我。

我已经掌握了directx11 的基础知识并开始运行,现在我想找点乐子。所以很自然地,我一直在大量阅读着色器管道,我已经着迷了。编写一段简单、微小的代码,它必须足够高效,以每 60 秒运行数万次而不浪费资源,这让我急于掌握这个概念,然后再继续下去,可能会弄得一团糟东西的。我遇到的问题是掌握像素着色器实际在做什么。

顶点着色器很容易理解,你将一个对象的顶点组织在统一的数据结构中,这些数据结构与它相关的信息,比如位置和纹理坐标,然后将每个顶点传递给着色器,通过变换矩阵从 3d 转换为 2d . 只要我理解它,我就可以弄清楚如何编码。

但我没有像素着色器。我得到的是顶点着色器的输出是像素着色器的输入。那么这不就是将多边形顶点的二维坐标交给像素着色器吗?我所理解的是像素着色器接收单个像素并对它们执行计算以确定颜色和照明等内容。但如果这是真的,那么哪些像素呢?整个屏幕还是仅位于转换后的 2d 多边形内的像素?

还是我完全误解了某些东西?

4

2 回答 2

10

顶点着色器很容易理解,你将一个对象的顶点组织在统一的数据结构中,这些数据结构与它相关的信息,比如位置和纹理坐标,然后将每个顶点传递给着色器,通过变换矩阵从 3d 转换为 2d .

在此之后,生成并裁剪图元(三角形或三角形的倍数)(在 Direct3D 11 中,由于变换反馈、几何着色器、曲面细分等等,它实际上要复杂一些……但不管它是什么,在最后你有三角形)。

现在,片段被“生成”了,即将一个三角形分割成一个规则网格的小单元,顶点着色器的输出属性根据每个网格单元与三个顶点的相对位置进行插值,并设置一个“任务”为每个小网格单元。这些单元中的每一个都是一个“片段”(如果使用多重采样,一个像素1可能存在多个片段)。

最后,在所有这些“任务”上执行一个小程序,这就是像素着色器(或片段着色器)。

它采用插值的顶点属性,并可选择读取统一值或纹理,并产生一个输出(它也可以选择产生多个输出)。像素着色器的此输出引用一个片段,然后被丢弃(例如由于深度测试)或与帧缓冲区混合。通常,同一像素着色器的许多实例会同时并行运行。这是因为像这样运行 GPU 会更高效、更节能。一个像素着色器不知道同时运行的任何其他像素着色器。
像素着色器通常在一组中运行(也称为“扭曲”或“波前”),并且一组中的所有像素着色器同时执行完全相同的指令(在不同的数据上)。同样,这允许构建更强大的芯片,消耗更少的能源,更便宜。




1请注意,在这种情况下,片段着色器仍然只为每个“单元格”运行一次。多重采样仅根据(更高分辨率)深度测试决定是否将计算值存储在更高分辨率的额外“槽”(子样本)之一中。对于屏幕上的大多数像素,所有子样本都是相同的。然而,在边缘上,只有一些子样本会被特写几何体填充,而有些子样本会保持它们的值不受更远的“背景”几何体的影响。当多采样图像被解析(即转换为“正常”图像)时,显卡会生成这些子样本的“混合”(在最简单的情况下,只是算术平均值),这会导致除边缘之外的所有内容都出现和往常一样,边缘是“

于 2012-06-25T17:34:21.200 回答
2

您对像素着色器的理解是正确的,因为它“接收单个像素并对其执行计算以确定颜色和照明等内容”。

着色器接收的像素是在变换后的 2d 多边形(具体为三角形)的光栅化过程中计算的单个像素。因此,顶点着色器处理三角形的 3 个点,而像素着色器处理“填充”三角形的像素,一次一个。

于 2012-06-25T17:32:37.890 回答