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

## Recommended Posts

I usually can't think of any good forum topics to start, so you can imagine how delighted I am to be posting this now. I have been using this shader for objects that are at (0,0,0). The objects are usually just rotated with an arcball and all works fine. Today I translated the object -50 along X and well... just have a look: Here is the FX file that I am using:
// DELighting structs
// ************************************************************
struct DELight_s
{
int	Type;
bool	Active;
bool	LightingActive;
float4	Position;
float4	Diffuse;
float4	Specular;
float4	Direction;
float	Attenuation;
float	Range;
float	Theta;
float	Phi;
float	Falloff;
};

struct DEAmbient_s
{
bool 	Active;
float4 	Color;
};

// Variables
// ************************************************************
DELight_s		DE1NALight 		: DENALIGHT1;
DEAmbient_s		DEAmbient 		: DEAMBIENTLIGHT;
float4x4		DEWorld			: DEWORLD;
float4x4		DEWorldViewProj	 	: DEWORLDVIEWPERSPECTIVE;
float4x4 		DEViewInverse 		: DEVIEW_INVERSE;

texture NormalTexture : DETEXTURE
<
string name="Dwarf_Normal.tga";
>;

texture ColorTexture : DEBASIC_MATERIAL_TEXTURE;

// The sample state for the basic texture
sampler2D NormalMap = sampler_state
{
Texture 		= (NormalTexture);
MinFilter 		= Linear;
MagFilter		= Linear;
};

// The sample state for the basic texture
sampler2D ColorMap = sampler_state
{
Texture 		= (ColorTexture);
MinFilter 		= Linear;
MagFilter		= Linear;
};

// ************************************************************
struct sVSIN
{
float4 Position 	: POSITION;
float4 Normal   	: NORMAL;
float2 UV		: TEXCOORD0;
float4 Tangent  	: TANGENT;
};

struct sPSIN
{
float4 Position 	: POSITION;
float4 Normal		: COLOR0;
float4 LightVector	: TEXCOORD0;
float2 TexCoord0	: TEXCOORD1;
float2 TexCoord1	: TEXCOORD2;
};

// ************************************************************
{
// Create struct to send to pixel shader
sPSIN OUT = (sPSIN)0;

// Get the Eye Position
float3 World_Eye_Position = DEViewInverse[3].xyz;

// Calculate the transformed world vertex position
float3 World_Vertex_Position = mul(VIN.Position, DEWorld).xyz;

// Calculate light direction from the Nearest Active Light
float3 Light_Direction = World_Vertex_Position - DE1NALight.Position;

// Tangent
float3 T = mul(VIN.Tangent, DEWorld);
// Normal vector
float4 N = mul(VIN.Normal, DEWorld);
// Eye vector
float3 E = normalize(World_Eye_Position - World_Vertex_Position);
// Light vector
float3 L = normalize(-Light_Direction.xyz);
// Compute the tangent rotation matrix
float3 B = cross(T, N);

// Compute the 3x3 tranform from tangent space to object space
float3x3 Object_To_Tangent_Space;
Object_To_Tangent_Space[0] = T;
Object_To_Tangent_Space[1] = B;
Object_To_Tangent_Space[2] = N;

// Transform normal from object space to tangent space
OUT.Normal.xyz = 0.5 *
mul(Object_To_Tangent_Space, N) + 0.5.xxx;

// Transform light vector from object space to tangent space
OUT.LightVector.xyz = 0.5 *
mul(Object_To_Tangent_Space, L.xyz) + 0.5.xxx;

// Pass the calculated vertex position
OUT.Position = mul(VIN.Position, DEWorldViewProj);

// Pass texture coordinates
OUT.TexCoord0 = VIN.UV;
OUT.TexCoord1 = VIN.UV;

return OUT;
}

// ************************************************************

{
// Get the bump normal
float4 Bump_Normal = 2 * (tex2D(NormalMap, PIN.TexCoord0) - 0.5);

// Get the color map color
float4 Texture_Color = tex2D(ColorMap, PIN.TexCoord1);

// Expand iterated normal to [-1,1]
float4 Normal = 2 * (PIN.Normal - 0.5);

// Expand iterated light vector to [-1,1]
float4 Light_Vector = 2 * (PIN.LightVector - 0.5);

float Shadow = saturate(4 * dot(Normal.xyz, Light_Vector.xyz));

// Calculate Annenuation
float Attenuation = 1/DE1NALight.Attenuation;

// Computer diffuse term
float4 Diffuse_Term = Attenuation *
saturate(dot(Bump_Normal.xyz, Light_Vector.xyz)-0.2);

return Texture_Color * (Diffuse_Term * Shadow  + DEAmbient.Color);
}

