1
\$\begingroup\$

I've been trying to implement a Directional light into an XNA game I'm working on, but for what ever reason, I cannot seem to get the directional light to be a true directional light. Instead, I am stuck with a directional point light. 'Directional Point Light', in this case, means 'each model has a proper directional light applied to it, but the light is coming from a fixed point, instead of an offset position to the model'. What I want is for the directional light to come from a offset of each model, so that each model, regardless of position, will be lit from the same angle.

Ex: If I have 2 cubes (separate models), c1 at (0,0,0) and c2 at (4,0,4), and my light direction as (0, 2, 2), and I am standing at (6, 0, -3) I want to see the top, left (and back, if I could see it) faces of my cubes lit, but instead I get the back, left and top faces of c1 lit, but the right, front, and top faces of c2 light, which isn't what I want.

Current shader code

// Global world variables
float4x4 World;
float4x4 View;
float4x4 Projection;

// Ambient Lighting variables
float3 AmbientColor;
float AmbientIntensity;

// Diffuse Lighting variables
float3 DiffuseColor;
float DiffuseIntensity;
float3 DiffuseLightDirection;

// Texturing variables
Texture ModelTexture;

// Texture sampler
sampler TextureSampler = sampler_state { 
    texture = <ModelTexture> ;
    magfilter = LINEAR;
    minfilter = LINEAR;
    mipfilter= LINEAR;
    AddressU = WRAP;
    AddressV = WRAP;
};

struct StaticLightVSInput
{
    float4 Position : POSITION0;
    float3 Normal : NORMAL0;
    float2 TexCoords : TEXCOORD0;
};

struct StaticLightVSOutput
{
    float4 Position : POSITION0;
    float2 TexCoords : TEXCOORD0;
    float3 Normal : TEXCOORD1;
    float3 CameraView : TEXCOORD4;
}; 

StaticLightVSOutput StaticLightVertexShader( StaticLightVSInput input )
{
    StaticLightVSOutput output;

    // Set output position
    float4 worldPosition = mul( input.Position, World );
    float4 viewPosition = mul( worldPosition, View );
    output.Position = mul( viewPosition, Projection );

    output.TexCoords = input.TexCoords;

    return output;
}

float4 StaticLightPixelShader( StaticLightVSOutput input ) : COLOR0
{
    float4 texColor = tex2D( TextureSampler, input.TexCoords );
    // calculate diffuse light
    float diffuse = saturate(dot( -DiffuseLightDirection, input.Normal )) * DiffuseIntensity * DiffuseColor;
    // calculate specular light  - disabled for now
    float specular = 0; //SpecularIntensity * SpecularColor * max(pow(dotProduct, Shinniness), 0) * diffuse;

    float3 ambient = AmbientIntensity * AmbientColor;
    float3 color = texColor.rgb * saturate( diffuse + ambient + specular );

    return float4 (color.rgb, texColor.a);
}

technique StaticLighting
{
    pass Pass0
    {
        VertexShader = compile vs_2_0 StaticLightVertexShader();
        PixelShader = compile ps_2_0 StaticLightPixelShader();
    }
}

C# code for setting the shader

// set parameters for our shader
objectLightingEffect.Parameters["World"].SetValue(position);
objectLightingEffect.Parameters["View"].SetValue(view);
objectLightingEffect.Parameters["Projection"].SetValue(projection);
// Ambient light
objectLightingEffect.Parameters["AmbientColor"].SetValue(weather.AmbientColor.GetVector3());
objectLightingEffect.Parameters["AmbientIntensity"].SetValue(weather.AmbientIntensity);
// Diffuse light
objectLightingEffect.Parameters["DiffuseColor"].SetValue(weather.SunColor.GetVector3());
objectLightingEffect.Parameters["DiffuseIntensity"].SetValue(weather.SunIntensity);
Vector3 dir = new Vector3(16, 13, 0) + position.Translation;
objectLightingEffect.Parameters["DiffuseLightDirection"].SetValue(dir);
// Texture
objectLightingEffect.Parameters["ModelTexture"].SetValue(texture.Texture);

I've even tried offsetting the lights 'direction' (read: position) by the position matrix of each object, which does nothing

Can someone please tell me what I'm doing wrong/missing? I've spent the past 3 days trying just about every single directional light shader variation Google has managed to find for me, and I can't believe something so simple has to be nearly impossible. I can't find anything related to my problem at all here, on stackoverflow, or on any game development blog/tutorial.

Any help will be greatly appreciated.

\$\endgroup\$
1
\$\begingroup\$

Just set DiffuseLightDirection to a constant unit vector. Don't try to add it to the object's position as you're doing now. This vector represents the direction the light is coming from, not the position of anything. So if it's constant, all the objects will be lit from the same direction.

\$\endgroup\$
  • \$\begingroup\$ Thanks. I originally had it like that, but it still wasn't working. I originally had normal and specular mapping as well, but it was still working as I originally described, even with the DiffuseLightDirection set to a constant. I suspect it might have been something in my normal mapping code, and I introduced the object position to try and fix it, and forgot to backout this change when I started stripping the shader down to find the source of the problem. Dumbass mistake. Good with C#, not so much with HLSL. Thanks anyway. \$\endgroup\$ – Seta Mar 1 '14 at 9:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.