View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# Strange normal mapping problem

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

9 replies to this topic

### #1pachesantiago  Members

Posted 06 September 2012 - 02:43 PM

Hy guys, having a little problem here, wich i think is self explanatory:

Im trying to implement a simple normal mapping shader, wich I allready tryed in a program i use to test shaders ( DarkShader) but when i loaded it into my engine, that happend. Got that strange black parts.

string Description = "This shader uses preview lights to produce per pixel normal mapped lighting. This shader requires lights.";
string Thumbnail = "Normal Mapping.png";
//The Extra Data map, contains :
// Red : Seams
// Blue : Specular Power
// Green : Specular Ammount
// The seams data is used to multiply the specs inverse, so the seams arent visible
//--------------
//Untweakables
//--------------
float4x4 WorldViewProj : WorldViewProjection;
float4x4 World : World;
float4x4 WorldT : WorldTranspose;
float4x4 WorldIT : WorldInverseTranspose;
float4 LightPos[8] : LIGHTPOSITION;
float3 LightColor[8] : LIGHTCOLOR;
float3 AmbientColor : AMBIENTCOLOR;
float3 eyepos : CameraPosition;
float time : TIME;
int L_Count : LightCount;
//--------------
//Tweakables
//--------------
int TileRes = 512;
float detailScale
<
string UIWidget = "slider";
float UIMax = 16.0;
float UIMin = 0.1;
float UIStep = 0.01;
> = 5.0f;
float SpecularPower1
<
string UIWidget = "slider";
float UIMax = 15;
float UIMin = 0.001;
float UIStep = 0.0001;
> = 3;
float DetailInfluence
<
string UIWidget = "slider";
float UIMax = 1;
float UIMin = 0.001;
float UIStep = 0.0001;
> = 0.24;
/*
float SeamCorrection
<
string UIWidget = "slider";
float UIMax = 10;
float UIMin = 1;
float UIStep = 0.0001;
> = 2;*/
<
string ResourceName = "";
>;
{
MinFilter = Anisotropic;
MagFilter = Linear;
MipFilter = Linear;
};
texture BaseTex
<
string ResourceName = "";
>;
sampler diffuse_smp = sampler_state
{
Texture = <BaseTex>;
MinFilter = Anisotropic;
MagFilter = Linear;
MipFilter = Linear;
};
texture NormalMap
<
string ResourceName = "";
>;
sampler normalmap_smp = sampler_state
{
Texture = <NormalMap>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
texture NormalMapTile
<
string ResourceName = "";
>;
sampler normalmapTile_smp = sampler_state
{
Texture = <NormalMapTile>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};

struct app_in
{
float4 pos : POSITION;
float3 normal : NORMAL0;
float3 tangent : TANGENT0;
float3 binormal : BINORMAL0;
float2 uv : TEXCOORD0;
};
struct vs_out
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
float3 normal : TEXCOORD1;
float3 tangent : TEXCOORD2;
float3 binormal : TEXCOORD3;
float4 wpos : TEXCOORD4;
float2 uvTile : TEXCOORD5;
};
vs_out VS( app_in IN )
{
vs_out OUT;

float4 pos = mul( IN.pos, WorldViewProj );
OUT.pos = pos;
OUT.wpos = mul( IN.pos, World );
OUT.uv = IN.uv;
OUT.uvTile = IN.uv * detailScale;
float3 normal = normalize(mul(IN.normal.xyz,(float3x3)World ));
float3 tangent = normalize(mul(IN.tangent.xyz,(float3x3)World ));
float3 binormal = normalize(mul(IN.binormal.xyz,(float3x3)World ));

//smooth out the tangents and binormals with the normals
float3 b = normalize(cross( normal,tangent ));
b *= sign(dot(b,binormal));

float3 t = normalize(cross( normal,b ));
t *= sign(dot(t,tangent));

float3 t2 = normalize(cross( normal,binormal ));
t2 *= sign(dot(t2,tangent));

float3 b2 = normalize(cross( normal,t2 ));
b2 *= sign(dot(b2,binormal));

//pass normal, tangent, and binormal to pixel shader
OUT.normal = normal;
OUT.tangent = normalize((t+t2)*0.5);
OUT.binormal = normalize((b+b2)*0.5);

return OUT;
}
float luminance ( float3 rgb )
{
return rgb.r*0.3 + rgb.g*0.59 + rgb.b*0.11;
}
float3 getTexel( float2 p, uniform sampler2D texSamp,uniform int TexRes )
{
TexRes *= 8;

p = p*TexRes + 0.5;
float2 i = floor(p);
float2 f = p - i;
f = f*f*f*(f*(f*6.0-15.0)+10.0);
p = i + f;
p = (p - 0.5)/TexRes;
float3 outValue = tex2D( texSamp, p );
return outValue;
}
float4 PS( vs_out IN, uniform int numLights ) : COLOR
{
float3 color = AmbientColor;

float3 n = normalize(IN.normal);
float3 t = normalize(IN.tangent);
float3 b = normalize(IN.binormal);

//build transpose matrix
float3x3 TangentSpace = {t,b,n};
TangentSpace = transpose(TangentSpace);

n = normalize(tex2D(normalmap_smp, IN.uv)*2 - 1);
//float3 nT = normalize(tex2D(normalmapTile_smp, IN.uvTile)*2 - 1);
float3 nT = normalize(getTexel(IN.uvTile,normalmapTile_smp,TileRes));

float3 e = normalize(eyepos - IN.wpos);
float eyeDist = length(eyepos - IN.wpos);

e = mul(e,TangentSpace);

float4 texColor = tex2D( diffuse_smp, IN.uv );

//cycle through all lights, number depending on technique chosen
for ( int i = 0; i < numLights; i++ )
{
float range = LightPos[i].w;

if ( range > 0 )
{
float3 l = (LightPos[i].xyz);// - IN.wpos.xyz);
l = mul(l,TangentSpace);

//calculate attenuation
float dist = length(l);
float att = saturate((range-dist) / range);

//calculate diffuse lighting
l = normalize(l);
float diffuse = dot(n,l)* 0.5 +0.5;

//caculate specular lighting
float3 h = normalize(l+e);
float spec = pow( saturate(dot(n,h)), SpecularPower1 )*(1-pow(1-diffuse,10));

//calculate diffuse lighting
float diffuseTile = saturate(dot(n,l));

//caculate specular lighting
float specTile = pow( saturate(dot(nT,h)), SpecularPower1 )*(1-pow(1-diffuseTile,10));

float finalSpec = (specTile+(spec-DetailInfluence)/2);

// correct seams

//color += ((diffuse * att * LightColor[i]) + finalSpec  * att * LightColor[i] * smoothstep(0.3,0.6,luminance(texColor.xyz)));
color = diffuse;
}
}

return float4(color,1.0);// * texColor;
}
//choose the technique corresponding to the number of lights in your application
technique PerPixelLighting
{
pass p0
{
VertexShader = compile vs_2_0 VS( );
PixelShader = compile ps_3_0 PS( L_Count );
}
}


