// 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();
}
}
Dot3 Shader
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:
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]
From a quick glance over the code (it's late here & I'm tired), I'd say the following is where the problem lies:
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.
// 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.
That makes sense. Thanks for taking the time! [smile]
I'll have to try it out a little later...it's dinner time.
I'll have to try it out a little later...it's dinner time.
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]
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
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
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
Just planning my first attempts at shaders and wondered what the best approach is.
Thanks
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
Thanks in advance
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.
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
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
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]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement