Original Post
Ok, I started DirectX prgramming few days ago and now I have a problem in calculating normalized light for normal mapping. The problem is that there is no smooth transition between the area which is lit with directional light and one which only has ambient term. The shader code is:
float4x4 World;
float4x4 ViewProjection;
float4x4 worldInverseTransposeMatrix;
float3 cameraPos;
float4 materialSpecular = float4(0.9f, 0.9f, 0.9f, 1.0f);
float2 scaleBias = float2(0.05f, -0.05f);
float Time = 0;
float magnitude = 0;
float shininess = 40.0f;
texture BaseTexture;
texture NormalMapTexture;
texture HeightMapTexture;
sampler2D heightMapSampler = sampler_state
{
Texture =;
MagFilter = Linear;
MinFilter = Anisotropic;
MipFilter = Linear;
MaxAnisotropy = 16;
};
sampler2D normalMapSampler = sampler_state
{
Texture =;
MagFilter = Linear;
MinFilter = Anisotropic;
MipFilter = Linear;
MaxAnisotropy = 16;
};
sampler2D baseSampler = sampler_state
{
Texture =;
ADDRESSU = WRAP;
ADDRESSV = WRAP;
MAGFILTER = LINEAR;
MINFILTER = Anisotropic;
MIPFILTER = LINEAR;
MaxAnisotropy = 16;
};
struct VS_INPUT_TEX
{
float3 Position : POSITION;
float3 Normal : NORMAL;
float2 Texcoord : TEXCOORD0;
float4 tangent : TANGENT;
};
struct VS_OUTPUT_TEX
{
float4 Position : POSITION0;
float2 Texcoord : TEXCOORD0;
float3 halfVector : TEXCOORD2;
float3 lightDir2 : TEXCOORD3;
float3 Normal : TEXCOORD4;
};
float3 lightDir = float3(100, -50, -171);
VS_OUTPUT_TEX VertexShader1(VS_INPUT_TEX IN)
{
float3 worldPos = mul(float4(IN.Position, 1.0f), World).xyz;
float3 eyePosL = mul(float4(cameraPos, 1.0f), worldInverseTransposeMatrix);
float3 lightDir1 = -lightDir;
float3 viewDir = eyePosL - worldPos;
float3 halfVector = normalize(normalize(lightDir1) + normalize(viewDir));
float3 n = mul(IN.Normal, (float3x3)worldInverseTransposeMatrix);
float3 t = mul(IN.tangent.xyz, (float3x3)worldInverseTransposeMatrix);
float3 b = cross(n, t) * IN.tangent.w;
float3x3 tbnMatrix = float3x3(t.x, b.x, n.x,
t.y, b.y, n.y,
t.z, b.z, n.z);
VS_OUTPUT_TEX Output;
float4 vertex = mul(float4(IN.Position, 1.0f), mul(World, ViewProjection));
float amplitude = magnitude * (vertex.y + 20);
float4 wave = amplitude * float4(1.5 * sin(Time + vertex.x),
3 * sin(Time/2),
1.5 * cos(Time + vertex.z),
0);
//vertex = vertex + wave;
Output.Position = vertex;
Output.Texcoord = IN.Texcoord;
Output.halfVector = halfVector;
Output.lightDir2 = mul(lightDir1, tbnMatrix);
Output.Normal = IN.Normal;
return Output;
}
struct PixelShaderOutput
{
float4 Color : COLOR0;
float4 Color1 : COLOR1;
};
float4 PixelShader1(VS_OUTPUT_TEX Input) : COLOR0
{
float3 h = normalize(Input.halfVector);
float2 texCoord = Input.Texcoord;
float3 n = normalize(tex2D(normalMapSampler, texCoord).rgb * 2.0f - 1.0f);
float3 r = reflect(normalize(-Input.lightDir2), n);
float3 l = normalize(Input.lightDir2);
float nDotL = saturate(dot(n, l));
float nDotH = saturate(dot(r, h));
float power = (nDotL == 0.0f) ? 0.0f : pow(nDotH, shininess);
float4 texColor = tex2D(baseSampler, texCoord);
clip(texColor.a - 0.2);
//float3 Normal = normalize(Input.Normal);
float4 finalColor = 0;
float4 Diffuse = (float4(0.8f, 0.8f, 0.8f, 1.0f) * nDotL) + (materialSpecular * power) + float4(0.4f, 0.4f, 0.4f, 1.0f);
finalColor += texColor * Diffuse;
return finalColor;
}
technique Textured
{
pass
{
VertexShader = compile vs_2_0 VertexShader1();
PixelShader = compile ps_2_b PixelShader1();
}
}
And the drawing code:
D3DXHANDLE hTechnique;
hTechnique = effect->GetTechniqueByName("Textured");
if(SUCCEEDED(effect->SetTechnique(hTechnique)))
{
D3DXMATRIX viewProjection, worldMatrix;
D3DXMatrixMultiply(&viewProjection, &V, &projectionMatrix);
if(FAILED(effect->SetMatrix("ViewProjection", &viewProjection)))
{
MessageBox(hWnd, "Error", "Error", MB_OK);
}
D3DXMatrixIdentity(&worldMatrix);
effect->SetMatrix("World", &world);
D3DXMATRIX worldInverseTransposeMatrix;
D3DXMatrixInverse(&worldInverseTransposeMatrix, 0, &world);
D3DXMatrixTranspose(&worldInverseTransposeMatrix, &worldInverseTransposeMatrix);
effect->SetMatrix("worldInverseTransposeMatrix", &worldInverseTransposeMatrix);
effect->SetValue("vecEye", TheCamera.pos, sizeof(D3DXVECTOR3));
UINT numPasses = 0;
effect->Begin(&numPasses, 0);
for(UINT i=0 ; i < numPasses ; i++)
{
effect->BeginPass(i);
for(int x=0 ; x {
effect->SetTexture("BaseTexture", Textures[x]);
effect->SetTexture("NormalMapTexture", NormalMaps[x]);
//effect->SetTexture("HeightMapTexture", HeightMaps[x]);
effect->CommitChanges();
tree->DrawSubset(x);
}
effect->EndPass();
}
effect->End();
}
And the result is :
http://img532.imageshack.us/img532/3410/nosmooth.jpg
Please help, what should I do to get smooth transition. I think the problem is in getting normals??
Thanks.
float4x4 World;
float4x4 ViewProjection;
float4x4 worldInverseTransposeMatrix;
float3 cameraPos;
float4 materialSpecular = float4(0.9f, 0.9f, 0.9f, 1.0f);
float2 scaleBias = float2(0.05f, -0.05f);
float Time = 0;
float magnitude = 0;
float shininess = 40.0f;
texture BaseTexture;
texture NormalMapTexture;
texture HeightMapTexture;
sampler2D heightMapSampler = sampler_state
{
Texture =
MagFilter = Linear;
MinFilter = Anisotropic;
MipFilter = Linear;
MaxAnisotropy = 16;
};
sampler2D normalMapSampler = sampler_state
{
Texture =
MagFilter = Linear;
MinFilter = Anisotropic;
MipFilter = Linear;
MaxAnisotropy = 16;
};
sampler2D baseSampler = sampler_state
{
Texture =
ADDRESSU = WRAP;
ADDRESSV = WRAP;
MAGFILTER = LINEAR;
MINFILTER = Anisotropic;
MIPFILTER = LINEAR;
MaxAnisotropy = 16;
};
struct VS_INPUT_TEX
{
float3 Position : POSITION;
float3 Normal : NORMAL;
float2 Texcoord : TEXCOORD0;
float4 tangent : TANGENT;
};
struct VS_OUTPUT_TEX
{
float4 Position : POSITION0;
float2 Texcoord : TEXCOORD0;
float3 halfVector : TEXCOORD2;
float3 lightDir2 : TEXCOORD3;
float3 Normal : TEXCOORD4;
};
float3 lightDir = float3(100, -50, -171);
VS_OUTPUT_TEX VertexShader1(VS_INPUT_TEX IN)
{
float3 worldPos = mul(float4(IN.Position, 1.0f), World).xyz;
float3 eyePosL = mul(float4(cameraPos, 1.0f), worldInverseTransposeMatrix);
float3 lightDir1 = -lightDir;
float3 viewDir = eyePosL - worldPos;
float3 halfVector = normalize(normalize(lightDir1) + normalize(viewDir));
float3 n = mul(IN.Normal, (float3x3)worldInverseTransposeMatrix);
float3 t = mul(IN.tangent.xyz, (float3x3)worldInverseTransposeMatrix);
float3 b = cross(n, t) * IN.tangent.w;
float3x3 tbnMatrix = float3x3(t.x, b.x, n.x,
t.y, b.y, n.y,
t.z, b.z, n.z);
VS_OUTPUT_TEX Output;
float4 vertex = mul(float4(IN.Position, 1.0f), mul(World, ViewProjection));
float amplitude = magnitude * (vertex.y + 20);
float4 wave = amplitude * float4(1.5 * sin(Time + vertex.x),
3 * sin(Time/2),
1.5 * cos(Time + vertex.z),
0);
//vertex = vertex + wave;
Output.Position = vertex;
Output.Texcoord = IN.Texcoord;
Output.halfVector = halfVector;
Output.lightDir2 = mul(lightDir1, tbnMatrix);
Output.Normal = IN.Normal;
return Output;
}
struct PixelShaderOutput
{
float4 Color : COLOR0;
float4 Color1 : COLOR1;
};
float4 PixelShader1(VS_OUTPUT_TEX Input) : COLOR0
{
float3 h = normalize(Input.halfVector);
float2 texCoord = Input.Texcoord;
float3 n = normalize(tex2D(normalMapSampler, texCoord).rgb * 2.0f - 1.0f);
float3 r = reflect(normalize(-Input.lightDir2), n);
float3 l = normalize(Input.lightDir2);
float nDotL = saturate(dot(n, l));
float nDotH = saturate(dot(r, h));
float power = (nDotL == 0.0f) ? 0.0f : pow(nDotH, shininess);
float4 texColor = tex2D(baseSampler, texCoord);
clip(texColor.a - 0.2);
//float3 Normal = normalize(Input.Normal);
float4 finalColor = 0;
float4 Diffuse = (float4(0.8f, 0.8f, 0.8f, 1.0f) * nDotL) + (materialSpecular * power) + float4(0.4f, 0.4f, 0.4f, 1.0f);
finalColor += texColor * Diffuse;
return finalColor;
}
technique Textured
{
pass
{
VertexShader = compile vs_2_0 VertexShader1();
PixelShader = compile ps_2_b PixelShader1();
}
}
And the drawing code:
D3DXHANDLE hTechnique;
hTechnique = effect->GetTechniqueByName("Textured");
if(SUCCEEDED(effect->SetTechnique(hTechnique)))
{
D3DXMATRIX viewProjection, worldMatrix;
D3DXMatrixMultiply(&viewProjection, &V, &projectionMatrix);
if(FAILED(effect->SetMatrix("ViewProjection", &viewProjection)))
{
MessageBox(hWnd, "Error", "Error", MB_OK);
}
D3DXMatrixIdentity(&worldMatrix);
effect->SetMatrix("World", &world);
D3DXMATRIX worldInverseTransposeMatrix;
D3DXMatrixInverse(&worldInverseTransposeMatrix, 0, &world);
D3DXMatrixTranspose(&worldInverseTransposeMatrix, &worldInverseTransposeMatrix);
effect->SetMatrix("worldInverseTransposeMatrix", &worldInverseTransposeMatrix);
effect->SetValue("vecEye", TheCamera.pos, sizeof(D3DXVECTOR3));
UINT numPasses = 0;
effect->Begin(&numPasses, 0);
for(UINT i=0 ; i < numPasses ; i++)
{
effect->BeginPass(i);
for(int x=0 ; x
effect->SetTexture("BaseTexture", Textures[x]);
effect->SetTexture("NormalMapTexture", NormalMaps[x]);
//effect->SetTexture("HeightMapTexture", HeightMaps[x]);
effect->CommitChanges();
tree->DrawSubset(x);
}
effect->EndPass();
}
effect->End();
}
And the result is :
http://img532.imageshack.us/img532/3410/nosmooth.jpg
Please help, what should I do to get smooth transition. I think the problem is in getting normals??
Thanks.