Search code examples
openglglslshaderfragment-shader

Opengl Shader : Interpolating between two textures


I am trying to build a random terrain generator in c++ and opengl, but I have some trouble with texturing. I have two type of texture : herb and rock : enter image description here

As you can see, on top of hills there is rock, and herb down. I interpolate between these two textures by the vertex's height. My height value is between -1 and 1. So in my fragment shader I do :

float height = clamp(vs_position.y/20.f, -1f, 1f );

height = exp(height) / exp(1.f);


vec3 final_texture = mix(
vec3(texture(texture0, vs_texcoord)), 
vec3(texture(texture1, vs_texcoord)), 
vec3(height));

First line is not important, before I send vertex data to my shader, I multiply the height by 20 to have more pronounced hills.

Thirst line : I mix the two textures by height.

Second line : To have a "stronger" interpolation, I use a softmax function to have height value closer to 0 or 1. Honestly it doesn't do too much, maybe I don't use this function properly.

What I want is to do a stronger softmax, and being able to control the level of interpolation. So my height values should be closer to 0 or 1. Because what I get with my interpolation doesn't look great right now. So for example, if my height is 0.7, it should be transformed to 0.95. And f(0.3) = 0.05, f(0.5) = 0.5. Something like that. Do you know a tips for that?

EDIT : I did it !

enter image description here

It is pretty simple, I just repeat the function softmax several time :

float softmax(float value, float max , int iteration, float offset)
{
    value += offset;

    for(int i=0; i<iteration; i++)
    {
        value = exp(value);
        max = exp(max);
    }

    value = (value/max);
    value = clamp(value, 0.f, 1.f);

    return value;
}

And I use an offset to choose at what height the interpolation start


Solution

  • I recommend to use smoothstep to "smoothly" map the height from its range (e.g. [-20.0, 20.0]) to the range [0.0, 1.0] for the interpolation by mix. e.g.:
    (smoothstep performs a Hermite interpolation)

    vec3 color0 = texture(texture0, vs_texcoord).rgb;
    vec3 color1 = texture(texture1, vs_texcoord).rgb;
    
    float a = smoothstep(-20.0, 20.0, height);
    vec3 final_texture = mix(color0, color1, a);
    

    Note, it is even possible to restrict the interpolation to a certain range. In the following the color from texture0 is used, if height < -1.0 and from texture1 if height > -1.0. In between the it is smoothly interpolated between the textures:

    float a = smoothstep(-1.0, 1.0, height);
    vec3 final_texture = mix(color0, color1, a);