Skip to main content
added 115 characters in body
Source Link
Babis
  • 920
  • 4
  • 10

It's a simple interpolation. Let's assume that your heights span -1 to 1, 0 is water surface and you have 3 colours: dark green, light green and white. A way to do what you want is to have the following color_from_height function in the pixel or fragment shader (depending on how efficient you want to be):. In my shader below I visualize the gradient, but the function color_from_height should get the world space height.

// This is a shadertoy example (www.shadertoy.com) which will visualize the 4-colours palette


vec3 color_from_height( const float height )
{
    vec3 terrain_colours[4];
    terrain_colours[0] = vec3(0.0,0.0,0.6);
    terrain_colours[1] = vec3(0.1, 0.3, 0.1);
    terrain_colours[2] =  vec3(0.4, 0.8, 0.4);
    terrain_colours[3] = vec3(1.0,1.0,1.0);
    //vec3 terrain_colours[1] = vec3[1]{ vec3(0,0,0.6)};
    if(height < 0.0)
        return terrain_colours[0];
    else
    {
        float hscaled = height*2.0 - 1e-05; // hscaled should range in [0,2)
        int hi = int(hscaled); // hi should range in [0,1]
        float hfrac = hscaled-float(hi); // hfrac should range in [0,1]
        if( hi == 0)
            return mix( terrain_colours[1],terrain_colours[2],hfrac); // blends between the two colours    
        else
            return mix( terrain_colours[2],terrain_colours[3],hfrac); // blends between the two colours
    }
    return vec3(0.0,0.0,0.0);
}

void main(void)
{
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    vec3 col = color_from_height(uv.y*2.0-1.0);
    gl_FragColor = vec4(col,1.0);
}

It's a simple interpolation. Let's assume that your heights span -1 to 1, 0 is water surface and you have 3 colours: dark green, light green and white. A way to do what you want is to have the following color_from_height function in the pixel or fragment shader (depending on how efficient you want to be):

// This is a shadertoy example (www.shadertoy.com) which will visualize the 4-colours palette


vec3 color_from_height( const float height )
{
    vec3 terrain_colours[4];
    terrain_colours[0] = vec3(0.0,0.0,0.6);
    terrain_colours[1] = vec3(0.1, 0.3, 0.1);
    terrain_colours[2] =  vec3(0.4, 0.8, 0.4);
    terrain_colours[3] = vec3(1.0,1.0,1.0);
    //vec3 terrain_colours[1] = vec3[1]{ vec3(0,0,0.6)};
    if(height < 0.0)
        return terrain_colours[0];
    else
    {
        float hscaled = height*2.0 - 1e-05; // hscaled should range in [0,2)
        int hi = int(hscaled); // hi should range in [0,1]
        float hfrac = hscaled-float(hi); // hfrac should range in [0,1]
        if( hi == 0)
            return mix( terrain_colours[1],terrain_colours[2],hfrac); // blends between the two colours    
        else
            return mix( terrain_colours[2],terrain_colours[3],hfrac); // blends between the two colours
    }
    return vec3(0.0,0.0,0.0);
}

void main(void)
{
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    vec3 col = color_from_height(uv.y*2.0-1.0);
    gl_FragColor = vec4(col,1.0);
}

It's a simple interpolation. Let's assume that your heights span -1 to 1, 0 is water surface and you have 3 colours: dark green, light green and white. A way to do what you want is to have the following color_from_height function in the pixel or fragment shader (depending on how efficient you want to be). In my shader below I visualize the gradient, but the function color_from_height should get the world space height.

// This is a shadertoy example (www.shadertoy.com) which will visualize the 4-colours palette


vec3 color_from_height( const float height )
{
    vec3 terrain_colours[4];
    terrain_colours[0] = vec3(0.0,0.0,0.6);
    terrain_colours[1] = vec3(0.1, 0.3, 0.1);
    terrain_colours[2] =  vec3(0.4, 0.8, 0.4);
    terrain_colours[3] = vec3(1.0,1.0,1.0);
    //vec3 terrain_colours[1] = vec3[1]{ vec3(0,0,0.6)};
    if(height < 0.0)
        return terrain_colours[0];
    else
    {
        float hscaled = height*2.0 - 1e-05; // hscaled should range in [0,2)
        int hi = int(hscaled); // hi should range in [0,1]
        float hfrac = hscaled-float(hi); // hfrac should range in [0,1]
        if( hi == 0)
            return mix( terrain_colours[1],terrain_colours[2],hfrac); // blends between the two colours    
        else
            return mix( terrain_colours[2],terrain_colours[3],hfrac); // blends between the two colours
    }
    return vec3(0.0,0.0,0.0);
}

void main(void)
{
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    vec3 col = color_from_height(uv.y*2.0-1.0);
    gl_FragColor = vec4(col,1.0);
}
added 27 characters in body
Source Link
Babis
  • 920
  • 4
  • 10

It's a simple interpolation. Let's assume that your heights span -1 to 1, 0 is water surface and you have 3 colours: dark green, light green and white. A way to do what you want is to have the following color_from_height function in the pixel or fragment shader (depending on how efficient you want to be):

// This is a shadertoy example (www.shadertoy.com) which will visualize the 4-colours palette


