I've got a shader that does the texturing, lighting, etc. for my game engine (written on top of MonoGame, in case that's relevant) for my block-terrain-based game (everything is rendered as triangles and each chunk has its own mesh made from logical block objects, recomputed when relevant). I have two versions of this shader, a SM2 one and an SM4 one (for different targets), both do the same thing and are almost identical but I primarily focus on the SM2 one since that is for the primary target.

Anyway, a week or so ago I implemented directional lighting, and it looks fine.. except it seems to fail to take the distance from the light source into account - i.e., every block looks like it's an equal distance from the light source.

I tried setting up some obvious solutions - I was already calculating the direction of the light using a parameter of the light position with the vertex position, so I took an intermediate (pre-normalization) value of this and used it as the distance to modulate the intensity of the light. Sounds good, yeah? Well, it somehow made no difference at all. I can't seem to find a piece of software to help me debug a vertex/pixel shader combo (only lone pixel shaders), so I'm basically stuck thinking through the logic and trying things. That's a familiar debug style for me, but I've been trying for a week or two and haven't come up with anything that has made a difference.

I've since stripped this out of the shader (since it didn't work, and I wanted to just work on other things for a while), but I was calculating the distance in the vertex shader (and passing it to the pixel shader) like this:

float3 final3DPos = mul(inPos, World);
float3 direction = -(final3DPos - LightPosition);
Output.LightDirection = direction;
Output.LightDistance = length(direction);


I also tried setting LightDistance to (abs(distance.x) + abs(distance.z)), with distance being what in the above is LightDistance - I ignored Y since it's constant and figured it would exaggerate the difference between positions.. same effect!

In the pixel shader, LightDirection is normalized before use.

I tried setting the end result as a color made from the distance, and everything ended up black. I tried dividing this by various values in case the numbers were too big and multiplying by 255, and no matter what i did everything was the same color.

I tried just using it in the calculations by dividing by it or deriving a multiplier to use from it, and again every block was lit the same.

I could pass the distance to the light in with the vertex information, but calculating that and sending it in for EVERY VERTEX seems really stupid and unnecessary.. :(

• Directional light does not have a position only a direction. It is usually used to simulate sunlight. I encourage you to use a gpu debugger if you want to continue with this. ;) – János Turánszki Oct 2 '14 at 14:53
• Yes, I'm trying to simulate sunlight. I have a system set up to move the sun position with the time of day. So you're saying that what I have isn't really a directional light anymore? I was really trying to find a way to simulate sunlight without a shadow camera and all of that (had trouble doing that), but I guess it isn't possible to light multiple objects with the same light source properly without some method of occlusion. – Yushatak Oct 2 '14 at 14:59
• If you move your sun position, then you could feed your directional light shader with the direction vector from the sun to the origin (-sunPos). ;) – János Turánszki Oct 2 '14 at 15:33
• Please post the structure of Output; specifically the semantics assigned. Also, PIX will debug both vertices and pixels but occasionally feels like it costs more time than it saves. Without using a debugger, set Output.LightDirection to a fixed value (0, 1, 0) and then output that value in your pixel shader; the output color should match (bright green). Do the same for Output.LightDistance. – Jon Feb 11 '15 at 7:32