• 12
• 12
• 9
• 10
• 13

# My bump mapping shaders are giving me strange results

This topic is 3698 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi everyone. I am having a problem with my bump mapping shaders. The problem is a little hard to describe but the phenomenon which I have encountered the most is that pixels with normals facing towards the light source are in shadow while the pixels with normals facing away from the light are lit (the opposite of what should actually happen). These shaders are for DirectX10 and are written in HLSL 4.0.
struct PS_BUMP
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD0;
float3 Normal : TEXCOORD1;
float4 Orig_Pos : TEXCOORD2;
float3 LightDir : TEXCOORD3;
};

//texture sampler
SamplerState samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
};

PS_BUMP bump_VS(float4 Pos : POSITION, float2 Tex : TEXCOORD0, float3 Normal : NORMAL, float3 tangent : TANGENT, float3 bitangent : BITANGENT)
{
PS_BUMP psBump;

float4x4 WorldView = mul(World, View);
float4x4 WorldViewProj = mul(WorldView, Projection);

psBump.Pos = mul(Pos, WorldViewProj);
psBump.Tex = Tex;
psBump.Orig_Pos = mul(Pos, World);
psBump.Normal = normalize(mul(Normal, (float3x3)World));

tangent = mul(tangent, (float3x3)World);
bitangent = mul(bitangent, (float3x3)World);

TBNMatrix = float3x3(tangent,bitangent,psBump.Normal);

psBump.LightDir = local_light_pos - psBump.Orig_Pos;
psBump.LightDir = mul(psBump.LightDir, TBNMatrix);
psBump.LightDir = normalize(psBump.LightDir);

return psBump;
}
float4 bump_PS(PS_BUMP psBump) : SV_TARGET
{
float3 normal = normalize(2.0f * BumpmapTexture.Sample(samLinear, psBump.Tex).rgb - 0.5f);

float DiffuseLightingFactor = clamp(dot(normalize(psBump.LightDir), normal),0,1);

float atten = Attenuation(local_light_pos, psBump.Orig_Pos, local_light_radius);

float4 outColor;
outColor.rgb = local_light_color * DiffuseLightingFactor * atten;

outColor.a = 1.0f;

return outColor;
}


##### Share on other sites
Hi,

float3 normal = normalize(2.0f * BumpmapTexture.Sample(samLinear, psBump.Tex).rgb - 0.5f);

Is this line correct? I mean, you are storing your normals in a RGB-texture and here you unpack the normals.

Your RGB-channels have values between [0..1] so after that line your values are between [-0,5..1,5]. So the -0.5f should be -1.0f.

Even if you normalize the vector, it'll point to wrong direction. It would work if you added some extra round brackets.

Regards!

[Edited by - kauna on February 2, 2008 9:58:11 AM]

##### Share on other sites
Quote:
 Even if you normalize the vector, it'll point to wrong direction. It would work if you added some extra round brackets.

What exactly do you mean? Like this?

float3 normal = normalize((2.0f * BumpmapTexture.Sample(samLinear, psBump.Tex).rgb - 0.5f));

##### Share on other sites
Quote:
 Original post by BPDfloat3 normal = normalize((2.0f * BumpmapTexture.Sample(samLinear, psBump.Tex).rgb - 0.5f));Thanks for your reply.

I think he means like this:
float3 normal = normalize(2.0f * (BumpmapTexture.Sample(samLinear, psBump.Tex).rgb - 0.5f));

That'll give you a range of -1 to 1 instead of -0.5 to 1.5.

##### Share on other sites
Depending on the texture format (evidence suggests its an unsigned type though), your maths is still wrong.

BumpmapTexture.Sample(samLinear, psBump.Tex).rgb will be returning values in the 0.0 to 1.0 range. Multipling by 2.0 will make this 0.0 to 2.0 (funny that!) and then subtracting 0.5 will give you -0.5 to 1.5 which is wrong - it needs to be -1.0 to +1.0.

Simply change the -0.5f to be -1.0f [smile]

hth
Jack

##### Share on other sites
Thank you all for your replies. I changed the 0.5 to 1.0 but the shaders are still not giving me consistent results. It occurs to me that it's possible my tangent and bitangent vectors might be wrong. Here is the function I use to calculate them:

//vertex structuretypedef struct{	D3DXVECTOR3 Pos;	D3DXVECTOR2 Tex;	D3DXVECTOR3 Normal;	D3DXVECTOR3 Tangent;	D3DXVECTOR3 Bitangent;}Vertex;struct Triangle{	unsigned short index[3];};void CalculateTangentArray(int vertexCount, Vertex * vertices, int triangleCount, const Triangle * triangles){	D3DXVECTOR3 * tan1 = new D3DXVECTOR3[vertexCount * 2];	D3DXVECTOR3 * tan2 = tan1 + vertexCount;			for(int a = 0; a < triangleCount; a++)	{		int i1 = triangles[a].index[0];		int i2 = triangles[a].index[1];		int i3 = triangles[a].index[2];		D3DXVECTOR3 v1 = vertices[i1].Pos;		D3DXVECTOR3 v2 = vertices[i2].Pos;		D3DXVECTOR3 v3 = vertices[i3].Pos;		D3DXVECTOR2 w1 = vertices[i1].Tex;		D3DXVECTOR2 w2 = vertices[i2].Tex;		D3DXVECTOR2 w3 = vertices[i3].Tex;		float x1 = v2.x - v1.x;		float x2 = v3.x - v1.x;		float y1 = v2.y - v1.y;		float y2 = v3.y - v1.y;		float z1 = v2.z - v1.z;		float z2 = v3.z - v1.z;		float s1 = w2.x - w1.x;		float s2 = w3.x - w1.x;		float t1 = w2.y - w1.y;		float t2 = w3.y - w1.y;		float r = 1.0f / (s1 * t2 - s2 * t1);		D3DXVECTOR3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);		D3DXVECTOR3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);		tan1[i1] += sdir;		tan1[i2] += sdir;		tan1[i3] += sdir;		tan2[i1] += tdir;		tan2[i2] += tdir;		tan2[i3] += tdir;	}	for(int a = 0; a < vertexCount; a++)	{		D3DXVECTOR3 n = vertices[a].Normal;		D3DXVECTOR3 t = tan1[a];		//Gram-Schmidt orthogonalize		//D3DXVec3Normalize(&vertices[a].Tangent,new D3DXVECTOR3(t - n * D3DXVec3Dot(&n, &t)));		D3DXVECTOR3 Tan((t - n * D3DXVec3Dot(&n, &t)));		vertices[a].Tangent.x = Tan.x;		vertices[a].Tangent.y = Tan.y;		vertices[a].Tangent.z = Tan.z;		D3DXVec3Normalize(&vertices[a].Tangent, &vertices[a].Tangent);	}	delete[] tan1;}//calculate bitangents//New_mesh supplies the input parameters for the CalculateTangentArray functionfor(int q = 0; q < New_mesh.num_vertices; q++){	D3DXVec3Cross(&New_mesh.vertices[q].Bitangent, &New_mesh.vertices[q].Normal, &New_mesh.vertices[q].Tangent);	D3DXVec3Normalize(&New_mesh.vertices[q].Bitangent, &New_mesh.vertices[q].Bitangent);}

This code is based on the function from www.terathon.com/code/tangent.php

I used this code because when I asked people at the XNA forums about how to calculate tangent space vectors, I was told that this is more or less the standard way of doing it (I've seen some other ways of doing it as well). Other than incorrect tangent and bitangent vectors, I really don't know what else could be wrong with my program. I've scoured the web and tried to base my shaders off the examples I've found (notwithstanding the 0.5 error). Anyway, thanks for all of your help; I really do appreciate it.

##### Share on other sites
I can't see anything else obvious via simple static code analysis.

I suggest you put your printf() debugging hat on and go back to basic principles. Output intermediary values, put in additional checks, break down the shader to the smallest incorrect fragment etc..etc..

Creating some known sample data is essential as you can work out what the result should be and compare that against what you're actually getting.

You can use things like PIX, but I've often found it easier just to go the printf route.

Jack