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 :
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 !
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
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);