Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL3.2 GLSL blocky interpolation

I am wanting a nice gradient effect. But at the minute its really patchy and you can see a seem between the two triangles. I have the following shaders vert and frag. The only thing I can think to do is to swap to a pre-generated texture.

The data is buffed as floats [x y][R G B] for two triangles, I don't think that the C++ source is worth showing.

VERT #version 330

layout(location = 0) in vec2 position;    
layout(location = 1) in vec3 incolor;

smooth out vec3 color;

void main()
{
    color = incolor;
    gl_Position = vec4(position.x,position.y,0.0,1.0);  
}

FRAG #version 330

smooth out vec4 outputColor;
smooth in vec3 color;

void main()
{
    outputColor  = vec4(vec3(color),1.0);   
}

RESULT blocky

Looking at the single triangle shows the blocky-ness enter image description here

like image 884
Andrew Avatar asked Jan 05 '13 01:01

Andrew


1 Answers

It's a correct behavior of linear interpolation of attributes of a quad. Remember that a quad is always rendered as two triangles. There are two possibilities to do so: with a \ diagonal or a / diagonal as their common edge. How the attribute is interpolated now becomes ambiguous (is different in the both cases).

I'll show you an example similar to yours.

enter image description here

Triangles are separated by a \ diagonal.

enter image description here

Triangles are separated by a / diagonal.

In both cases, the colors of the vertices are:

000000  top left
3B3B3B  top right + bottom left
FFFFFF  bottom right

A solution is to provide only attribute values (colors) which result in unambiguous interpolated colors. This is the case when the following holds.

Consider a line from the top left to the bottom right corner (let's call these the base vertices with an assigned base color). The top left corner has a value of 0, the bottom right 1. Every other vertex (in this case bottom left, top right) has to be projected orthogonally to this imaginary line and the corresponding value is assigned to this vertex. In this case (a square) the two other corners have a value of .5 each. The colors of these corners have to be a mix value of the two base colors with an alpha value corresponding to the value just calculated.

In the example above, the colors of the two other corners had to be 808080 instead of 3B3B3B in order to make both images look equally:

enter image description here

In your case, you use the following colors for the vertices (at least, they appear as such in your screenshot):

000000  top left
3A3A3A  top right + bottom left
595959  bottom right

So they don't fulfill the requirement from above, as 3A3A3A isn't the mean value between the other twos.


A slightly different example demonstrates why you maybe don't just want to use .5 for the mix alpha value (which results in mean values for the two other vertices). Consider a non-square quad, like this rectangle, which uses values .5 for the two other corners, which corresponds to 808080 gray:

enter image description here

As you can see, the direction of the gradient isn't orthogonal to the connection line between the two "base corners", as I called them (top left -- bottom right). Now let's see what my method from above produces:

enter image description here

Which looks more like a linear gradient between the two corners, but in "world space", not in "texture space". You might prefer one of the two outputs over the other; I wanted to show you the difference. The values on the connection line (orthogonal projection) look like the following (they are only approximations!)

enter image description here

Sorry for my bad images... ;)

like image 53
leemes Avatar answered Nov 06 '22 03:11

leemes