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..