McLovin
McLovin

Reputation: 3417

Opengl texture flickering when used with mix()

I'm rendering a terrain with multiple textures that includes smooth transitions between the textures, based on the height of each fragment. Here's my fragment shader:

#version 430

uniform sampler2D tex[3];

uniform float renderHeight;

in vec3 fsVertex;
in vec2 fsTexCoords;

out vec4 color;

void main()
{
    float height = fsVertex.y / renderHeight;

    const float range1 = 0.2;
    const float range2 = 0.35;
    const float range3 = 0.7;
    const float range4 = 0.85;

    if(height < range1)
        color = texture(tex[0], fsTexCoords);
    else if(height < range2) //smooth transition
        color = mix( texture(tex[0], fsTexCoords), texture(tex[1], fsTexCoords), (height - range1) / (range2 - range1) );
    else if(height < range3)
        color = texture(tex[1], fsTexCoords);
    else if(height < range4) //smooth transition
        color = mix( texture(tex[1], fsTexCoords), texture(tex[2], fsTexCoords), (height - range3) / (range4 - range3) );
    else
        color = texture(tex[2], fsTexCoords);
}

'height' will always be in the range [0,1].

Here's the weird flickering I get. From what I can see they happen when 'height' equals one of the rangeN variables when using mix().

flickering

Contours highlighted

What may be the cause of this? I also tried playing around with adding and subtracting a 'bias' variable in some computations but had no luck.


Upvotes: 2

Views: 1037

Answers (1)

Jerem
Jerem

Reputation: 1862

Your problem is non-uniform flow control. Basically, you can't call texture() inside an if.

Two solutions:

  • make all the calls to texture() first then blend the results with mix()
  • calculate the partial derivatives of the texture coordinates (with dFdx & co., there is an example in the link above) and use textureGrad() instead of texture()

In very simple cases, the first solution may be slightly faster. The second one is the way to go if you want to have many textures (normal maps etc.) But don't take my word for it, measure.

Upvotes: 1

Related Questions