OK, I just checked in support for custom light shader inputs. You can now do something like this (just a hacked-up test shader, don’t take too many lessons from this):
light = PointLight('abc') # Or Spotlight, or DirectionalLight
light.setColor(...)
light_path = render.attachNewNode(light)
render.setShaderInput("customLight", light_path)
// Custom light shader input, works on all light types except AmbientLight
uniform gl_LightSourceParameters customLight;
uniform struct {
// Sum of all ambient lights
vec4 ambient;
} p3d_LightModel;
uniform struct {
vec4 ambient;
vec4 diffuse;
vec3 specular;
float shininess;
} p3d_Material;
in vec3 vpos;
in vec3 norm;
void main() {
gl_FragColor = p3d_LightModel.ambient * p3d_Material.ambient;
vec3 diff = customLight.position.xyz - vpos * customLight.position.w;
vec3 L = normalize(diff);
vec3 E = normalize(-vpos);
vec3 R = normalize(-reflect(L, norm));
vec4 diffuse = clamp(p3d_Material.diffuse * customLight.diffuse * max(dot(norm, L), 0), 0, 1);
vec4 specular = vec4(p3d_Material.specular, 1) * customLight.specular * pow(max(dot(R, E), 0), gl_FrontMaterial.shininess);
float spotEffect = dot(normalize(customLight.spotDirection), -L);
if (spotEffect > customLight.spotCosCutoff) {
gl_FragColor += (diffuse + specular) / (customLight.constantAttenuation + customLight.linearAttenuation * length(diff) + customLight.quadraticAttenuation * length(diff) * length(diff));
}
}
If you don’t want to use the built-in definition of the gl_LightSourceParameters struct you can just define your own:
struct p3d_LightSourceParameters {
// Ambient is always vec4(0, 0, 0, 1)
vec4 ambient;
// light.get_color()
vec4 diffuse;
// light.get_specular_color()
vec4 specular;
// In case of Spotlight/PointLight, this is the light position in view space, with fourth component 1
// In case of DirectionalLight, this is actually (-dir) with the fourth component set to 0
vec4 position;
// This is the only one that's not actually available
vec4 halfVector;
// Etc blah blah same as OpenGL FFP equivalents
// You can just omit their declaration if you don't need them, they are bound by name
vec3 spotDirection;
float spotExponent;
float spotCutoff;
float spotCosCutoff;
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
};
uniform p3d_LightSourceParameters customLight;
For compactness, you can just define what you need:
uniform struct {
vec4 position;
vec4 diffuse;
} customLight;
Please let me know if this is sufficient for your needs. I can add more attributes if desired. I will be adding p3d_LightSource[i] in the future as a way to access lights that were set via setLight() rather than via setShaderInput().
(The shader input code is a bit messy at the moment, this might go a bit more easily once I start merging in some of the improvements I’ve been working on regarding the shader system, but that’ll have to wait a while.)