Hi, this is an example of a shader that can use to make terrain (derived from Anaël's CustomShaders example) :
uniform bool AlphaTest;
uniform vec4 FogColor;
uniform float FogEnd;
uniform float FogScale;
uniform vec3 MaterialEmit;
uniform float MaterialShininess;
uniform float MaterialOpacity;
uniform vec4 LightPosition[4];
uniform vec3 LightDiffuseProduct[4];
uniform vec3 LightSpecularProduct[4];
uniform vec3 LightSpotDirection[4];
uniform float LightConstantAttenuation[4];
uniform float LightQuadraticAttenuation[4];
uniform float LightSpotCosCutoff[4];
uniform float LightSpotExponent[4];
uniform bool LightActive[4];
uniform sampler2D LightShadowMap[3];
uniform bool LightShadow[3];
uniform float LightShadowBias[3];
uniform float LightShadowBlur[3];
uniform sampler2D Texture[8];
uniform sampler2D RandTexture;
varying vec2 texCoord[8];
varying vec4 shadowCoord[3];
varying vec4 position, normal, tangent;
vec4 texture0 = texture2D(Texture[0], texCoord[0]);
vec4 texture1 = texture2D(Texture[1], texCoord[1]);
vec4 texture2 = texture2D(Texture[2], texCoord[2]);
vec4 texture3 = texture2D(Texture[3], texCoord[3]);
vec4 texture4 = texture2D(Texture[4], texCoord[4]);
vec4 texture5 = texture2D(Texture[5], texCoord[5]);
vec4 texture6 = texture2D(Texture[6], texCoord[6]);
vec4 texture7 = texture2D(Texture[7], texCoord[7]);
float calcule_oppose (float red, float green, float blue)
{
if(red>green)
{
if (red>blue)
{
return (1.0-red);
}
else
{
return (1.0-blue);
}
}
else if(green>blue)
{
return (1.0-green);
}
else
{
return (1.0-blue);
}
}
float red = texture1.x;
float green = texture1.y;
float blue = texture1.z;
float oppose = calcule_oppose(red,green,blue);
vec3 diffuse = MaterialEmit;
vec3 specular = vec3(0.0, 0.0, 0.0);
vec3 nor = normalize(normal.xyz);
vec3 bi = normalize(-cross(normal.xyz, tangent.xyz));
vec3 tan = normalize(tangent.xyz);
vec3 bump = normalize((texture2.xyz*(oppose/(red+green+oppose+blue))+ texture4.xyz*(red/(red+green+oppose+blue))+texture6.xyz*(green/(red+green+oppose+blue))+texture7.xyz*(blue/(red+green+oppose+blue)))* 2.0 - 1.0);
vec3 N = normalize(tan*bump.x + bi*bump.y + nor*bump.z);
vec3 E = normalize(-position.xyz);
float lookup(vec4 shadCoord, sampler2D shadMap, vec2 offSet)
{
float distanceFromLight = texture2D(shadMap, shadCoord.xy + offSet).z;
return step(shadCoord.z, distanceFromLight);
}
float computeShadow(bool shad, vec4 shadCoord, sampler2D shadMap, float shadBias, float shadBlur)
{
float shadow = 1.0;
if(shad)
{
vec4 shadowCoordinateWdivide = shadCoord;
shadowCoordinateWdivide.z -= shadBias;
shadowCoordinateWdivide /= shadowCoordinateWdivide.w;
float blur = (shadBlur*0.01);
vec4 rand = texture2D(RandTexture, (shadowCoordinateWdivide.xy)*(500.0/(shadBlur+1.0)))*2.0 - 1.0;
vec2 d = rand.xy;
d = normalize(d)*blur;
vec2 dp = vec2(d.y, -d.x);
shadow = lookup(shadowCoordinateWdivide, shadMap, rand.zw*blur);
shadow += lookup(shadowCoordinateWdivide, shadMap, d);
shadow += lookup(shadowCoordinateWdivide, shadMap, -d);
shadow += lookup(shadowCoordinateWdivide, shadMap, dp);
shadow += lookup(shadowCoordinateWdivide, shadMap, -dp);
shadow *= 0.2;
}
return shadow;
}
void computeLight(vec3 lightPosition, float constantAttenuation, float quadraticAttenuation, vec3 lightDiffuse, vec3 lightSpecular, vec3 spotDir, float spotCos, float spotExp, bool shad, vec4 shadCoord, sampler2D shadMap, float shadBias, float shadBlur)
{
vec3 lightDir = lightPosition - position.xyz;
vec3 L = normalize(lightDir);
float lambertTerm = max(dot(N, L), 0.0);
if(lambertTerm > 0.0)
{
if(spotCos > 0.0)
{
float spot = dot(spotDir, -L);
if(spot > spotCos)
{
float shadow = computeShadow(shad, shadCoord, shadMap, shadBias, shadBlur);
spot = clamp(pow(spot, spotExp), 0.0, 1.0);
float lightDirLength2 = dot(lightDir, lightDir);
float attenuation = (spot / (constantAttenuation + (lightDirLength2 * quadraticAttenuation)))*shadow;
diffuse = diffuse + (lightDiffuse * lambertTerm * attenuation);
vec3 S = normalize(E + L);
float spec = pow(max(dot(S, N), 0.0), MaterialShininess) * attenuation;
specular = specular + (lightSpecular * spec);
}
}
else
{
float lightDirLength2 = dot(lightDir, lightDir);
float attenuation = (1.0 / (constantAttenuation + (lightDirLength2 * quadraticAttenuation)));
diffuse = diffuse + (lightDiffuse * lambertTerm * attenuation);
vec3 S = normalize(E + L);
float spec = pow(max(dot(S, N), 0.0), MaterialShininess) * attenuation;
specular = specular + (lightSpecular * spec);
}
}
}
void computeLightNoShadow(vec3 lightPosition, float constantAttenuation, float quadraticAttenuation, vec3 lightDiffuse, vec3 lightSpecular, vec3 spotDir, float spotCos, float spotExp)
{
vec3 lightDir = lightPosition - position.xyz;
vec3 L = normalize(lightDir);
float lambertTerm = max(dot(N, L), 0.0);
if(lambertTerm > 0.0)
{
if(spotCos > 0.0)
{
float spot = dot(spotDir, -L);
if(spot > spotCos)
{
spot = clamp(pow(spot, spotExp), 0.0, 1.0);
float lightDirLength2 = dot(lightDir, lightDir);
float attenuation = (spot / (constantAttenuation + (lightDirLength2 * quadraticAttenuation)));
diffuse = diffuse + (lightDiffuse * lambertTerm * attenuation);
vec3 S = normalize(E + L);
float spec = pow(max(dot(S, N), 0.0), MaterialShininess) * attenuation;
specular = specular + (lightSpecular * spec);
}
}
else
{
float lightDirLength2 = dot(lightDir, lightDir);
float attenuation = (1.0 / (constantAttenuation + (lightDirLength2 * quadraticAttenuation)));
diffuse = diffuse + (lightDiffuse * lambertTerm * attenuation);
vec3 S = normalize(E + L);
float spec = pow(max(dot(S, N), 0.0), MaterialShininess) * attenuation;
specular = specular + (lightSpecular * spec);
}
}
}
void main(void)
{
if(LightActive[0])
{
computeLight(
LightPosition[0].xyz,
LightConstantAttenuation[0],
LightQuadraticAttenuation[0],
LightDiffuseProduct[0],
LightSpecularProduct[0],
LightSpotDirection[0],
LightSpotCosCutoff[0],
LightSpotExponent[0],
LightShadow[0],
shadowCoord[0],
LightShadowMap[0],
LightShadowBias[0],
LightShadowBlur[0]
);
if(LightActive[1])
{
computeLight(
LightPosition[1].xyz,
LightConstantAttenuation[1],
LightQuadraticAttenuation[1],
LightDiffuseProduct[1],
LightSpecularProduct[1],
LightSpotDirection[1],
LightSpotCosCutoff[1],
LightSpotExponent[1],
LightShadow[1],
shadowCoord[1],
LightShadowMap[1],
LightShadowBias[1],
LightShadowBlur[1]
);
if(LightActive[2])
{
computeLight(
LightPosition[2].xyz,
LightConstantAttenuation[2],
LightQuadraticAttenuation[2],
LightDiffuseProduct[2],
LightSpecularProduct[2],
LightSpotDirection[2],
LightSpotCosCutoff[2],
LightSpotExponent[2],
LightShadow[2],
shadowCoord[2],
LightShadowMap[2],
LightShadowBias[2],
LightShadowBlur[2]
);
if(LightActive[3])
{
computeLightNoShadow(
LightPosition[3].xyz,
LightConstantAttenuation[2],
LightQuadraticAttenuation[3],
LightDiffuseProduct[3],
LightSpecularProduct[3],
LightSpotDirection[3],
LightSpotCosCutoff[3],
LightSpotExponent[3]
);
}
}
}
}
vec4 finalColor = vec4(diffuse*texture0.xyz + specular*(texture3.xyz*(oppose/(red+green+oppose+blue))+ texture5.xyz*(red/(red+green+oppose+blue))), MaterialOpacity*texture0.w);
float fogFactor = clamp((FogEnd + position.z) * FogScale, 0.0, 1.0);
gl_FragColor = mix(FogColor, finalColor, fogFactor);
}
attribute vec3 Vertex;
attribute vec3 Normal;
attribute vec3 Tangent;
attribute vec3 Color;
uniform bool LightShadow[3];
uniform mat4 LightShadowMatrix[3];
uniform mat4 TextureMatrix[8];
uniform mat4 ModelViewMatrix;
uniform mat4 ProjectionMatrix;
uniform mat4 NormalMatrix;
uniform mat4 ProjModelViewMatrix;
varying vec2 texCoord[8];
varying vec4 shadowCoord[3];
varying vec4 position, normal, tangent;
attribute vec2 TexCoord0;
attribute vec2 TexCoord1;
attribute vec2 TexCoord2;
attribute vec2 TexCoord3;
attribute vec2 TexCoord4;
attribute vec2 TexCoord5;
attribute vec2 TexCoord6;
attribute vec2 TexCoord7;
void main(void)
{
if(LightShadow[0]) shadowCoord[0] = LightShadowMatrix[0] * vec4(Vertex, 1.0);
if(LightShadow[1]) shadowCoord[1] = LightShadowMatrix[1] * vec4(Vertex, 1.0);
if(LightShadow[2]) shadowCoord[2] = LightShadowMatrix[2] * vec4(Vertex, 1.0);
normal = NormalMatrix * vec4(Normal, 1.0);
position = ModelViewMatrix * vec4(Vertex, 1.0);
gl_Position = ProjModelViewMatrix * vec4(Vertex, 1.0);
texCoord[0] = (TextureMatrix[0] * vec4(TexCoord0, 1.0, 1.0)).xy;
texCoord[1] = (TextureMatrix[1] * vec4(TexCoord1, 1.0, 1.0)).xy;
texCoord[2] = (TextureMatrix[2] * vec4(TexCoord2, 1.0, 1.0)).xy;
texCoord[3] = (TextureMatrix[3] * vec4(TexCoord3, 1.0, 1.0)).xy;
texCoord[4] = (TextureMatrix[4] * vec4(TexCoord4, 1.0, 1.0)).xy;
texCoord[5] = (TextureMatrix[5] * vec4(TexCoord5, 1.0, 1.0)).xy;
texCoord[6] = (TextureMatrix[6] * vec4(TexCoord6, 1.0, 1.0)).xy;
texCoord[7] = (TextureMatrix[7] * vec4(TexCoord7, 1.0, 1.0)).xy;
tangent = NormalMatrix * vec4(Tangent, 1.0);
}