Why do you need 20-40 textures? That's quite a lot and unless they are very small, you'll run into memory problems with that. Anyway, you can't assign them dynamically at runtime (well, you can...but it's complicated and kills performance, so there's no point in doing it). Just assign them at build time. You are creating the object anyway, so why not assign the correct texture based on the current height in the process!?

A custom shader can be created by creating an instance of GLSLShader and assign to an Object3D. For that, you have to write the shader code in glsl...this the shader that i'm using for the terrain:

vertex shader

`attribute vec2 texture0;`

attribute vec2 texture1;

attribute vec2 texture2;

attribute vec2 texture3;

uniform vec4 additionalColor;

uniform vec4 ambientColor;

uniform mat4 modelViewMatrix;

uniform mat4 modelViewProjectionMatrix;

uniform mat4 textureMatrix;

uniform float fogStart;

uniform float fogEnd;

uniform vec3 fogColor;

uniform vec3 lightPositions[8];

uniform vec3 diffuseColors[8];

uniform vec3 specularColors[8];

uniform float shininess;

attribute vec4 position;

attribute vec3 normal;

varying vec2 texCoord0;

varying vec2 texCoord1;

varying vec2 texCoord2;

varying vec2 texCoord3;

varying vec4 vertexColor;

varying vec4 fogVertexColor;

const vec4 WHITE = vec4(1.0,1.0,1.0,1.0);

void main(void)

{

texCoord0=texture0;

texCoord1=texture1*0.5;

texCoord2=texture2;

texCoord3=texture3;

vertexColor = additionalColor+ambientColor;

vec3 vVertex = vec3(modelViewMatrix * position);

vec3 normalEye = normalize(modelViewMatrix * vec4(normal, 0.0)).xyz;

float angle = dot(normalEye, normalize(lightPositions[0] - vVertex));

if (angle > 0.0) {

vertexColor += vec4(diffuseColors[0] * angle + specularColors[0] * pow(angle, shininess),0.0);

}

vertexColor=2.0*vec4(min(WHITE, vertexColor).xyz, 0.5);

float fogWeight = clamp((-vVertex.z - fogStart) / (fogEnd - fogStart), 0.0, 1.0);

fogVertexColor = vec4(fogColor, 0.0) * fogWeight;

fogWeight=1.0-fogWeight;

vertexColor*=fogWeight;

gl_Position = modelViewProjectionMatrix * position;

}

fragment shader

`precision highp float;`

uniform sampler2D textureUnit0;

uniform sampler2D textureUnit1;

uniform sampler2D textureUnit2;

uniform sampler2D textureUnit3;

varying vec2 texCoord0;

varying vec2 texCoord1;

varying vec2 texCoord2;

varying vec2 texCoord3;

varying vec4 vertexColor;

varying vec4 fogVertexColor;

void main (void)

{

vec4 col0 = texture2D(textureUnit0, texCoord0);

vec4 col1 = texture2D(textureUnit1, texCoord1);

vec4 col2 = texture2D(textureUnit2, texCoord2);

vec4 col3 = col2*0.4;

vec4 blend = texture2D(textureUnit3, texCoord3);

float w1=blend.r;

float w2=blend.g;

float w3=blend.b;

gl_FragColor = vertexColor * vec4(((1.0-w1)*(1.0-w2)*(1.0-w3)*col0+col1*w1+col2*w2+col3*w3).rgb, 0.0) + fogVertexColor;

}

If you are a beginner in 3d, i suggest to stay away from shaders if possible. Anyway, a splatting texture is a texture that defines the distribution of other textures on an object based on it's own rgb values. You can see that in the fragment shader posted above. In your case, you might not need this, because you could simply use the height instead.