Visible Light Source Not The Same As Shader

Started by
1 comment, last by NickGravelyn 17 years, 11 months ago
First of all I apologize for making tons of threads, but they're all different topics so that's why I do it. I'm having trouble getting a light source to affect shaded objects where the visible source is. I can't exactly explain with pictures, so you can download the quick demo here. Use WASD and the mouse to move and look around, respectively. The camera starts at (0, 0, 0), right in the middle of the sphere, so just hold S for a few seconds and you'll see the stuff. Basically the problem is that my app is drawing the light source in the scene, but the way the other object is lit by my shader, it appears that either my shader has the wrong coordinates or the visible object is drawn at the wrong position. Here's a bit of code showing how everything is set up:

D3DXVECTOR4 lightSource = D3DXVECTOR4(10.0f, 10.0f, 0.0f, 1.0f);
float lightAngle = D3DX_PI / 128;
D3DXMATRIX lightRotationMatrix;

...

D3DXMatrixIdentity(&lightRotationMatrix);
D3DXMatrixRotationY(&lightRotationMatrix, lightAngle);

...


app.D3DDevice()->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xFF000000, 1.0f, 0);
app.D3DDevice()->BeginScene();

D3DXMATRIX worldMatrix, wvpMatrix;

D3DXVec4Transform(&lightSource, &lightSource, &lightRotationMatrix);
mesh.Shader()->SetVector("lightSource", &lightSource);

mesh.SetTechniqueHandle("DiffuseLighting");
D3DXMatrixIdentity(&worldMatrix);
wvpMatrix = (worldMatrix * app.Camera().ViewMatrix() * app.ProjectionMatrix());
mesh.Shader()->SetMatrix("matWVP", &wvpMatrix);
mesh.Shader()->SetMatrix("matWorld", &worldMatrix);
mesh.Render();

mesh.SetTechniqueHandle("AmbientLighting");
D3DXMatrixIdentity(&worldMatrix);
D3DXMATRIX tMatrix, sMatrix;
D3DXMatrixTranslation(&tMatrix, lightSource.x, lightSource.y, lightSource.z);
D3DXMatrixScaling(&sMatrix, .2, .2, .2);
D3DXMatrixMultiply(&worldMatrix, &sMatrix, &tMatrix);
wvpMatrix = (worldMatrix * app.Camera().ViewMatrix() * app.ProjectionMatrix());
mesh.Shader()->SetMatrix("matWVP", &wvpMatrix);
mesh.Render();

app.D3DDevice()->EndScene();
app.D3DDevice()->Present(NULL, NULL, NULL, NULL);



And here's the shader in case that matters

float4x4 matWVP : WORLDVIEWPROJECTION;
float4x4 matWorld : WORLD;
float4 lightSource;
float4 ambientColor;
float ambientIntensity;
float4 diffuseColor;
float diffuseIntensity;

struct VS_INPUT 
{
   float4 Position : POSITION;
   float3 Normal : NORMAL;
};

struct VS_OUTPUT 
{
   float4 Position : POSITION;
   float3 Light : TEXCOORD1;
   float3 Normal : TEXCOORD2;
};

struct VS_OUTPUT2
{
   float4 Position : POSITION;
};

VS_OUTPUT DiffuseVertexShader(VS_INPUT Input)
{
   VS_OUTPUT Output;

   Output.Position = mul(Input.Position, matWVP);
   float4 lightDir = Output.Position - lightSource;
   Output.Light = normalize(lightDir);
   Output.Normal = -normalize(mul(Input.Normal, matWorld));
   
   return(Output);
}

float4 DiffusePixelShader(float3 Light : TEXCOORD1, float3 Normal : TEXCOORD2) : COLOR0
{
	float4 dc = diffuseIntensity * diffuseColor * dot(Normal, Light);
	float4 ac = ambientIntensity * ambientColor;
	return (dc + ac);
}

VS_OUTPUT2 AmbientVertexShader(VS_INPUT Input)
{
   VS_OUTPUT2 Output;

   Output.Position = mul(Input.Position, matWVP);
   
   return(Output);
}

float4 AmbientPixelShader() : COLOR0
{
	return (1, 1, 1, 1);
}

technique DiffuseLighting
{
   pass Pass_0
   {
      VertexShader = compile vs_2_0 DiffuseVertexShader();
      PixelShader = compile ps_2_0 DiffusePixelShader();
   }
}

technique AmbientLighting
{
	pass Pass_0
	{
		VertexShader = compile vs_2_0 AmbientVertexShader();
		PixelShader = compile ps_2_0 AmbientPixelShader();
	}
}



Advertisement
I couldn't run SimEngine.exe, it just crashes, but I have spotted some erros in DiffuseVertexShader.

You creating a light vector from to positions that are not in the same space. lightSource is in world space and Output.Position is in post-perspective space. You need the current position in world space too and the light vector should point towards the light source:

Output.Light = normalize(lightSource - mul(Input.Position, matWorld)));

And now it's not necessary to negate to normal when transforming it to world space.
That did the trick. You guys around here are awesome. Guess I just needed to work on my shaders a bit more.

This topic is closed to new replies.

Advertisement