23

在一个简单的 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结果是插值颜色而不是顶点颜色?

4

2 回答 2

18

"varying" variables in the fragment shader have the result of linearly interpolating between the values given at the vertex shader stage (based on the relative position of the fragment between the vertices).

That is, when the rasterizer spits out a fragment at a pixel, its position is also given relative to the triangle vertices in barycentric coordinates. These coordinates are then used to interpolate all varying variables from the vertex shader. In most cases, this is what you want and the speed gained from not interpolating is pretty insignificant these days.

Using the keyword "flat" will disable interpolation and instead use the value of the first vertex (I'm not 100% sure "flat" works with varying as I've switched to using in/out keywords with the newer versions of GLSL).

On a side note, I've found this particularly useful if the fragment needs some values from each of the vertices. In this case I use flat out myVertexValue[3] in the geometry shader (for example here).

于 2013-08-15T13:47:54.047 回答
2

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

于 2013-08-15T13:39:59.003 回答