Vertex shader interpolation is weird

Hi all,
I have a problem interpolating a value using shaders.
I have the following code:
vertex shader:

varying float value;
void main(){
	gl_Position = gl_Vertex;
	value = gl_Color.r;
}";

pixel shader:

varying float value;
vec4 color = (0., 0., 0., 0.);
void main(){
	gl_FragColor = color;
	gl_FragColor.r = value;
}

glcode:

glBegin(GL_QUADS);
glColor3f(0, 0, 0);
glVertex2f(-1, -1); //BL
glColor3f(1, 0, 0);
glVertex2f(-1, 1); //TL
glColor3f(0, 0, 0);
glVertex2f(1, 1); //TR
glColor3f(0, 0, 0);
glVertex2f(1, -1); //BR
glEnd();

It draws a square covering the whole screen.
As you can see, the top left color is red, the rest is black.
The intermediate values are then interpolated using the varying value variable and the result is this:

Now I put the red corner to the top right instead of top left:
glcode:

glBegin(GL_QUADS);
glColor3f(0, 0, 0);
glVertex2f(-1, -1); //BL
glColor3f(0, 0, 0);
glVertex2f(-1, 1); //TL
glColor3f(1, 0, 0);
glVertex2f(1, 1); //TR
glColor3f(0, 0, 0);
glVertex2f(1, -1); //BR
glEnd();

and I get this image:

I expect a rotated but otherwise identical picture, but the results are totally different.
Is it supposed to do that or is it a bug?
How do I get the result I expect?

Any help is appreciated.

Welcome to the world of triangles :slight_smile:
In the second image you can see the edge between the two triangles.
Can’t fix it without geometry shaders and funky maths, afaik.

Reminds me of this:

I expect a rotated but otherwise identical picture, but the results are totally different.
Is it supposed to do that or is it a bug?

“Supposed to”? It is allowed to by the OpenGL specification. And virtually every OpenGL implementation will do this. But it doesn’t have to.

How do I get the result I expect?

You’ll have to work at it. Basically, you need to do the interpolation yourself in the fragment shader. It’s not a trivial thing to do, and how you do it really depends on what your ultimate visual objective is.

I solved it by passing all 4 color values and then doing something like this:

xinfluence = gl_FragCoord.x / xresolution;
yinfluence = gl_FragCoord.y / yresolution;

gl_FragColor = top_left_color * (1 - xinfluence) * yinfluence + 
	top_right_color * xinfluence * yinfluence + 
	bottom_right_color * xinfluence * (1 - yinfluence) + 
	bottom_left_color * (1 - xinfluence) * (1 - yinfluence);

I keep thinking this is overkill and 20 FPS on a GeForce 8400 GS signifies that I’m doing it wrong, but it works for my application.
I still need to figure out how to do cubic interpolation or splines. I was sure graphics cards would have at least one decent interpolation algorithm built in.

Thanks for the help.

I was sure graphics cards would have at least one decent interpolation algorithm built in.

They do. In GLSL, the function is called “mix”, for some reason.