Challenge accepted!
First, you can write a vertex shader that takes an image in grayscale and uses it as a height map, and includes a variable float (called vAmount below) to go to the fragment shader to determine the texture to display (blend) in this 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;
Next up is a fragmented shader, which can include as many textures that you need for different heights, and there is a big built-in function called smoothstep that makes it easy to calculate smooth transitions.
Sample 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 THREE.ShaderMaterial to use this for a given grid. The above code is implemented in http://stemkoski.imtqy.com/Three.js/Shader-Heightmap-Textures.html and gives this result:

Hope this helps you get started. Happy coding!