Hi,
Thanks for all the posts, but I still haven't figured out where the problem is. I think that it has to do with the tangent space. Here are two screenshots where you can see the problem and the source code. I will continue searching for a solution, and if I can manage to find one I will post it.
Up to now I know that:
1. It is not related to calculating the lightDirection in the vertex shader.
2. It's not a problem with the model, because I have tried it with other models and the same thing happens.
float4x4 World;
float4x4 View;
float4x4 Projection;
float3 cameraPosition;
//light properties
float3 lightPosition;
float4 ambientLightColor;
float4 diffuseLightColor;
float4 specularLightColor;
//material properties
float specularPower = 16;
float specularIntensity = 1;
texture2D Texture;
texture2D NormalMap;
texture2D EmissiveMap;
texture2D SpecularMap;
sampler2D DiffuseTextureSampler = sampler_state
{
Texture = <Texture>;
MinFilter = linear;
MagFilter = linear;
MipFilter = linear;
};
sampler2D NormalTextureSampler = sampler_state
{
Texture = <NormalMap>;
MinFilter = linear;
MagFilter = linear;
MipFilter = linear;
};
sampler2D EmissiveTextureSampler = sampler_state
{
Texture = <EmissiveMap>;
MinFilter = linear;
MagFilter = linear;
MipFilter = linear;
};
sampler2D SpecularTextureSampler = sampler_state
{
Texture = <SpecularMap>;
MinFilter = linear;
MagFilter = linear;
MipFilter = linear;
};
struct VertexShaderInput
{
float3 position : POSITION0;
float2 texCoord : TEXCOORD0;
float3 normal : NORMAL0;
float3 binormal : BINORMAL0;
float3 tangent : TANGENT0;
};
struct VertexShaderOutput
{
float4 position : POSITION0;
float2 texCoord : TEXCOORD0;
float3 directionToLight : TEXCOORD1;
float3 viewDirection : TEXCOORD2;
float3x3 tangentToWorld : TEXCOORD3;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output = (VertexShaderOutput)0;
float4x4 wvp = mul(mul(World, View), Projection);
output.position = mul(float4(input.position, 1.0f), wvp);
float4 worldPosition = mul(float4(input.position, 1.0f), World);
output.directionToLight = lightPosition - worldPosition;
output.viewDirection = cameraPosition - worldPosition;
output.tangentToWorld[0] = mul(input.tangent, World);
output.tangentToWorld[1] = mul(input.binormal, World);
output.tangentToWorld[2] = mul(input.normal, World);
output.texCoord = input.texCoord;
return ( output );
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
input.directionToLight = normalize(input.directionToLight);
input.viewDirection = normalize(input.viewDirection);
float3 normalFromMap = normalize(tex2D(NormalTextureSampler, input.texCoord).rgb * 2.0f - 1.0f);
normalFromMap = mul(normalFromMap, input.tangentToWorld);
normalFromMap = normalize(normalFromMap);
//Diffuse
float4 diffuseTexture = tex2D(DiffuseTextureSampler, input.texCoord);
float nDotL = saturate( dot(normalFromMap, input.directionToLight));
float4 diffuse = (2 * diffuseLightColor * nDotL);
//Specular
float4 SpecularTexture = tex2D(SpecularTextureSampler, input.texCoord);
float3 reflectedLight = reflect(-input.directionToLight, normalFromMap);
float rDotV = saturate(dot(reflectedLight, input.viewDirection));
float4 specular = 4 * SpecularTexture * specularLightColor * pow(rDotV, specularPower);
float4 emissive = tex2D(EmissiveTextureSampler, input.texCoord);
return ((ambientLightColor) + diffuse + specular) * diffuseTexture + (2* emissive);
}
technique Render
{
pass Pass0
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
