# Setting up HLSL lighting, rotation & you

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

## Recommended Posts

My goal is simple, take a 3D object that's in model space, translate it to world space and light it based on where the point light is. This isn't that big a deal until you want to rotate this 3D object on more then 1 axis. It's also odd what you have to do to rotate it on the z axis to have it lit correctly. I'm amazed at all the hoops I need to jump through to get this to work correctly which makes me wonder if I'm doing this right. To just place an object in your world and have it lit correctly, all you need to do is invert it's z. Now to be able to rotate it and still have it lit correctly, you have to swap the order in which you handle it's rotation. So if you rotate the position of your object in the order of z,y,x, then the matrix you provide for the lighting needs to be handled in an opposite order (x,y,z). If you rotate only on the z axis, or a combination there of, you need to invert the z sin entries in your lighting matrix. Oy.[wow] So at this point it all works except if you have a 3D object orbit a point and if the object is rotating on a different axis (or multiple axises) then it's orbit axis. Here's my shader.
//-----------------------------------------------------------------------------
// Effect File Variables
//-----------------------------------------------------------------------------

// Lighting only matrix - rigid body transform
// Rotations in x,y,z order, z pos inverted, z sin inverted
float4x4 worldMatrix;
float4x4 worldMatrixTranspose;

// Pos only matrix
// Rotations in z,y,x order, can include scaling
float4x4 worldViewProjMatrix;
texture material;

//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------

// For testing, let's hard code our light position
float3 lightPos = float3(-20.0f, -10.0f, 35.0f);

struct VS_INPUT
{
float4 position	: POSITION;
float2 texture0 : TEXCOORD0;
float3 normal   : NORMAL;
};

struct VS_OUTPUT
{
float4 position : POSITION;
float2 texture0 : TEXCOORD0;
float4 color	: COLOR0;
};

struct PS_OUTPUT
{
float4 color : COLOR;
};

//-----------------------------------------------------------------------------
// Texture samplers
//-----------------------------------------------------------------------------
sampler textureSampler =
sampler_state
{
Texture = <material>;
};

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

{
VS_OUTPUT OUT;

float3 lDir = normalize( lightPos - (float3)mul( IN.position, worldMatrix ) );
float diffuse = max(0.0, dot(lDir, mul( IN.normal, (float3x3)worldMatrixTranspose )));

// for test sake, add some ambient
OUT.color = float4( 0.15, 0.15, 0.15, 1.0 );

if( diffuse > 0.0f )
{
OUT.color += float4( float3( 0.5, 0.5, 0.5 ) * diffuse, 1.0 );
}

OUT.position = mul( IN.position, worldViewProjMatrix );

OUT.texture0 = IN.texture0;

return OUT;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

{
PS_OUTPUT OUT;

OUT.color = tex2D( textureSampler, IN.texture0 ) * IN.color;

return OUT;
}

//-----------------------------------------------------------------------------
// Simple Effect (1 technique with 1 pass)
//-----------------------------------------------------------------------------

technique effect0
{
pass Pass0
{
}
}


[Edited by - howie_007 on March 15, 2010 10:36:31 AM]

##### Share on other sites
Quote:
 My goal is simple, take a 3D object that's in model space, translate it to world space and light it based on where the point light is. This isn't that big a deal until you want to rotate this 3D object on more then 1 axis. It's also odd what you have to do to rotate it on the z axis to have it lit correctly.I'm amazed at all the hoops I need to jump through to get this to work correctly which makes me wonder if I'm doing this right.To just place an object in your world and have it lit correctly, all you need to do is invert it's z. Now to be able to rotate it and still have it lit correctly, you have to swap the order in which you handle it's rotation. So if you rotate the position of your object in the order of z,y,x, then the matrix you provide for the lighting needs to be handled in an opposite order (x,y,z).If you rotate only on the z axis, or a combination there of, you need to invert the z sin entries in your lighting matrix. Oy.[wow]So at this point it all works except if you have a 3D object orbit a point and if the object is rotating on a different axis (or multiple axises) then it's orbit axis.
Hm, none of that sounds right :-S As you note, you shouldn't have to jump through that many hoops (or any hoops at all, really) to apply simple vertex lighting in world space.

float diffuse = max(0.0, dot(lDir, mul( IN.normal, (float3x3)worldMatrixTranspose )));
Why are you transforming the normal using the transpose of the world matrix?

If the world transform for the object is a rigid body transform (i.e. rotation and translation only), you should just be able to use the world transform here. For some transform types you would need to use the inverse transpose of the world matrix, but then you'd also need to renormalize the normal in the shader.

What types of transforms are included in the world transform? Is it just rotation and translation? If so, you might try replacing the transpose world matrix with the world matrix in the above line of code and see if that solves the problem.

##### Share on other sites
Quote:
 Original post by jykWhat types of transforms are included in the world transform? Is it just rotation and translation?
yep.

Quote:
 Original post by jykIf so, you might try replacing the transpose world matrix with the world matrix in the above line of code and see if that solves the problem.
I tested it every which way to Sunday. I've also been looking at the ATI fixed function shader as example code. They do a lot of transposes and inversions to their matrixes which is what gave me the idea to try it, but I must admit I don't fully understand why it needs to be done. Through much experimentation, I came up with what is working now.

Below is a code snippet from the ATI fixed function cpp file. I find it hard to follow what they are doing and why. Comments would have been nice.

//render using programmable shaderm_pEffect->SetTechnique(m_pEffect->GetTechniqueByName("basic_with_shader"));D3DXMATRIXA16 compMat, invMat;m_pEffect->SetMatrixTranspose("matView", &m_matView);D3DXMatrixMultiply(&compMat, &m_matWorld, &m_matView);m_pEffect->SetMatrixTranspose("matWorldView", &compMat);D3DXMatrixInverse(&invMat, NULL, &compMat);D3DXMatrixTranspose(&invMat, &invMat);m_pEffect->SetMatrixTranspose("matWorldViewIT", &invMat);D3DXMatrixInverse(&invMat, NULL, &m_matView);D3DXMatrixTranspose(&invMat, &invMat);m_pEffect->SetMatrixTranspose("matViewIT", &invMat);D3DXMatrixMultiply(&compMat, &compMat, &m_matProj);m_pEffect->SetMatrixTranspose("matWorldViewProj", &compMat);m_pEffect->SetMatrixTranspose("matProj", &m_matProj);m_pEffect->SetMatrixTranspose("matWorld", &m_matWorld);

Why would you have to re-normalize a vertex normal? It's being sent to DirectX normalized.

Before switching to shaders, I was using the normal DirectX lighting calls and had the same problem so I had to transform the light position to the object in model space. This was one of the reasons for switching to shaders. In my Java/OpenGL engine, OpenGL handles the lighting of objects correctly without any additional work. It's the one thing I like about OpenGL over DirectX.

##### Share on other sites

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

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628663
• Total Posts
2984111

• 10
• 10
• 9
• 9
• 10