GLSL p3d_LightSourceParameters structure

Hello,
doesn’t anyone know how are following attributes in p3d_LightSourceParameters structure filled in?

uniform struct p3d_LightSourceParameters {
  // Primary light color.
  vec4 color;

  // Light color broken up into components, for compatibility with legacy shaders.
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  ...
}

It behaves very strange in my shader. I use 2 lights in Panda app (one ambient and one directional which rotates around). In my shader I’m reading 8 lights from the array and summing the results. I’m using ambient, diffuse and specular values to calculate Phong lighting model but I also added functionality for switching between ambient only, diffuse only and specular only lighting modes.

If I use both lights then the ambient and specular values are black (visually). If I disable directional light in Panda app (only ambient light is active) then the ambient value is white and specular value black. In both cases diffuse values seem to be calculated which seems a bit odd -> I would expect for ambient light the diffuse attribute to be a zero vector.

I think worth mentioning that those 2 lights illuminate the object correctly if automatic shader is used.

Here is part of the shader calculating Phong lighting model (based on the OpenGL 4.0 Shading Language Cookbook - only difference is that I’m using multiple light sources and Panda3D):

vec3 phongModel(vec4 pos, vec3 norm) {
    // Calculate light intensity
    vec3 lightIntensity = vec3(0.0);
    
    vec3 cameraVec = normalize(-pos.xyz);
    
    for(int i = 0; i < p3d_LightSource.length(); i++) {
        // Calculation of the vector to the light source
        vec3 sourceVec = normalize(vec3(p3d_LightSource[i].position - pos));
        
        // Reflection vector calculation (r = -s + 2 * dot(s, n) * n)
        vec3 reflectVec = reflect(-sourceVec, norm);
        
        // Assistance variable
        float sDotN = max(dot(sourceVec, norm), 0.0);
        
        // Ambient light component calculation (Ia = La * Ka)
        vec3 aLight = p3d_LightSource[i].ambient.xyz * p3d_Material.ambient.xyz;
        
        // Diffuse light component calculation (Id = Ld * Kd * dot(s, n))
        vec3 dLight = p3d_LightSource[i].diffuse.xyz * p3d_Material.diffuse.xyz * sDotN;
        
        // Specular light component calculation (Is = Ls * Ks * dot(r, v)^f)
        vec3 sLight = sDotN > 0.0 ? \
            p3d_LightSource[i].specular.xyz * p3d_Material.specular * \
            pow(max(dot(reflectVec, cameraVec), 0.0), p3d_Material.shininess) : \
            vec3(0.0);
        
        // Final light intensity calculation (I = Ia + Id + Is)
        lightIntensity += aLight + dLight + sLight;
    }
    
    return lightIntensity;
}

Any help or explanation what am I doing wrong is appreciated.

What video card vendor and model do you have? Which version of Panda3D?

You should note that ambient lights are not handled through the p3d_LightSource mechanism. The reason for this is that the ambient contribution is simply a fixed term (p3d_LightModel.ambient) that is added on top of the total light intensity so it would be inefficient to do all the calculations of regular lights on them.

GPU: NVIDIA GeForce GTX 970
Panda3D: 1.10.3

Yea…so I should use the p3d_LightModel.ambient instead of sum over p3d_LightSource[i].ambient. That makes sense. What is the ambient in p3d_LightSource for then?

So ambient works now. Thanks.

Autoshader (left), ambient only shader (right):

The field is just present for historical reasons, to make it easier to port existing shaders over. Unlike OpenGL, Panda3D lights never had an “ambient” term, since it was deemed an unnecessary feature. It generally suffices to just use the color field.

So do I understand it correctly that color field is used for multiplication like this?

for(int i = 0; i < p3d_LightSource.length(); i++) {
    ...
    // Diffuse light component calculation (Id = Ld * Kd * dot(s, n))
    vec3 dLight = p3d_Material.diffuse.xyz * sDotN;
    
    // Specular light component calculation (Is = Ls * Ks * dot(r, v)^f)
    vec3 sLight = sDotN > 0.0 ? \
        p3d_Material.specular * \
        pow(max(dot(reflectVec, cameraVec), 0.0), p3d_Material.shininess) : \
        vec3(0.0);
    
    lightIntensity += p3d_LightSource[i].color.xyz * (dLight + sLight);
}

lightIntensity += p3d_LightModel.ambient.xyz * p3d_Material.ambient.xyz;

Strange is that I’m still getting non-zero diffuse vector of the light even when only ambient light is active in the scene.