   Question about basic Phong Shader
  Hello all,I'm going over a tutorial that provides an HLSL vertex and pixel shader for basic Phong lighting.  Most of it makes sense to me, but there is one portion of the vertex shader that I don't get:// transform our normal with matInverseWorld, and normalize itOut.N = normalize(mul(matInverseWorld, N));Why do I need to transform the normal vector by the inverse of the world transform?  To be honest, this is the exact opposite of what I'd expect.  I would think that the normals of the mesh would need to be transofrmed into world space in order to be correctly lit.  Have the normals already been transformed by some process by the time they arrive at the vertex shader?Thanks much for your help!   
  i would assume your source for the shader has the normals in world space and your lighting is being done in object space... if that isn't the case then you have a mismatch in space somewhere in your pipe.the normal method is* Geometry has positions/ Normals in "object" space* Instance of geometry has a "transform"* Vertex Shader transforms from object to world* Lighting in vertex or pixel shader done in world coords.variants all deal with forms of local space lighting (camera space, object space).   ;  Andy, I totally agree with everything you just wrote.  That is what I would assume too.  But the behavior is totally weird.  Here is the complete shader:// Global variables// Can be accessed from outside the shader, using Effect->Parameters["key"] where key = variable namefloat4x4matWorldViewProj;float4x4matInverseWorld; // For calculating normalsfloat4vLightDirection; // Our lights direction// The OUT structure our Vertex Shader will use.struct OUT{float4 Pos: POSITION; // Store transformed position  herefloat3 L:TEXCOORD0; // Store the normalized light direction herefloat3 N:TEXCOORD1; // Store the transformed and normalized normal here};// Our vertex shader, takes the vertex position and vertex normal as inputOUT VertexShader( float4 Pos: POSITION, float3 N: NORMAL ){OUT Out = (OUT) 0;Out.Pos = mul(Pos, matWorldViewProj);// normalize(a) returns a normalized version of a.// in this case, a = vLightDirectionOut.L = normalize(vLightDirection);// transform our normal with matInverseWorld, and normalize itOut.N = normalize(mul(matInverseWorld, N));return Out;}// Our pixelshader. Needs the light direction and normal from the vertex shader.float4 PixelShader(float3 L: TEXCOORD0, float3 N: TEXCOORD1) : COLOR{// Ambient lightfloat Ai = 0.8f;float4 Ac = float4(0.075, 0.075, 0.2, 1.0);// Diffuse lightfloat Di = 1.0f;float4 Dc = float4(1.0, 1.0, 1.0, 1.0);// return Ambient light * diffuse light. See tutorial if// you dont understand this formulareturn Ai * Ac + Di * Dc * saturate(dot(L, N));}// our techniquetechnique DiffuseLight{pass P0{VertexShader = compile vs_1_1 VertexShader();PixelShader = compile ps_1_1 PixelShader();}} My test case is, I have a model that rotates around the Y axis ( Y is up ).  There is also a light direction, defined to be (-1.0,-1.0,-1.0).If I remove the transform by the inverse world matrix, then the lighting will only affect a certain patch of the model, and will follow that patch around as it rotates.  This makes sense; the lighting is being done in Object space here, since I haven't transformed the Normal.But if I render this model using the code as provided, it looks completely correct; the model spins in place, and the light stays put, lighting whatever side of the Object happens to be facing into the direction of the light.  The result implies that the lighting is being done in world space which is what I want, but I have no idea how the code is producing that result.Stranger still, if I modify the code to transform by the world matrix itself ( which is what I would have expected the code to do ), it produces this "swiveling" light that seems to rotate around in circles.I'm not honestly sure what to test here.  Based on Trial #1, the Normal seems to be coming through in Object space, yet I have to mult it by the inverse of the world matrix to get it into what I'd expect to be world space. Any ideas?   ;  Buhhh.... I think I may have just figured out what is causing this.  Appearantly the order in which you pass the elements into the "mul" instruction matters.  In terms of lighting results, this:mul(matInverseWorld, N)... is equivalent to this:mul(N, matWorld)So order matters?  I'll have to look into that instruction in greater depth, perhaps this is reversing row-major-ness or something.  In any case, I'm no longer as worried that I am going crazy.   ;Quote:Original post by jujumburaBuhhh.... I think I may have just figured out what is causing this.  Appearantly the order in which you pass the elements into the "mul" instruction matters.  In terms of lighting results, this:mul(matInverseWorld, N)... is equivalent to this:mul(N, matWorld)So order matters?  I'll have to look into that instruction in greater depth, perhaps this is reversing row-major-ness or something.  In any case, I'm no longer as worried that I am going crazy.Yes, order matters.  If you reverse the argument order, it is analogous to multiplying by the transpose of the matrix.  In the case of transforming a vector, this amounts to the transpose of a rotation matrix, which is the inverse of that transform.  So they nicely put the (inverse(inverse(worldmatrix)) which is really the (worldmatrix).  Nice and simple [grin].