Jump to content
  • Advertisement
Sign in to follow this  
noaktree

Dot3 Shader

This topic is 4951 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

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

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

// Shader I/O structs 
// ************************************************************
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; 
};

// Vertex Shader 
// ************************************************************
sPSIN VertexShader(sVSIN VIN)
{	
	// 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;
}

// Pixel Shader 
// ************************************************************
float4 PixelShader(sPSIN PIN) : COLOR

{
	// 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);
	
	// Compute self-shadowing term
   	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    
	{				
		VertexShader 	= compile vs_1_1 VertexShader();		
		PixelShader  	= compile ps_2_0 PixelShader();   
	}  	
}




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


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


// Tangent
float3 T = mul(VIN.Tangent, DEWorld);
// Normal vector
float4 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 this post


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


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


Link to post
Share on other sites
Your solution was successful. Thanks.

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


Link to post
Share on other sites
Guest Anonymous Poster
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 this post


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

Thanks in advance

Share this post


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


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


Link to post
Share on other sites
Quote:
Thanks for the quick reply, So basically your just supplying the rotation section of the matrix to your shaders.
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]

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!