Well, I guess this time I got them working correctly
At least to my eye, they seem to work fine (the only thing I could mention is that on low poly stuff spotlight brightness seems to be too weak).
Here is how my mtl_shaded.fx looks like:
#include <pos>
#include <normal>
#include <lights>
float4x4 matWorldViewProj;
float4 vecViewPos;
float4 vecLightDir[8];
float4 vecSunColor;
float4 vecFog;
float4 vecFogColor;
float4 vecSkill1;
Texture entSkin1;
Texture entSkin2;
sampler ColorSampler = sampler_state
{
Texture = <entSkin1>;
Mipfilter = None;
Minfilter = None;
Magfilter = None;
};
sampler ShadowSampler = sampler_state
{
Texture = <entSkin2>;
Mipfilter = Linear;
Minfilter = Linear;
Magfilter = Linear;
};
struct vertexOut
{
float4 Pos : POSITION;
float4 Color : COLOR0;
float3 Normal : NORMAL;
float4 Tex : TEXCOORD0;
float4 WorldPos : TEXCOORD1;
};
vertexOut VS (
in float4 inPos : POSITION,
in float3 inNormal : NORMAL,
in float2 inTex1 : TEXCOORD0,
in float2 inTex2 : TEXCOORD1
)
{
inPos.w = 1.0f;
vertexOut Out;
// vertex snapping
float4 snapToPixel = mul(inPos, matWorldViewProj);
float4 vertex = snapToPixel;
vertex.xyz = snapToPixel.xyz / snapToPixel.w;
vertex.x = floor((vecSkill1.y + 40) * vertex.x) / (vecSkill1.y + 40); // default 160
vertex.y = floor(vecSkill1.y * vertex.y) / vecSkill1.y; // default 120
vertex.xyz *= snapToPixel.w;
Out.Pos = vertex;
// affine texture mapping
Out.Pos *= inPos.w / length(mul(inPos, matWorldViewProj));
Out.Normal = normalize (mul(inNormal, (float3x3)matWorld));
Out.Tex.xy = inTex1.xy;
Out.Tex.zw = inTex2.xy;
Out.WorldPos = mul(inPos, matWorld);
Out.Color = 0;
float3 P = DoPos(inPos);
float3 N = DoNormal(inNormal);
// multiple dynamic lights
float light = 0;
float lastLight = iLights - vecSunColor.w;
for(; light < lastLight; light += 1.0)
{
// light ray
float3 ray = Out.WorldPos - vecLightPos[light].xyz;
// spotlight factor
float depth = saturate(dot(vecLightDir[light].xyz, ray) / vecLightPos[light].w);
float spot = 1.0 - saturate(length(cross(vecLightDir[light].xyz, ray)) / (vecLightPos[light].w * depth));
// normalize the light ray
float dist = length(ray);
ray /= dist;
// attenuation
float att = 1.0 - saturate(dist / vecLightPos[light].w);
// final light factor
float strength = vecLightDir[light].w ? spot * att : att;
// diffuse term
Out.Color.rgb += vecLightColor[light].rgb * saturate(-dot(ray, inNormal.xyz)) * strength;
}
// cut out polygons
float distance = length(mul(inPos, matWorldViewProj));
if(vecSkill1.z == 0){ vecSkill1.z = 512; }
if (distance > vecSkill1.z)
{
Out.Pos.w = 0;
}
return Out;
}
float4 PS(vertexOut In) : COLOR0
{
float4 textureColor = tex2D(ColorSampler, In.Tex.xy);
float4 color = tex2D(ShadowSampler, In.Tex.zw);
float fDepth = distance(vecViewPos.xyz, In.WorldPos.xyz);
color += In.Color; // add dynamic lights
color.rgb = saturate(color.rgb);
color.rgb = pow(color.rgb, vecSkill1.x);
color.rgb *= textureColor.rgb;
float Fog = saturate((fDepth - vecFog.x) * vecFog.z);
color.rgb = lerp(color.rgb, vecFogColor, Fog);
color.a = 1;
return color;
}
technique mtl_shaded
{
pass one
{
ZWriteEnable = True;
AlphaBlendEnable = False;
AlphaTestEnable = False;
VertexShader = compile vs_3_0 VS();
PixelShader = compile ps_3_0 PS();
}
}
Also, the worldPos I use is float4 and the one used in your example is float3.. I tried to do
float3 ray = Out.WorldPos.xyz - vecLightPos[light].xyz;
instead of
float3 ray = Out.WorldPos - vecLightPos[light].xyz;
but it didn't work, so I left it as it is.
Here you can watch video on youtube (clickable screenshot)
Best regards
Edit: level is dark, that was made intentionally (it can be adjusted to make it very bright if needed).
Also, I noticed that the way you calculate shadows, make them more smooth almost like per pixel lightning, while the original one looked like this
Maybe making them a bit smoother is better.. but just in case, is there an easy way to make them edgier?
Edit2: adding custom strength factor seems to help a lot too!
I'm pretty happy with results! Thank you one more time man!