2
\$\begingroup\$

I have this: terrain

(Right now I have the height map in a x*x size 2D array and a 1D vector too.)

What I am trying to achieve is something like this: target Without using any textures, only plain colors. So basically smooth transitions and some shadow (using shaders). My vertex shader looks like this:

    #version 330 
    layout (location = 0) in vec3 Position;
    layout (location = 1) in vec3 Normal;
    layout (location = 2) in vec3 Color;

    out vec3 fragmentNormal;
    out vec4 ex_color,pos;
    out vec3 N;
    out vec3 v;

    void main () {
    pos= vec4(Position,1);
    ex_color = vec4(Color,1);   
    fragmentNormal = Normal;

    v = vec3(gl_ModelViewMatrix * pos);       
    N = normalize(gl_NormalMatrix * Normal);

    gl_Position = gl_ModelViewProjectionMatrix * vec4(Position,1);

I have normals for all the vertices. Color is set simply in the c++ code based on height.

Here is the fragment shader

    in vec3 N;
    in vec3 v;
    in vec4 ex_color;
    void main(void)
    {
       vec3 L = normalize(gl_LightSource[0].position.xyz - v);   
       vec4 Idiff = gl_FrontLightProduct[0].diffuse * max(dot(N,L), 0.0);  
       Idiff = clamp(Idiff, 0.0, 1.0); 
       gl_FragColor = Idiff*ex_color;
    }

So I guess my problem is what formula should I use to mix the colors. I think I don't need to set the colors in the c++ code but in the shaders.

Update: Here is the wireframe of the terrain. wireframe

Update2: Based on @Babis' answer the result is: enter image description here

So the gradient is not "projected" onto the surface as I would like to do. What could cause this? Maybe my qustion wasn't clear.

\$\endgroup\$
  • \$\begingroup\$ there's a difference between screen Y (what you appear to use for that last pic) and world Y (what you want to use) \$\endgroup\$ – ratchet freak Nov 3 '14 at 11:22
2
\$\begingroup\$

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);
}
\$\endgroup\$
  • \$\begingroup\$ you misunderstood my answer, the height that you need to provide is the "world space height". the screen space height that I used was to visualize the gradient :) \$\endgroup\$ – Babis Nov 3 '14 at 11:06
  • \$\begingroup\$ Thanks I got it :) Now I need to rescale my terrain to [0,1] or modify your solution to my range :) What would you prefer? \$\endgroup\$ – Zoltantan Nov 3 '14 at 17:01
  • \$\begingroup\$ None of the two, really :) you can provide in the shader the maximum height and "normalize" the provided height: norm_height = height/max_height; color_from_height( norm_height ); That way you barely do any changes. \$\endgroup\$ – Babis Nov 3 '14 at 17:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.