// Technique
// ************************************************************
technique DETechnique
<float vs=1.1; float ps=2.0;>
{
pass Pass0
{
}
}


I messed around with it a bit and was unable to correct the problem. I'm almost certain that all of the data coming into the shader is good. So I guess this is where you guys tell me what I did wrong. [smile] ...Please! [Edited by - noaktree on March 30, 2005 4:11:56 PM]

##### Share on other sites
From a quick glance over the code (it's late here & I'm tired), I'd say the following is where the problem lies:

// Tangentfloat3 T = mul(VIN.Tangent, DEWorld);		// Normal vectorfloat4 N = mul(VIN.Normal, DEWorld);

DEWorld is a full 4x4 matrix; i.e. one which includes translation.

So your tangent space basis vectors (T and N) are also being translated when you translate your object...

...for tangent space, the light vector should only be rotated (because it's just a direction vector rather than a position). It shouldn't be translated.

Multiplying the tangent and normal by the top left 3x3 of the matrix (rather than the full 4x4) should do the trick.

##### Share on other sites
That makes sense. Thanks for taking the time! [smile]
I'll have to try it out a little later...it's dinner time.

##### Share on other sites
Quote:
 Original post by S1CA...for tangent space, the light vector should only be rotated (because it's just a direction vector rather than a position). It shouldn't be translated.

Ah, tiredness strikes... I'll just correct my maths: the matrix that will result from translating the basis vectors (N, T, B) will shear and/or scale (as well as rotate) the light vector rather than translate it.

A shear/scale of L is as bad as a translation though: L dot N = cos theta*|L|*|N|, if L or N aren't unit, your lighting goes overly dark or light depending on the magnitude of the vectors. Additionally, negative translation of the basis vectors (e.g. -50,0,0) will also cause the light vector (and basis vectors) to point the wrong way. Generally "wrong" looking [wink]

##### Share on other sites

I will send the rotation data as a 3x3 matrix parameter to speed things along.
I've never sent a 3x3 but according to the docs:

"If the destination matrix is smaller than the source matrix, the additional components of the source matrix will be ignored."

So it should be fairly straight forward.

Thanks again,
Neil

##### Share on other sites
As a small side question, looking at your code you use structures to group stuff. Does this help the compiler produce better code, ie less constants/regs used? Also when you set the values in your code do you just set one param with a block of memory the size of the structure or do you need to set each member?

Just planning my first attempts at shaders and wondered what the best approach is.

Thanks

##### Share on other sites
Just a question do you reckon you could post your updated HLSL code as i'm having the exact same problem as you in my normal mapping shader and a little bit of code may save me hours of frustration.

##### Share on other sites
Quote:
 As a small side question, looking at your code you use structures to group stuff. Does this help the compiler produce better code, ie less constants/regs used? Also when you set the values in your code do you just set one param with a block of memory the size of the structure or do you need to set each member?
I'm not sure if sending a struct improves performance in any way. I am sending the whole thing with one call (SetValue()).

Quote:
 Just a question do you reckon you could post your updated HLSL code as i'm having the exact same problem as you in my normal mapping shader and a little bit of code may save me hours of frustration.
The only changes that I've made to the existing code are in these two calls where

// Tangent
float3 T = mul(VIN.Tangent, DEWorld_Rotation33);
// Normal
float3 N = mul(VIN.Normal, DEWorld_Rotation33);

where DEWorld_Rotation33 is a 3x3 matrix containing the world rotation data. As Simon said it's just the world 4x4 matrix without translation and scaling. Hope this helps.

##### Share on other sites
Thanks for the quick reply, So basically your just supplying the rotation section of the matrix to your shaders. so if below is a standard 4x4 Matrix

r00 r01 r02 t0
r10 r11 r12 t1
r20 r21 r22 t2
0 0 0 1

you would chop off the t0 (translation) and 0 rows and columns to leave

r00 r01 r02
r10 r11 r12
r20 r21 r22

just making sure i'm understanding correctly :)

Thanks

##### Share on other sites
Quote:
Not to my "shaders" exactly - It's one of many that I'm passing as parameters. I'm using that matrix to calculate the tangents and normals so I can use them to create my tangent rotation matrix. I pass a full version of the world matrix also as well as others to calculate other parts.

[Edited by - noaktree on March 30, 2005 11:03:00 PM]

1. 1
Rutin
29
2. 2
3. 3
4. 4
5. 5

• 13
• 13
• 11
• 10
• 13
• ### Forum Statistics

• Total Topics
632960
• Total Posts
3009481
• ### Who's Online (See full list)

There are no registered users currently online

×