First, sorry for resurrecting an old thread, but I think I might have figured out what is going on.
I was trying to use light ramping with two thresholds, but it wouldn’t work. After going through the examples (especially Tut-Cartoon-Basic.py), trying makeDoubleThreshold() and some Googling, I ended up here. Using Panda3D 1.8.1, I get the exact same behaviour as reported by the original poster: the double threshold mode works just like the single threshold mode (the parameters t1 and l1 are ignored).
Looking at the source code, I think this is actually a bug in panda/src/pgraph/lightRampAttrib.cxx and panda/src/pgraphnodes/shaderGenerator.cxx.
In lightRampAttrib.cxx of Panda3D 1.8.1, the function LightRampAttrib::make_double_threshold() says
CPT(RenderAttrib) LightRampAttrib::
make_double_threshold(PN_stdfloat thresh0, PN_stdfloat val0, PN_stdfloat thresh1, PN_stdfloat val1) {
LightRampAttrib *attrib = new LightRampAttrib();
attrib->_mode = LRT_single_threshold;
attrib->_threshold[0] = thresh0;
attrib->_level[0] = val0;
attrib->_threshold[1] = thresh1;
attrib->_level[1] = val1;
return return_new(attrib);
}
Note that the attrib mode is set as LRT_singlethreshold. However, for double threshold mode, shaderGenerator.cxx expects LRTdouble_threshold. This is why the parameters for the second threshold are getting ignored.
Additionally, reading through ShaderGenerator::synthesize_shader(), there is a related problem. The shader generator actually expects three levels when an LRT_double_threshold light ramp is active (quoting from shaderGenerator.cxx):
case LightRampAttrib::LRT_double_threshold:
{
PN_stdfloat t0 = light_ramp->get_threshold(0);
PN_stdfloat t1 = light_ramp->get_threshold(1);
PN_stdfloat l0 = light_ramp->get_level(0);
PN_stdfloat l1 = light_ramp->get_level(1);
PN_stdfloat l2 = light_ramp->get_level(2);
text << "\t // Double-threshold light ramp\n";
text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
text << "\t float lr_out = " << l0 << "\n";
text << "\t if (lr_in > " << t0 << ") lr_out=" << l1 << ";\n";
text << "\t if (lr_in > " << t1 << ") lr_out=" << l2 << ";\n";
text << "\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n";
break;
}
However, LightRampAttrib only has two levels available (according to lightRampAttrib.h and lightRampAttrib.I - see the array allocations and the functions LightRampAttrib::get_level(), LightRampAttrib::get_threshold()). Retrieving the level for an out-of-range index returns 0.0 (see LightRampAttrib::get_level() in lightRampAttrib.I). Hence, with the code quoted here, the light level will drop to black when the input is above t1.
To fix this, I propose the following, adapting the approach of the single threshold mode (where the “low” value is always 0.0):
case LightRampAttrib::LRT_double_threshold:
{
PN_stdfloat t0 = light_ramp->get_threshold(0);
PN_stdfloat t1 = light_ramp->get_threshold(1);
PN_stdfloat l0 = light_ramp->get_level(0);
PN_stdfloat l1 = light_ramp->get_level(1);
text << "\t // Double-threshold light ramp\n";
text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
text << "\t float lr_out = 0.0\n";
text << "\t if (lr_in > " << t0 << ") lr_out=" << l0 << ";\n";
text << "\t if (lr_in > " << t1 << ") lr_out=" << l1 << ";\n";
text << "\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n";
break;
}
The only changes are in the levels: 0.0 for less than t0, l0 for between t0 and t1, and l1 for greater than t1. This version matches the Python API documentation for makeDoubleThreshold() ( http://www.panda3d.org/reference/1.8.1/python/classpanda3d.core.LightRampAttrib.php ), and is consistent with the behaviour of makeSingleThreshold().
Finally, a practical question: should I file a bug about this somewhere?