Terrain Multitexturing
From GameStudio Wiki
[edit]
terrain multitexturing shader
the terrain needs three textures:
- colormap1 - tiling can be specified with entity skill41(u) and skill42(v)
- colormap2 - tiling can be specified with entity skill43(u) and skill44(v)
- macromap - 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. adding an additional detailmap or similar things wouldn't be difficult either...
action terrain
{
my.skill41=float(10);
my.skill42=float(20);
my.skill43=float(5);
my.skill44=float(10);
my.flare=off;
my.transparent=off;
my.material=mat_terrain_multitexture;
}
material mat_terrain_multitexture
{
effect=
"
texture entSkin1;
texture entSkin2;
texture entSkin3;
matrix matWorldViewProj;
matrix matWorld;
matrix matWorldView;
vector vecSunDir;
vector vecDiffuse;
vector vecAmbient;
vector vecLight;
vector vecFog;
vector vecSkill41;
technique multitexture
{
pass p
{
texture[0]=<entSkin1>; // colormap1
texture[1]=<entSkin2>; // colormap2
texture[2]=<entSkin3>; // macromap
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
mul oT0.xy,v7.xy,c64.xy // output scaled uvs - colormap1
mul oT1.xy,v7.xy,c64.zw // output scaled uvs - colormap2
mov oT2.xy,v7.xy // output uvs - macromap
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
};
pixelShader=
asm
{
ps.1.3
def c0,0,0,0,1
tex t0 // sample colormap1
tex t1 // sample colormap2
tex t2 // sample macromap
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
};
}
}
";
}
another multitexturing example, this time with three tiled textures and with pixel shader version 1.1 for geforce3 compatibility. the blue channel of the macro map controls where the third texture appears.
material mtl_multitexture
{
effect=
"
texture entSkin1;
texture entSkin2;
texture entSkin3;
texture entSkin4;
matrix matWorldViewProj;
matrix matWorld;
matrix matWorldView;
vector vecSunDir;
vector vecFog;
technique multitexture
{
pass p0
{
Texture[0]=<entSkin1>; // colormap1
Texture[1]=<entSkin2>; // colormap2
Texture[2]=<entSkin3>; // colormap3
Texture[3]=<entSkin4>; // macromap
magFilter[2]=linear;
minFilter[2]=linear;
mipFilter[2]=linear;
magFilter[3]=linear;
minFilter[3]=linear;
mipFilter[3]=linear;
zWriteEnable=true;
vertexShaderConstant[0]=<matWorldViewProj>;
vertexShaderConstant[4]=<matWorld>;
vertexShaderConstant[8]=<matWorldView>;
vertexShaderConstant[16]=<vecSunDir>;
vertexShaderConstant[20]=<vecFog>;
vertexShaderConstant[64]=(16.0f,32.0f,36.0f,60.0f); // u_scale1,v_scale1,u_scale2,v_scale2
vertexShaderConstant[65]=(8.0f,16.0f,0.0f,0.0f); // u_scale3,v_scale3
vertexShaderConstant[95]=(0.5f,1.0f,2.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 oD0,r0,-c16 // normal.light -> lighting constant
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 - colormap1
mul oT1.xy,v7.xy,c64.zw // output scaled uvs - colormap2
mul oT2.xy,v7.xy,c65.xy // output scaled uvs - colormap3
mov oT3.xy,v7.xy // output uvs - macromap
};
pixelShader=
asm
{
ps.1.1
def c0,1,1,1,1
tex t0 // sample colormap1
tex t1 // sample colormap2
tex t2 // sample colormap3
tex t3 // sample macromap
mov r1,t1
lrp r0.rgb,t3.a,t0,r1 // blend t0 with t1 depending on t3 alpha
+mov r0.a,c0
mov r1.a,t3.b
lrp r0.rgb,r1.a,r0,t2 // blend the result with t2 depending on t3 blue
+mov r0.a,c0
mul r0.rgb,r0,v0 // modulate with diffuse vertex lighting
};
}
}
technique fallback { pass p0 { } }
";
}

