顶点和片段着色器如何在OpenGL中进行通信?

时间:2015-02-04 22:45:11

标签: opengl graphics glsl fragment-shader vertex-shader

我真的不明白片段着色器是如何工作的。

我知道

  • 顶点着色器每个顶点运行一次
  • 片段着色器每个片段运行一次

由于片段着色器每个顶点不起作用,但每个片段如何将数据发送到片段着色器?顶点数量和碎片数量不相等。

如何确定哪个片段属于哪个顶点?

2 个答案:

答案 0 :(得分:8)

要理解这一点,您需要考虑整个渲染管道。顶点着色器的输出(除了特殊输出gl_Position)作为"相关数据"传递。顶点到管道中的下一个阶段。

虽然顶点着色器一次在单个顶点上工作,而根本不关心基元,但是管道的其他阶段确实考虑了基本类型(和顶点连接信息)。这通常被称为"原始汇编"。现在,我们仍然有单个顶点和VS生成的相关数据,但我们也知道哪些顶点组合在一起以定义基本图元,如点(1个顶点),1个线(2个顶点)或3个(3个)顶点)。

在光栅化期间,为输出像素栅格中属于基元的每个像素位置生成片段。在这样做时,定义原始的顶点的相关数据可以在整个原始中进行插值。在一行中,这很简单:完成线性插值。让我们用每个相关的输出向量v调用端点A和B,这样我们就有了v_A和v_B。在整个线上,我们得到v的插值在每个端点处为v(x)=(1-x)* v_A + x * v_B,其中x在0(在点A)到1(在点)的范围内B)。对于三角形,使用所有3个顶点的数据之间的重心插值。因此,虽然顶点和片段之间没有1:1的映射,但VS的输出仍然定义FS的corrseponding输入的值,不是直接的,而是间接地通过所使用的基元类型的插值。 / p>

conceptual data shader flow in the GL

到目前为止我给出的公式有点简化。实际上,默认情况下,通过修改公式来有效地应用透视校正,以便考虑透视的失真效应。这仅仅意味着插值应当在物体空间中线性应用(在应用投影的失真之前)。例如,如果你有一个透视投影和一些与图像平面不平行的图元,那么在屏幕空间中向右移动1个像素就意味着在真实物体上移动一个可变距离,具体取决于实际点的距离。相机飞机。

您可以使用GLSL中noperspective / in变量的out限定符来禁用透视校正。然后,按照我的描述使用线性/重心插值。

您还可以使用flat限定符,它将完全禁用插值。在这种情况下,只有一个顶点的值(所谓的"激发顶点")用于整个图元的所有片段。整数数据永远不能由GL自动插值,并且在发送到片段着色器时必须被限定为flat

答案 1 :(得分:1)

答案是他们不是 - 至少不是直接的。还有一个名为" rasterizer"位于管道中的顶点处理器和片段处理器之间。光栅化器负责收集从顶点着色器出来的顶点,将它们重新组合成图元(通常是三角形),将这些三角形分解成光栅"光栅。 (部分)coverer像素,并将这些片段发送到片段着色器。

这是一个(大部分)固定功能的硬件,你不需要直接编程。你可以做一些配置调整,它会影响它作为基元处理的内容以及它作为片段产生的内容,但在大多数情况下它只是在顶点着色器和片段着色器之间进行处理。