Challenge accepted!
First, you can write a vertex shader that takes a grayscale image and uses it as a heightmap, and includes a varying float (called vAmount
below) to pass to the fragment shader to determine the texture(s) to display(blend) at that point.
uniform sampler2D bumpTexture;
uniform float bumpScale;
varying float vAmount;
varying vec2 vUV;
void main()
{
vUV = uv;
vec4 bumpData = texture2D( bumpTexture, uv );
vAmount = bumpData.r; // assuming map is grayscale it doesn't matter if you use r, g, or b.
// move the position along the normal
vec3 newPosition = position + normal * bumpScale * vAmount;
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
}
Next comes the fragment shader, which can include however many textures you need for different elevations, and there is a great built-in function called smoothstep
that makes smooth transitions much easier to calculate.
An example of code for such a fragment shader:
uniform sampler2D oceanTexture;
uniform sampler2D sandyTexture;
uniform sampler2D grassTexture;
uniform sampler2D rockyTexture;
uniform sampler2D snowyTexture;
varying vec2 vUV;
varying float vAmount;
void main()
{
vec4 water = (smoothstep(0.01, 0.25, vAmount) - smoothstep(0.24, 0.26, vAmount)) * texture2D( oceanTexture, vUV * 10.0 );
vec4 sandy = (smoothstep(0.24, 0.27, vAmount) - smoothstep(0.28, 0.31, vAmount)) * texture2D( sandyTexture, vUV * 10.0 );
vec4 grass = (smoothstep(0.28, 0.32, vAmount) - smoothstep(0.35, 0.40, vAmount)) * texture2D( grassTexture, vUV * 20.0 );
vec4 rocky = (smoothstep(0.30, 0.50, vAmount) - smoothstep(0.40, 0.70, vAmount)) * texture2D( rockyTexture, vUV * 20.0 );
vec4 snowy = (smoothstep(0.50, 0.65, vAmount)) * texture2D( snowyTexture, vUV * 10.0 );
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0) + water + sandy + grass + rocky + snowy;
}
Then you can use a THREE.ShaderMaterial
to use this for a given mesh. The above code is implemented at http://stemkoski.github.io/Three.js/Shader-Heightmap-Textures.html and produces a result like this:
Hope this helps you get started. Happy coding!