Jump to content
  • Advertisement
Sign in to follow this  
ryt

My light is pointing in wrong direction

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

This is a picture of a sphere and directional light http://img213.images.../392/sphere.jpg. In code the light direction is set to (-1.0, 1.0, -1.0) but it looks like is set to (-1.0, 1.0, 1.0). I can't find what's wrong.
This is a little of code:

///////////////////////////////// from .cpp
D3DXMatrixIdentity(&g_mWorld);

D3DXVECTOR3 eye(0.0f, 0.0f, -6.0f);
D3DXVECTOR3 at(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMatrixLookAtLH(&g_mView, &eye, &at, &up);

D3DXMatrixPerspectiveFovLH(&g_mProjection, (float)D3DX_PI * 0.25f, (float)g_Width/(float)g_Height, 0.1f, 100.0f);

D3DXVECTOR3 lightDir(-1.0f, 1.0f, -1.0f);
g_pLightDirVariable->SetFloatVector((float*)&lightDir);

///////////////////////////////// effect .fx
// Constant Buffer Variables

matrix g_mProjection;
matrix g_mWorld;
matrix g_mView;
float4 g_vLightDir;


struct VS_INPUT
{
float4 pos : POSITION;
float3 normal : NORMAL;
};

struct PS_INPUT
{
float4 pos : SV_POSITION;
float3 normal : NORMAL;
};

// Vertex Shaders
PS_INPUT VS(VS_INPUT input)
{
PS_INPUT output = (PS_INPUT)0;
output.pos = mul(input.pos, g_mWorld);
output.pos = mul(output.pos, g_mView);
output.pos = mul(output.pos, g_mProjection);
output.normal = mul(input.normal, g_mWorld);

return output;
}

// Pixel Shader
float4 PS(PS_INPUT input) : SV_Target
{
float4 finalColor = 0;
input.normal = normalize(input.normal);
finalColor = saturate(dot(g_vLightDir, input.normal));
finalColor.a = 1;

return finalColor;
}

// Techniques
technique10 Simple
{
pass P0
{
SetVertexShader( CompileShader(vs_4_0, VS()) );
SetGeometryShader(NULL);
SetPixelShader( CompileShader(ps_4_0, PS()) );
}
}

Share this post


Link to post
Share on other sites
Advertisement
Pretty common error, ryt. In your shader, you're dotting the light direction with the normal. If the light is pointing toward the normal (which indicates you want it to be illuminated), you'll get negative numbers. Reverse the direction of the light before you set it to the shader so it's pointing in the same direction as the normals you want to light up.

Share this post


Link to post
Share on other sites
Actualy, I think that is what I did. I want the light to come from a little left, little up and from the viewer so the sphere is lit in front of a viewer. That's why I have put the light direction (-1.0, 1.0, -1.0), the z coord is -1.0 so it should point to the viewer.

Share this post


Link to post
Share on other sites
Your light direction is pointing from the origin in the -X, +Y, -Z direction. That's a little left, a little up and toward the viewer. The viewer is along -Z looking at the origin. It should be correct.

Sorry - hit the wrong key while editing.

Share this post


Link to post
Share on other sites
Yes, that's right (that's from where the light should be comming). But from picture it can be seen that the light is not comming from near the viewer, but opposite, from +Z toward the viewer.

Share this post


Link to post
Share on other sites

Yes, that's right (that's from where the light should be comming). But from picture it can be seen that the light is not comming from near the viewer, but opposite, from +Z toward the viewer.

Sorry. I'm still getting used to this new editor.

First, ensure the normal is correct by changing your vertex shader:

float3 normalW = mul( float4(input.normal,0),g_mWorld).xyz; // direction vs coord conversion
output.normal = normalize(normalW);

Sorry. I have a distraction. I'll be back if needed.

EDIT: I apologize.

Normally, diffuse [strike]shading[/strike] lighting is done in the vertex shader and just the diffuse color is passed to the pixel shader.

I.e., add float4 diffuse : COLOR0 to your vertex shader output and:

float s = max(dot( normalW, g_vLightDir.xyz ), 0); // intensity of light. normalW as calc'd above
// no diffuse material color, so just use intensity for grayscale
output.diffuse = float4( s,s,s,1 );

You might try that with your "reversed" light direction and forget the pixel shader for now.

Share this post


Link to post
Share on other sites
Your light direction is incorrect. If you want the light to be coming in from behind the viewer's top left shoulder, the direction should be (1.0, -1.0, 1.0). This would put the light's position at some multiple of (-1.0, 1.0, -1.0) (Upper left quadrant, behind the origin).

If you are using a light direction, then your diffuse calculation is wrong. Currently, it is expecting a light position vector, rather than a direction vector. When comparing a light direction vector to a normal vector, you want the negative of the dot product result (as the dot between a direction and a normal will result in a negative dot product, and you want it to be positive). Even then, you want to make sure that your lower bound is zero, so you will do something like this:

output.diffuse = max(-dot(normal, LightDirection), 0.0);

Otherwise, you can pass the position of the light and use the normalized vector of the position and take the positive dot product.

Share this post


Link to post
Share on other sites
I have found the error. The sphere had a wrong culling clockwise instead of counter-clockwise, so a back of the sphere was drawn.

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!