g_LightDirection not passed to custom shader

Trying to write a basic phong lighting implementation, so I need the light direction. Sure enough, just use the g_LightDirection uniform, right? Nope, it gets passed as (0,0,0,1) vector to the shader, even though there is a directional light in the scene. Any ideas what could cause that?
Another weird thing I noticed while digging through the lighting.j3md source is that g_LightDirection is not defined as a global uniform the shader would need in the j3md, but is still used in the shader itself. What’s up with that?

My j3md:

MaterialDef Simple {
    MaterialParameters {
        Texture2D colorMap
    }
    Technique {
        LightMode MultiPass
        WorldParameters {
            LightDirection
            WorldViewProjectionMatrix
            WorldNormalMatrix
        }
        VertexShader GLSL330 : Shaders/Toon/Toon.vert
        FragmentShader GLSL330 : Shaders/Toon/Toon.frag
    }
}

Toon.vert:

uniform mat3 g_WorldNormalMatrix;
uniform mat4 g_WorldViewProjectionMatrix;

in vec3 inPosition;
in vec3 inNormal;

out vec3 worldNormal;

void main(){
    worldNormal = g_WorldNormalMatrix * inNormal;
    gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
}

Toon.frag:

uniform vec4 g_LightDirection;

in vec3 worldNormal;

void main(){
    float dotProduct = dot(normalize(g_LightDirection.xyz), normalize(worldNormal));
    gl_FragColor = vec4(0.1, 0.1, 1.0, 1.0) * max(0.0, dotProduct);
}

I tried displaying just the worldNormal (which displays as it should) and g_LightDirection (which displays completely black, but not transparent) as colors, but it didn’t really help me finding the source of this.

When in doubt for stuff like this, I look at a shader that works… like Lighting.j3md.

In this case, it seems to e using g_LightPosition… which has some extra data packed into it.

I don’t know why it doesn’t use g_LightDirection but historically DirectionalLight used to be thought of us “the position that the light is shining from”… which is kind of backwards because a directional light has no position. Over time we changed the interpretation to be direction based.

I’ve switched to g_LightPosition in combination with lightComputeDir() from Lighting.glsllib and while it works perfectly for point lights, directional lights give a wrong direction. In what variable exactly is the light type that I should feed into lightComputeDir() stored? Currently I’m using g_LightColor.w.

Point light (I didn’t implement the falloff yet):

The non working directional light:

EDIT: Seems like the desync is a SDK issue, since it also happens with stock shaders.

I recommend looking at Lighting.vert as that’s all I’d be cutting/pasting from at this point.

Issue solved?

Well yes, but actually no

I got my shader working using g_LightPosition and I’ve fixed the sdk bug that made directional lights point in the wrong direction, but the source of all of this probably remains. g_LightDirection still won’t get passed to the shader.

So now we can either:

a) remove it, since there are other ways to get the same information and that way it won’t confuse people trying to make shaders

b) try fixing the fact that it doesn’t get passed.

1 Like

It looks like it is passed, though :thinking:

No idea then, my shader always got a vec4(0.0, 0.0, 0.0, 1.0) no matter what I did with the light.

Oh!

For directional lights:

                    //FIXME : there is an inconstency here due to backward
                    //compatibility of the lighting shader.
                    //The directional light direction is passed in the
                    //LightPosition uniform. The lighting shader needs to be
                    //reworked though in order to fix this.
                    tmpLightDirection.set(0, 0, 0, 0);
                    lightDir.setValue(VarType.Vector4, tmpLightDirection);

It seems it is only used for spot lights, are the current shaders still using it? If not i think we can either remove it or mark it as deprecated.
It’s still used by spot lights.

IMO the entire multipass logic should be considered as for backward compatibility only, with modern hardware the single pass lighting is probably always a much better choice.

That’s because spotlights need position and direction.

But the non-use of direction for directional light is related to this: