here is my terrain multitexturing shader!

the terrain needs 3 textures:
  • 1. tiled - tiling can be specified with entity skill41(u) and skill42(v)
  • 2. tiled - tiling can be specified with entity skill43(u) and skill44(v)
  • 3. not tiled - this texture's alpha channel specifies how the first two textures get blended. (the pixelshader additionally adds (signed) this texture's color channels but you could comment out this line if you don't need this.)

with some changes it would also be possible to blend the textures depending on the terrain's slope instead of the alpha channel.

Code:
material mat_terrain_multitexture

{
effect=
"
texture texSkin1;
texture texSkin2;
texture texSkin3;

matrix matWorldViewProj;
matrix matWorld;
matrix matWorldView;

vector vecSunDir;
vector vecDiffuse;
vector vecAmbient;
vector vecLight;
vector vecFog;
vector vecSkill41;

technique multitexture
{
pass p0
{
Texture[0]=<texSkin1>;
Texture[1]=<texSkin2>;
Texture[2]=<texSkin3>;

MagFilter[2]=linear;
MinFilter[2]=linear;
MipFilter[2]=linear;

ZWriteEnable=true;

VertexShaderConstant[0]=<matWorldViewProj>;
VertexShaderConstant[4]=<matWorld>;
VertexShaderConstant[8]=<matWorldView>;

VertexShaderConstant[16]=<vecSunDir>;
VertexShaderConstant[17]=<vecDiffuse>;
VertexShaderConstant[18]=<vecAmbient>;
VertexShaderConstant[19]=<vecLight>;
VertexShaderConstant[20]=<vecFog>;
VertexShaderConstant[64]=<vecSkill41>; //(u_scale1, v_scale1, u_scale2, v_scale2)
VertexShaderConstant[95]=(0.0f,0.0f,0.0f,0.0f);

VertexShader=
decl
{
stream 0;
float v0[3]; //position
float v3[3]; //normal
float v7[2]; //uv
}
asm
{
vs.1.1
m4x4 oPos,v0,c0 // transform position to clip space

m3x3 r0,v3,c4 // transform normal to world space
dp3 r0.w,r0,r0 // renormalize it
rsq r0.w,r0.w
mul r0,r0,r0.w

dp3 r0,r0,-c16 // normal.light -> lighting constant
mul r0.xyz,r0,c17 // modulate against material diffuse color
add oD0.xyz,r0,c19 // add environment light

mov r1.w,c20.w // r1.w=1
dp4 r0,v0,c10 // distance to camera position
add r0,r0,-c20.x // distance-fog_start
mad r0.x,-r0.x,c20.z,r1.w // 1-(distance-fog_start)*(1/(fog_end-fog_start))
max oFog.x,r0.x,c95.w // clamp with custom max value

mul oT0.xy,v7.xy,c64.xy // output scaled uvs - stage 0
mul oT1.xy,v7.xy,c64.zw // output scaled uvs - stage 1
mov oT2.xy,v7.xy // output uvs - stage 2
};

PixelShader=
asm
{
ps.1.3
def c0,0,0,0,1
tex t0 // sample t0
tex t1 // sample t1
tex t2 // sample t2
lrp r0.rgb,t2.a,t0,t1 // blend t0 with t1 using the alpha channel of t2
+mov r0.a,c0
//add r0.rgb,r0,t2_bias // add(signed) rgb of t2
mul r0.rgb,r0,v0 // modulate with diffuse vertex lighting
};
}
}
";
}

starter mat_terrain_multitexture_init
{
vec_set(mat_terrain_multitexture.ambient_blue,mat_terrain.ambient_blue);
vec_set(mat_terrain_multitexture.diffuse_blue,mat_terrain.diffuse_blue);
vec_set(mat_terrain_multitexture.specular_blue,mat_terrain.specular_blue);
mat_terrain_multitexture.power=mat_terrain.power;
}



i am a beginner with writing shaders so please tell me if you find any mistakes or if you know how to improve it!

i also would like to know if exactly the same thing would be possible with the fixed d3d path? i don't think so because the fixed path is somewhat inflexible...