Now here are two screenshots of my test level: a 26 sided sphere within a hollowed cube.
The sphere without hatching shader:

The sphere with hatch shader (d3d_automaterial = 1):

And the code of the hatching shader:
Code:
function mtl_hatch_init
{
bmap_to_mipmap(mtl.skin1);
bmap_to_mipmap(mtl.skin2);
}
material hatch123 {
skin1=bmp_hatch123;
skin2=bmp_hatch456;
event=mtl_hatch_init;
effect
"
texture mtlSkin1;
texture mtlSkin2;
matrix matWorldViewProj;
matrix matWorld;
vector vecSunDir;
technique hatch
{
pass p0
{
texture[0]=<mtlSkin1>;
texture[1]=<mtlSkin2>;
vertexShaderConstant[16]=<matWorldViewProj>;
vertexShaderConstant[20]=<matWorld>;
vertexShaderConstant[32]=<vecSunDir>;
vertexShaderConstant[48]={2.0,2.0,0.0,0.0}; // u_scale, v_scale, 0, 0
vertexShaderConstant[49]={6.0,6.0,6.0,1.0}; // brightness
vertexshader=
asm
{
vs.1.1
dcl_position v0;
dcl_normal v3;
dcl_texcoord0 v7;
def c0,0,0,0,0
def c1,1,1,1,1
def c2,2,2,2,2
def c3,3,3,3,3
def c4,4,4,4,4
def c5,5,5,5,5
def c6,6,6,6,6
def c7,7,7,7,7
m4x4 oPos,v0,c16 // transform position to clip space
mul oT0.xy,v7.xy,c48.xy // output scaled uvs
mul oT1.xy,v7.xy,c48.xy // output scaled uvs
m3x3 r3,v3,c20 // transform normal to world space
dp3 r3,r3,-c32 // normal.light -> light factor
mul r3,r3,c4 // brightness
mov r5.x,c5.x // seed blend weights
mov r5.y,c4.x
mov r5.z,c3.x
mov r5.w,c0.x
mov r6.x,c2.x
mov r6.y,c1.x
mov r6.z,c0.x
mov r6.w,c0.x
sub r5,r3,r5 // sub each weight's initial value from the light factor
sub r6,r3,r6
max r5,r5,c0 // ged rid of everything below zero
sge r7,c2,r5 // flag weights that are <= 2
mul r5,r5,r7 // zero out weights > 2
sge r7,r5,c1 // flag weights that are >= 1
mul r7,r7,c2 // subtract all weights that are greater than or equal to one from 2
sub r5,r7,r5
slt r7,r5,c0 // flag all weights that are < 0 and negate
sge r8,r5,c0 // flag all spots that are >= 0
add r7,-r7,r8 // add the flags
mul r5,r5,r7 // should negate negatives and leave positives
max r6,r6,c0 // repeat for second set of weights
sge r7,c2,r6
mul r6,r6,r7
sge r7,r6,c1
mul r7,r7,c2
sub r6,r7,r6
slt r7,r6,c0
sge r8,r6,c0
add r7,-r7,r8
mul r6,r6,r7
sge r8,c1,r3 // check for total shadow and clamp on the darkest texture
mov r7,c0
mov r7.z,r8.z
add r6,r6,r7
min r6,r6,c1
mov oT2.xyz,r5 // output 123 weights to uv3
mov oT3.xyz,r6 // output 456 weights to uv4
};
pixelshader=
asm
{
ps.1.1
tex t0 // sample t0
tex t1 // sample t1
texcoord t2 // get 123 weights
texcoord t3 // get 456 weights
dp3_sat r0,1-t0,t2 // t0.t2_weights
dp3_sat r1,1-t1,t3 // t1.t3_weights
add_sat r0,r0,r1 // r0+r1
mov_sat r0,1-r0 // complement and saturate
};
}
}
";
}