Here's a button I exported from Blender into a .x format: The Button after a Blender-Render

Now here it is in the game with BasicEffect applied to everything: Button with BasicEffect Applied

And now with my custom shader: Hmmm, that's not supposed to do that

And there's the problem. While the surrrounding environment is much brighter (I will get around to doing something about that btw), the button isn't. I'm using the vertex shader to do the lighting calculations. Sharp-eyed observers will notice that the texture is still slightly visible, but that's just ambient lighting. I have no specular lighting, just ambient + diffuse. So I guessed if lighting = ambient, then diffuse must be 0.

Here's my diffuse code:

float4 CombineDiffuseLights(float3 Normal, float3 Position3D)
    float4 lightColour = (0,0,0,0);
    for (int i = 0; i < NumberOfLights; i++)
        float3 LightDirection = normalize(LightPosition[i] - Position3D);
        float DiffuseIntensity = saturate(dot(LightDirection, Normal));  //Where I suspect the problem lies
        lightColour += DiffuseIntensity * DiffuseColour * AttenuationPerLight(Position3D, LightPosition[i]);
    lightColour.a = 1;
    return lightColour;

For the record:

  • Normal = mul(input.Normal, World);
  • Position3D = mul(input.Position, World);
  • DiffuseColour = (1,1,1,1);
  • Everything in the environment is using the same (vertex) shader
  • All normals are the right way around (CULLMODE = CCW;)
  • All LightPositions are going in with correct values

I've also noticed that if I manually set DiffuseIntensity = 1; this happens: Bright, depthless, but relatively OK

Besides the retina-searing brightness, it's proportionally the right shade compared to the environment, but there's no depth (duh, it's all 1). So why on earth is DiffuseIntensity = saturate(dot(LightDirection, Normal)); giving me problems? It's a pretty standard way of finding a diffuse value isn't it? Is it doing something that I'm not aware of or is it a case of 'HLSL: You're doing it wrong!'? Normally I'd have some clue but I am totally stuck on this one.


1 Answer 1


Found it. After days of debugging with PIX, looking through assembly code and reviewing all of my old code samples, it turned out that it wasn't anything in my diffuse code that was wrong, just one of the parameters I passed through. I said I was using:

Normal = mul(input.Normal, World);

but I was assuming that I hadn't non-uniformly scaled anything. As it turns out I should have used:

Normal = mul(input.Normal, WorldInverseTranspose);

It took me a couple of minutes to work it out, but I eventally found that I was using non-uniform scaling, and I was using it on the exact objects that were screwing up. At least now I know what a non-uniformly scaled object looks like without Matrix.Inverse(Matrix.Transpose(objectWorldMatrix)) applied to it.

It's always the little things isn't it...

  • \$\begingroup\$ @Nick I was kinda surprised to find that I had to wait 4 hours to answer, but it's done now. \$\endgroup\$ Dec 31, 2012 at 16:48
  • \$\begingroup\$ @MetaReference it's a precaution in place to prevent people just asking/answering their own questions just to get more rep. \$\endgroup\$
    – ashes999
    Dec 31, 2012 at 17:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .