【问题标题】:How does vertex shader pass color information to fragment shader?顶点着色器如何将颜色信息传递给片段着色器?
【发布时间】:2026-01-10 04:40:01
【问题描述】:

在一个简单的 hello-world OpenGL 程序中,它只是在窗口上绘制一个静态三角形, 当我将三角形的 3 个顶点设置为红色、绿色和蓝色时,三角形被渐变填充。

但是当我使用这样的着色器时:

顶点着色器:

attribute vec4 aVertex;
attribute vec4 aColor;

varying vec4 vColor;

void main(void) {
    gl_Position = gl_ModelViewMatrix * gl_ProjectionMatrix * aVertex;
    vColor = aColor;
}

其中aVertexaColor 属性来自顶点缓冲区,通过glVertexAttribPointer 调用传递。

片段着色器:

varying vec4 vColor;
void main(void) {
    gl_FragColor = vColor;
}

三角形还是用渐变填充的,问题来了:

如果顶点着色器是按顶点计算的,那么vColor 的每个实例都应该分配一个顶点的颜色。并且顶点颜色应该是红色、绿色或蓝色,如顶点缓冲区中设置的那样。

那么渐变是从哪里来的呢?

或者,换句话说,什么时候在片段着色器中,vColor 变成了插值颜色而不是顶点的颜色?

【问题讨论】:

标签: opengl glsl shader


【解决方案1】:

片段着色器中的“变化”变量具有在顶点着色器阶段给出的值之间线性插值的结果(基于顶点之间片段的相对位置)。

也就是说,当光栅化器在一个像素处吐出一个片段时,它的位置也是相对于重心坐标中的三角形顶点给出的。然后使用这些坐标对来自顶点着色器的所有变量进行插值。在大多数情况下,这就是您想要的,而现在通过不插值获得的速度已经微不足道了。

使用关键字“flat”将禁用插值,而是使用第一个顶点的值(我不是 100% 确定“flat”适用于变化,因为我已切换到使用带有 @987654321 的 in/out 关键字@)。

附带说明,如果片段需要来自每个顶点的一些值,我发现这特别有用。在这种情况下,我在几何着色器 (for example here) 中使用 flat out myVertexValue[3]

【讨论】:

  • 我突然意识到在应用插值之前不需要知道变量是关于颜色的。实际上,坐标、法线、TexCoords 和一切都是顶点之间的插值。
【解决方案2】:

渐变来自于在变体传递到fragment 着色器时发生的顶点颜色之间的插值。如果您不想在变体的开头使用“flat”关键字进行插值。 您的误解可能源于缺乏关于顶点和片段阶段如何工作的知识。它们的工作方式不同。顶点着色器是按顶点调用的,而片段是按像素调用的。默认情况下会发生插值,因为需要覆盖光栅化期间生成的片段在原始组件定义的区域上的舞台。正如我所说,您可以通过“平面”禁用插值。在这种情况下,第一个顶点属性的颜色将定义形状的整体颜色。

【讨论】: