像素着色器实际上是做什么的?

8

我是一名相对较新的图形编程人员,刚刚阅读了一些书籍并扫描了一些教程,所以请原谅如果这个问题看起来很愚蠢。

我已经掌握了directx11的基础知识,并且现在想要寻找一些乐趣。因此,我自然而然地深入研究了着色器管道,我已经着迷了。编写一个简单的、微小的代码,必须足够高效地运行,每秒可能运行数万次,而不浪费资源,让我急于掌握概念,以免在继续之前可能会弄乱事情。我遇到的问题是难以理解像素着色器实际在做什么。

顶点着色器很容易理解,你将对象的顶点组织成统一的数据结构,与其相关的信息如位置和纹理坐标,然后将每个顶点传递到着色器中,通过转换矩阵从3D转换为2D。只要我理解了它,我就可以找出如何编码。

但是我不太理解像素着色器。我理解的是,顶点着色器的输出是像素着色器的输入。那么这不只是把多边形顶点的2D坐标交给像素着色器吗?我所理解的是,像素着色器接收到单个像素并对它们进行计算,以确定颜色和光照等属性。但如果是这样的话,那些像素呢?整个屏幕还是仅在变换后的2D多边形内的像素?

或者我完全误解了什么?

2个回答

10
顶点着色器很容易理解,您可以将对象的顶点组织成统一的数据结构,以关于其位置和纹理坐标等信息的方式进行关联,然后将每个顶点传递到着色器中,通过变换矩阵从3D转换为2D。
之后,将生成和剪裁原始图元(三角形或多个三角形)。在Direct3D 11中,由于变换反馈、几何着色器、曲面细分等因素,事情实际上要复杂一些......但无论是什么,在最后你会得到三角形。
现在,片段被"生成"了,即单个三角形被分成带有规则网格的小单元格,根据每个网格单元格相对于三个顶点的位置插值顶点着色器的输出属性,并为每个小网格单元格设置一个"任务"。每个单元格都是一个"片段"(如果使用了多重采样,则一个像素可能存在多个片段)。
最后,对所有这些"任务"执行一个小程序,这就是像素着色器(或片段着色器)。
它获取插值的顶点属性,并可选择读取统一值或纹理,然后生成一个输出(它也可以选择生成多个输出)。像素着色器的输出是一个片段,然后可以将其丢弃(例如由于深度测试)或与帧缓冲混合。
通常情况下,许多相同的像素着色器一起并行运行。这是因为GPU以这种方式运行更有效率并具有更低的功耗。单个像素着色器不知道同时运行的任何其他像素着色器。
像素着色器通常以组(也称为"线程束"或"波前")的形式运行,组内所有像素着色器在同一时间执行完全相同的指令(在不同的数据上)。同样,这允许构建更强大、少用能量和更便宜的芯片。1请注意,在这种情况下,片段着色器仍然只对每个“单元格”运行一次。多重采样只是决定是否根据(更高分辨率的)深度测试将计算得到的值存储在更高分辨率的额外“插槽”(子采样)之一中。对于屏幕上的大多数像素,所有子采样都是相同的。然而,在边缘处,只有一些子采样会被近距离几何体填充,而一些子采样则会保持来自远处的“背景”几何体的值。当解决多采样图像(即转换为“正常”图像)时,显卡会生成这些子采样的“混合”(在最简单的情况下,仅为算术平均值),这导致除了边缘以外的所有内容都和通常一样,而边缘被“平滑化”。

好的,我现在明白了。不过,由于我是一位视觉学习者,我画了一个图表来表示我理解的内容,请告诉我是否有遗漏的地方。http://postimage.org/image/9oy2nroqr/ - FatalCatharsis
1
一个错误:顶点着色器后的坐标不是像素坐标,而是_归一化坐标_。对于Direct3D来说,这意味着它们在0.0和1.0之间(在OpenGL中为-1.0和1.0)。一开始这并不是很直观,因为屏幕通常不是正方形,但是它“只是起作用”(不用担心,你无需做任何特别的事情!),并且在这个空间中进行计算(例如剪辑)对硬件来说更有效率。其余部分看起来不错(几何着色器、细分和裁剪被称为“发生在中间的东西”)。 - Damon
啊,我明白了。实际上,我更喜欢标准化坐标,因为无论你选择什么屏幕分辨率,所有的东西都会在相同的比例尺上。不过OpenGL似乎有点奇怪,从-1到1。那么几何着色器和曲面细分阶段发生在中间?我本来以为它们是最先执行的,因为新顶点可以被馈送到顶点着色器并转换为屏幕坐标。自动创建的新顶点是否已转换为2D? - FatalCatharsis
我意识到我正在迅速把这个问题变成一堆小问题,已经占用了你很多时间。我认为我对像素着色器的运作有了相当好的理解,所以应该没问题了。谢谢帮忙!现在去玩得开心一点吧 :P - FatalCatharsis
2
请点击这里(或者这里查看OpenGL 4.x等效的更好的图片,名称略有不同但是意思相同)。出于几个实际和效率的原因,将曲面细分放在顶点着色器之后是有意义的(例如,如果不知道一个补丁覆盖的屏幕区域大小,如何确定需要细分多少次?)。你不能简单地将每个三元组的顶点细分成一千个三角形。你需要根据它们实际覆盖的屏幕面积来进行细分。 - Damon
好的,当你这样说的时候,现在它变得有些合理了。再次感谢 :P - FatalCatharsis

2

你对像素着色器的理解是正确的,它“接收单个像素并对其执行计算,以确定颜色和光照等信息。”

像素着色器接收到的像素是在转换为2D多边形(具体来说是三角形)时计算出的单个像素。因此,顶点着色器处理三角形的三个点,而像素着色器逐个处理“填充”三角形的像素。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接