OpenGL如何在片段着色器上插值varying变量,即使它们只在顶点着色器上设置了三次?

10

由于顶点着色器每个顶点只运行一次(也就是在三角形中运行3次),如果将varying变量仅分配了三次,那么它如何为每个片元计算呢?

片元着色器:

precision mediump float;
varying vec4 v_Color;

void main() {
    gl_FragColor = v_Color;
}

顶点着色器:

attribute vec4 a_Position;
attribute vec4 a_Color;

varying vec4 v_Color;

void main() {
    v_Color = a_Color;
    gl_Position = a_Position;
}
所以问题是,这背后的系统如何知道在每个片元中如何计算变量v_Color,因为此着色器仅在三角形中分配v_Color 3次。

它在三个顶点之间插值计算数值,这就是所谓的变量插值。 - Matt Greer
1
我对GLSL并不是很有经验,希望有其他人能回答这个问题。但基本上,如果你的顶点相距十个像素,那么在顶点之间的每个像素将获得一个插值颜色,该颜色朝另一种颜色的1/10,2/10,3/10等方向移动。 - Matt Greer
1
是的。当您在顶点着色器中设置 v_Color 时,它会在顶点上进行设置。当片段着色器运行时,它读取所有顶点的 v_Color 值并根据片段的位置在它们之间进行插值。没有覆盖。 - Colonel Thirty Two
以下是有关在vec或mat值之间变化的更多信息:https://gamedev.stackexchange.com/questions/139720/glsl-varying-interpolation-component-wise-reference-in-the-spec - trusktr
看看 Gregg Man 的这个有趣的可视化:https://github.com/greggman/webgl-fundamentals/issues/80 - trusktr
显示剩余5条评论
2个回答

7

顶点着色器的所有输出都是按顶点计算的。当您在顶点着色器中设置v_Color时,它会在当前顶点上设置该值。当片段着色器运行时,它会读取原始图元中每个顶点的v_Color值,并根据片段的位置在它们之间进行插值。


3
首先,假设顶点着色器每个顶点只运行一次是一个错误的想法。使用索引渲染时,原始图元组装通常可以基于顶点索引访问后处理T&L高速缓存(前面的顶点着色器调用结果),以消除对一个顶点进行多次评估。然而,新的东西例如几何着色器很容易导致这种情况崩溃。
至于片段着色器如何获得其值,通常是在光栅化期间完成的。这些每个顶点属性沿着图元表面(在本例中为三角形)相对于用于构建图元的顶点的距离进行插值。在DX11中,插值可以推迟到片段着色器本身运行时(称为“拉模型”插值),但传统上这是发生在光栅化期间的事情。

如果实现正在缓存顶点着色器的输出,那么据我所知,检测到对于该顶点的顶点着色器的第二次调用不能产生任何不同的值,因此这一点是无关紧要的。 - Colonel Thirty Two
1
@ColonelThirtyTwo:实际上,后 T&L 缓存的容量是有限的,而且传统上它是先进先出的。这就是为什么以本地优化顺序提供顶点(例如strip-order)可以提高性能,即使您实际上不使用顶点作为带状图(这主要节省了您必须存储的索引数量)。几何着色器通过引入第二层需要缓存的数据使情况变得更糟,但这主要影响 GS 的最大同时调用数和后 GS 缓存的大小在曲面细分引入时已经得到了很大程度的解决。 - Andon M. Coleman
没错,但它们不会影响最终渲染的图像。对于那些刚开始学习OpenGL并不太担心效率的人来说,这似乎是一个技术性的问题。 - Colonel Thirty Two
1
@ColonelThirtyTwo:这绝对是一个技术性的问题,与这个问题没有太多关联,所以我没有详细解释任何术语。我只是简单地提到了这是一个错误的假设,并使用了正确的术语,以防有人想要学习更多。要适当地解释所有这些需要很多篇幅 ;) - Andon M. Coleman

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