a lot of parts are commented, because i was trying to find where the error was. Narrowed it to the N dot L i think, but the odd part is that it worked perfect in the other program.
I ran out of ideas, if someone can help me it would be great.

### #2pachesantiago  Members

Posted 07 September 2012 - 12:26 PM

Anyone?

### #3pachesantiago  Members

Posted 07 September 2012 - 08:20 PM

come one, no one? maybe render states?

### #4phil_t  Members

Posted 08 September 2012 - 01:49 AM

Have you tried debugging it in PIX?

### #5pachesantiago  Members

Posted 08 September 2012 - 05:20 AM

yes, but i dont find anything strange. i mean, i dont know assembler, but i can see the pixel history, and it says that it exited the pixel shader with that color.

### #6phil_t  Members

Posted 08 September 2012 - 08:34 AM

So you see that it exited the pixel shader with the wrong color. Now you can use PIX to step through the shader code for that pixel and figure out why.

### #7JohnnyCode  Members

Posted 09 September 2012 - 04:06 PM

I would say your per vertex tangent space vectors are messed up (as this is an input that differs from Darkshader).

But still, in your shader you transform tangent space vectors to world space, and pass them to pixel shader, thus I think you do the dot product with a worldspace normal and a world space light direction vector.

The most effective and generall way is to

transform a light direction from world to object space (inverse world), and then from object space to texture space (tangent matrix), and, transform the object normal from Object space to texture Space(tangent matrix), pass those two , tx normal and tx light to pixel shader

just dot the two direction vectors.

Your tangent triple should transform from object space to texture space. (byt it can also transform from texture space to even view space, this is done in deffered rendering techniques). Also, if you have smooth normals on verticies, just compute the tangent and have binormal computed just as the cross product of those two in the vertex shader, you then have smooth tangent space, tghough not perpendicular in all directions (but it does not matter, you just can invert the matrix by transponing only and so on then)

### #8pachesantiago  Members

Posted 09 September 2012 - 07:58 PM

I would say your per vertex tangent space vectors are messed up (as this is an input that differs from Darkshader).

But still, in your shader you transform tangent space vectors to world space, and pass them to pixel shader, thus I think you do the dot product with a worldspace normal and a world space light direction vector.

The most effective and generall way is to

transform a light direction from world to object space (inverse world), and then from object space to texture space (tangent matrix), and, transform the object normal from Object space to texture Space(tangent matrix), pass those two , tx normal and tx light to pixel shader

just dot the two direction vectors.

Your tangent triple should transform from object space to texture space. (byt it can also transform from texture space to even view space, this is done in deffered rendering techniques). Also, if you have smooth normals on verticies, just compute the tangent and have binormal computed just as the cross product of those two in the vertex shader, you then have smooth tangent space, tghough not perpendicular in all directions (but it does not matter, you just can invert the matrix by transponing only and so on then)

wow thanks. in the vertex shader, when you say the "object normals" do you mean the normals in the normal map right?
the other thing, about smooth tangent space, I do have the normals smoothed, so i can do as you said. if is not a problem, can you point me to where i can find information on computing tangents? can you also explain a bit or point to documentacion of wath do you mean with "not perpendicular in all directions"?
thanks anyway, that's probably it, if thats it, you just saved me a lot of time

### #9JohnnyCode  Members

Posted 10 September 2012 - 11:35 AM

wow thanks. in the vertex shader, when you say the "object normals" do you mean the normals in the normal map right?

no, I have ment the per vertex normal, not the ones in the texture. Vertex normal is one of the bazic vectors for the tangent triple.

So, you have normals on your verticies, and you know how to compute binormal. tangent is a direction vector which exists in object space and points to the direction of texture coordinates x axis. It is actualy the x axis of texture coordinates expressed in 3d space (object space)

this is a great resource for u:

it laso calculates the handedness of a tangent that you need to decide with wheather cross product between tangent and normal points+ or -
so tangent data is 4 float vector [x,y,z,handedness].

### #10pachesantiago  Members

Posted 10 September 2012 - 01:20 PM

wow thanks. in the vertex shader, when you say the "object normals" do you mean the normals in the normal map right?

no, I have ment the per vertex normal, not the ones in the texture. Vertex normal is one of the bazic vectors for the tangent triple.

So, you have normals on your verticies, and you know how to compute binormal. tangent is a direction vector which exists in object space and points to the direction of texture coordinates x axis. It is actualy the x axis of texture coordinates expressed in 3d space (object space)

this is a great resource for u: