Jump to content
  • Advertisement
Sign in to follow this  
BPD

My bump mapping shaders are giving me strange results

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

If you intended to correct an error in the post then please contact us.

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;
	AddressU = Wrap;
	AddressV = Wrap;
};

//bump-mapping pass vertex shader
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;
}
//bump-mapping pass pixel shader
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;
}
Any help you can give me would be greatly appreciated. Thanks.

Share this post


Link to post
Share on other sites
Advertisement
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.

[edit]

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 this post


Link to post
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));


Thanks for your reply.

Share this post


Link to post
Share on other sites
Quote:
Original post by BPD


float3 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 this post


Link to post
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 this post


Link to post
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 structure
typedef 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 function
for(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 this post


Link to post
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!