vec3 color_from_height( const float height )
{
    vec3 terrain_colours[4];
    terrain_colours[0] = vec3(0.0,0.0,0.6);
    terrain_colours[1] = vec3(0.1, 0.3, 0.1);
    terrain_colours[2] =  vec3(0.4, 0.8, 0.4);
    terrain_colours[3] = vec3(1.0,1.0,1.0);
    //vec3 terrain_colours[1] = vec3[1]{ vec3(0,0,0.6)};
    if(height < 0.0)
        return terrain_colours[0];
    else
    {
        float hscaled = height*2.0 - 1e-05; // hscaled should range in [0,2)
        int hi = int(hscaled); // hi should range in [0,1]
        float hfrac = hscaled-float(hi); // hfrac should range in [0,1]
        if( hi == 0)
            return mix( terrain_colours[1],terrain_colours[2],hfrac); // blends between the two colours    
        else
            return mix( terrain_colours[2],terrain_colours[3],hfrac); // blends between the two colours
    }
    return vec3(0.0,0.0,0.0);
}

void main(void)
{
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    vec3 col = color_from_height(uv.y*2.0-1.0);
    gl_FragColor = vec4(col,1.0);
}

It's a simple interpolation. Let's assume that your heights span -1 to 1, 0 is water surface and you have 3 colours: dark green, light green and white. A way to do what you want is to have the following in the pixel or fragment shader (depending on how efficient you want to be):

// This is a shadertoy example (www.shadertoy.com) which will visualize the 4-colours palette


vec3 color_from_height( const float height )
{
    vec3 terrain_colours[4];
    terrain_colours[0] = vec3(0.0,0.0,0.6);
    terrain_colours[1] = vec3(0.1, 0.3, 0.1);
    terrain_colours[2] =  vec3(0.4, 0.8, 0.4);
    terrain_colours[3] = vec3(1.0,1.0,1.0);
    //vec3 terrain_colours[1] = vec3[1]{ vec3(0,0,0.6)};
    if(height < 0.0)
        return terrain_colours[0];
    else
    {
        float hscaled = height*2.0 - 1e-05; // hscaled should range in [0,2)
        int hi = int(hscaled); // hi should range in [0,1]
        float hfrac = hscaled-float(hi); // hfrac should range in [0,1]
        if( hi == 0)
            return mix( terrain_colours[1],terrain_colours[2],hfrac); // blends between the two colours    
        else
            return mix( terrain_colours[2],terrain_colours[3],hfrac); // blends between the two colours
    }
    return vec3(0.0,0.0,0.0);
}

void main(void)
{
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    vec3 col = color_from_height(uv.y*2.0-1.0);
    gl_FragColor = vec4(col,1.0);
}

It's a simple interpolation. Let's assume that your heights span -1 to 1, 0 is water surface and you have 3 colours: dark green, light green and white. A way to do what you want is to have the following color_from_height function in the pixel or fragment shader (depending on how efficient you want to be):

// This is a shadertoy example (www.shadertoy.com) which will visualize the 4-colours palette


vec3 color_from_height( const float height )
{
    vec3 terrain_colours[4];
    terrain_colours[0] = vec3(0.0,0.0,0.6);
    terrain_colours[1] = vec3(0.1, 0.3, 0.1);
    terrain_colours[2] =  vec3(0.4, 0.8, 0.4);
    terrain_colours[3] = vec3(1.0,1.0,1.0);
    //vec3 terrain_colours[1] = vec3[1]{ vec3(0,0,0.6)};
    if(height < 0.0)
        return terrain_colours[0];
    else
    {
        float hscaled = height*2.0 - 1e-05; // hscaled should range in [0,2)
        int hi = int(hscaled); // hi should range in [0,1]
        float hfrac = hscaled-float(hi); // hfrac should range in [0,1]
        if( hi == 0)
            return mix( terrain_colours[1],terrain_colours[2],hfrac); // blends between the two colours    
        else
            return mix( terrain_colours[2],terrain_colours[3],hfrac); // blends between the two colours
    }
    return vec3(0.0,0.0,0.0);
}

void main(void)
{
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    vec3 col = color_from_height(uv.y*2.0-1.0);
    gl_FragColor = vec4(col,1.0);
}
Source Link
Babis
  • 920
  • 4
  • 10

It's a simple interpolation. Let's assume that your heights span -1 to 1, 0 is water surface and you have 3 colours: dark green, light green and white. A way to do what you want is to have the following in the pixel or fragment shader (depending on how efficient you want to be):

// This is a shadertoy example (www.shadertoy.com) which will visualize the 4-colours palette


vec3 color_from_height( const float height )
{
    vec3 terrain_colours[4];
    terrain_colours[0] = vec3(0.0,0.0,0.6);
    terrain_colours[1] = vec3(0.1, 0.3, 0.1);
    terrain_colours[2] =  vec3(0.4, 0.8, 0.4);
    terrain_colours[3] = vec3(1.0,1.0,1.0);
    //vec3 terrain_colours[1] = vec3[1]{ vec3(0,0,0.6)};
    if(height < 0.0)
        return terrain_colours[0];
    else
    {
        float hscaled = height*2.0 - 1e-05; // hscaled should range in [0,2)
        int hi = int(hscaled); // hi should range in [0,1]
        float hfrac = hscaled-float(hi); // hfrac should range in [0,1]
        if( hi == 0)
            return mix( terrain_colours[1],terrain_colours[2],hfrac); // blends between the two colours    
        else
            return mix( terrain_colours[2],terrain_colours[3],hfrac); // blends between the two colours
    }
    return vec3(0.0,0.0,0.0);
}

void main(void)
{
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    vec3 col = color_from_height(uv.y*2.0-1.0);
    gl_FragColor = vec4(col,1.0);
}