diff -Naur '--exclude-from=binaries_and_temp_stuff.txt' panda3d-1.8.1-jj-fixes-base/panda/src/pgraph/lightRampAttrib.cxx panda3d-1.8.1-jj-systematic/panda/src/pgraph/lightRampAttrib.cxx --- panda3d-1.8.1-jj-fixes-base/panda/src/pgraph/lightRampAttrib.cxx 2014-09-26 21:30:44.494983655 +0300 +++ panda3d-1.8.1-jj-systematic/panda/src/pgraph/lightRampAttrib.cxx 2015-01-18 11:11:28.562647575 +0200 @@ -78,6 +78,84 @@ } //////////////////////////////////////////////////////////////////// +// Function: LightRampAttrib::make_single_threshold +// Access: Published, Static +// Description: Constructs a new LightRampAttrib object. This +// causes the luminance of the diffuse (and optionally also specular) +// lighting contribution to be quantized using a single threshold, +// but with linear smoothing of the transition: +// @code +// a = threshold0 - smoothing; +// b = threshold0 + smoothing; +// if (original_luminance > b) { +// luminance = level0; +// } else if (original_luminance < a) { +// luminance = 0.0; +// } +// else +// { +// luminance = lerp(0.0, level0, (original_luminance - a)/(b - a)); +// } +// @endcode +// This version uses the same quantization parameters +// for the diffuse and specular contributions. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) LightRampAttrib:: +make_single_threshold(PN_stdfloat thresh0, PN_stdfloat val0, PN_stdfloat smooth0, bool affect_specular) { + LightRampAttrib *attrib = new LightRampAttrib(); + attrib->_mode = LRT_single_threshold; + attrib->_threshold[0] = thresh0; + attrib->_level[0] = val0; + attrib->_smoothing[0] = smooth0; + attrib->_affect_specular = affect_specular; + if(affect_specular) { + // By default, we use the same quantization parameters + // for the specular contribution as for the diffuse contribution. + attrib->_threshold_specular[0] = thresh0; + attrib->_level_specular[0] = val0; + attrib->_smoothing_specular[0] = smooth0; + } + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: LightRampAttrib::make_single_threshold +// Access: Published, Static +// Description: Constructs a new LightRampAttrib object. This +// causes the luminance of the diffuse (and optionally also specular) +// lighting contribution to be quantized using a single threshold, +// but with linear smoothing of the transition: +// @code +// a = threshold0 - smoothing; +// b = threshold0 + smoothing; +// if (original_luminance > b) { +// luminance = level0; +// } else if (original_luminance < a) { +// luminance = 0.0; +// } +// else +// { +// luminance = lerp(0.0, level0, (original_luminance - a)/(b - a)); +// } +// @endcode +// This version allows specifying different quantization parameters +// for the diffuse and specular contributions. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) LightRampAttrib:: +make_single_threshold(PN_stdfloat thresh0, PN_stdfloat val0, PN_stdfloat smooth0, bool affect_specular, PN_stdfloat thresh0_specular, PN_stdfloat val0_specular, PN_stdfloat smooth0_specular) { + LightRampAttrib *attrib = new LightRampAttrib(); + attrib->_mode = LRT_single_threshold; + attrib->_threshold[0] = thresh0; + attrib->_level[0] = val0; + attrib->_smoothing[0] = smooth0; + attrib->_affect_specular = affect_specular; + attrib->_threshold_specular[0] = thresh0_specular; + attrib->_level_specular[0] = val0_specular; + attrib->_smoothing_specular[0] = smooth0_specular; + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// // Function: LightRampAttrib::make_double_threshold // Access: Published, Static // Description: Constructs a new LightRampAttrib object. This diff -Naur '--exclude-from=binaries_and_temp_stuff.txt' panda3d-1.8.1-jj-fixes-base/panda/src/pgraph/lightRampAttrib.h panda3d-1.8.1-jj-systematic/panda/src/pgraph/lightRampAttrib.h --- panda3d-1.8.1-jj-fixes-base/panda/src/pgraph/lightRampAttrib.h 2011-11-07 02:08:05.000000000 +0200 +++ panda3d-1.8.1-jj-systematic/panda/src/pgraph/lightRampAttrib.h 2015-01-18 11:11:28.562647575 +0200 @@ -46,7 +46,11 @@ static CPT(RenderAttrib) make_default(); static CPT(RenderAttrib) make_identity(); static CPT(RenderAttrib) make_single_threshold(PN_stdfloat thresh0, PN_stdfloat lev0); + static CPT(RenderAttrib) make_single_threshold(PN_stdfloat thresh0, PN_stdfloat lev0, PN_stdfloat smooth0, bool affect_specular); + static CPT(RenderAttrib) make_single_threshold(PN_stdfloat thresh0, PN_stdfloat lev0, PN_stdfloat smooth0, bool affect_specular, PN_stdfloat thresh0_specular, PN_stdfloat lev0_specular, PN_stdfloat smooth0_specular); static CPT(RenderAttrib) make_double_threshold(PN_stdfloat thresh0, PN_stdfloat lev0, PN_stdfloat thresh1, PN_stdfloat lev1); + static CPT(RenderAttrib) make_double_threshold(PN_stdfloat thresh0, PN_stdfloat lev0, PN_stdfloat smooth0, PN_stdfloat thresh1, PN_stdfloat lev1, PN_stdfloat smooth1, bool affect_specular); + static CPT(RenderAttrib) make_double_threshold(PN_stdfloat thresh0, PN_stdfloat lev0, PN_stdfloat smooth0, PN_stdfloat thresh1, PN_stdfloat lev1, PN_stdfloat smooth1, bool affect_specular, PN_stdfloat thresh0_specular, PN_stdfloat lev0_specular, PN_stdfloat smooth0_specular, PN_stdfloat thresh1_specular, PN_stdfloat lev1_specular, PN_stdfloat smooth1_specular); static CPT(RenderAttrib) make_hdr0(); static CPT(RenderAttrib) make_hdr1(); static CPT(RenderAttrib) make_hdr2(); @@ -55,7 +59,12 @@ INLINE LightRampMode get_mode() const; INLINE PN_stdfloat get_level(int n) const; INLINE PN_stdfloat get_threshold(int n) const; - + INLINE PN_stdfloat get_smoothing(int n) const; + INLINE bool get_affect_specular() const; + INLINE PN_stdfloat get_level_specular(int n) const; + INLINE PN_stdfloat get_threshold_specular(int n) const; + INLINE PN_stdfloat get_smoothing_specular(int n) const; + public: virtual void output(ostream &out) const; @@ -68,6 +77,11 @@ LightRampMode _mode; PN_stdfloat _level[2]; PN_stdfloat _threshold[2]; + PN_stdfloat _smoothing[2]; + bool _affect_specular; + PN_stdfloat _level_specular[2]; + PN_stdfloat _threshold_specular[2]; + PN_stdfloat _smoothing_specular[2]; static CPT(RenderAttrib) _default; diff -Naur '--exclude-from=binaries_and_temp_stuff.txt' panda3d-1.8.1-jj-fixes-base/panda/src/pgraph/lightRampAttrib.I panda3d-1.8.1-jj-systematic/panda/src/pgraph/lightRampAttrib.I --- panda3d-1.8.1-jj-fixes-base/panda/src/pgraph/lightRampAttrib.I 2011-10-10 08:25:16.000000000 +0300 +++ panda3d-1.8.1-jj-systematic/panda/src/pgraph/lightRampAttrib.I 2015-01-18 11:11:28.562647575 +0200 @@ -26,6 +26,15 @@ _level[1] = 0.0; _threshold[0] = 0.0; _threshold[1] = 0.0; + _smoothing[0] = 0.0; + _smoothing[1] = 0.0; + _affect_specular = false; + _level_specular[0] = 0.0; + _level_specular[1] = 0.0; + _threshold_specular[0] = 0.0; + _threshold_specular[1] = 0.0; + _smoothing_specular[0] = 0.0; + _smoothing_specular[1] = 0.0; } //////////////////////////////////////////////////////////////////// @@ -59,3 +68,58 @@ if ((n<0)||(n>1)) return 0.0; return _threshold[n]; } + +//////////////////////////////////////////////////////////////////// +// Function: LightRampAttrib::get_smoothing +// Access: Published +// Description: Returns the smoothing value for the nth range (range = threshold +- smoothing). +//////////////////////////////////////////////////////////////////// +INLINE PN_stdfloat LightRampAttrib:: +get_smoothing(int n) const { + if ((n<0)||(n>1)) return 0.0; + return _smoothing[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: LightRampAttrib::get_affect_specular +// Access: Published +// Description: Returns whether this light ramp affects specular lighting. If false, then diffuse only. This parameter only affects quantizing (cartoon shading) light ramps. +//////////////////////////////////////////////////////////////////// +INLINE bool LightRampAttrib:: +get_affect_specular() const { + return _affect_specular; +} + +//////////////////////////////////////////////////////////////////// +// Function: LightRampAttrib::get_level_specular +// Access: Published +// Description: Returns the nth lighting level for the specular contribution. Only relevant if affect_specular is enabled. +//////////////////////////////////////////////////////////////////// +INLINE PN_stdfloat LightRampAttrib:: +get_level_specular(int n) const { + if ((n<0)||(n>1)) return 0.0; + return _level_specular[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: LightRampAttrib::get_threshold_specular +// Access: Published +// Description: Returns the nth threshold level for the specular contribution. Only relevant if affect_specular is enabled. +//////////////////////////////////////////////////////////////////// +INLINE PN_stdfloat LightRampAttrib:: +get_threshold_specular(int n) const { + if ((n<0)||(n>1)) return 0.0; + return _threshold_specular[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: LightRampAttrib::get_smoothing_specular +// Access: Published +// Description: Returns the smoothing value for the nth range (range = threshold +- smoothing) for the specular contribution. Only relevant if affect_specular is enabled. +//////////////////////////////////////////////////////////////////// +INLINE PN_stdfloat LightRampAttrib:: +get_smoothing_specular(int n) const { + if ((n<0)||(n>1)) return 0.0; + return _smoothing_specular[n]; +} + diff -Naur '--exclude-from=binaries_and_temp_stuff.txt' panda3d-1.8.1-jj-fixes-base/panda/src/pgraphnodes/shaderGenerator.cxx panda3d-1.8.1-jj-systematic/panda/src/pgraphnodes/shaderGenerator.cxx --- panda3d-1.8.1-jj-fixes-base/panda/src/pgraphnodes/shaderGenerator.cxx 2014-09-26 21:30:46.958983631 +0300 +++ panda3d-1.8.1-jj-systematic/panda/src/pgraphnodes/shaderGenerator.cxx 2015-01-20 11:21:16.392062489 +0200 @@ -1158,37 +1158,136 @@ } } const LightRampAttrib *light_ramp = DCAST(LightRampAttrib, rs->get_attrib_def(LightRampAttrib::get_class_slot())); - if(_auto_ramp_on && ( (_separate_ambient_diffuse && _have_diffuse) || - (!_separate_ambient_diffuse && (_have_ambient || _have_diffuse)) ) ) { - switch (light_ramp->get_mode()) { - case LightRampAttrib::LRT_single_threshold: - { - PN_stdfloat t = light_ramp->get_threshold(0); - PN_stdfloat l0 = light_ramp->get_level(0); - text << "\t // Single-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_scale = (lr_in < " << t << ") ? 0.0 : (" << l0 << "/lr_in);\n"; - text << "\t tot_diffuse = tot_diffuse * lr_scale;\n"; - break; + if(_auto_ramp_on) { + // Lighting discretization for cartoon shading. + // + // We might have to generate almost identical code twice (once for diffuse and once for specular, + // if affect_specular is enabled for the light ramp). Hence we loop. + // + bool do_ramp[2]; // diffuse, specular + do_ramp[0] = ( _separate_ambient_diffuse && _have_diffuse) || + (!_separate_ambient_diffuse && (_have_ambient || _have_diffuse)); + do_ramp[1] = _have_specular && light_ramp->get_affect_specular() == true; + const char* rn[] = { "diffuse", "specular" }; // ramp name for generating unique variable names, + // and for referring to tot_diffuse, tot_specular. + + for(int j=0; j<2; ++j) { + if( !do_ramp[j] ) + continue; + + PN_stdfloat t0, l0, s0, t1, l1, s1; + if( j == 0 ) { // diffuse + t0 = light_ramp->get_threshold(0); + l0 = light_ramp->get_level(0); + s0 = light_ramp->get_smoothing(0); + t1 = light_ramp->get_threshold(1); + l1 = light_ramp->get_level(1); + s1 = light_ramp->get_smoothing(1); + } + else { // specular + // By default, these are initialized to the same values + // as the corresponding diffuse parameters. + // See panda/pgraph/lightRampAttrib.[I|cxx]. + t0 = light_ramp->get_threshold_specular(0); + l0 = light_ramp->get_level_specular(0); + s0 = light_ramp->get_smoothing_specular(0); + t1 = light_ramp->get_threshold_specular(1); + l1 = light_ramp->get_level_specular(1); + s1 = light_ramp->get_smoothing_specular(1); } - 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"; + + ostringstream olr_in, olr_out, otot; + olr_in << "lr_" << rn[j] << "_in"; // lr_diffuse_in, lr_specular_in + olr_out << "lr_" << rn[j] << "_out"; // lr_diffuse_out, lr_specular_out + otot << "tot_" << rn[j]; // tot_diffuse, tot_specular + string lr_in(olr_in.str()); + string lr_out(olr_out.str()); + string tot(otot.str()); + + switch (light_ramp->get_mode()) { + case LightRampAttrib::LRT_single_threshold: // Two lighting levels: zero and l0. + { + text << "\t // Single-threshold light ramp (for " << rn[j] << " lighting)\n"; + text << "\t float " << lr_in << " = dot(" << tot << ".rgb, float3(0.33,0.34,0.33));\n"; + + if( s0 == 0.0 ) { + text << "\t // sharp transition with thresholding only\n"; + text << "\t float " << lr_out << " = (" << lr_in << " < " << t0 << ") ? 0.0 : " << l0 << ";\n"; + } + else { + ostringstream olr_a, olr_b; + olr_a << "lr_" << rn[j] << "_a"; // lr_diffuse_a, lr_specular_a + olr_b << "lr_" << rn[j] << "_b"; // lr_diffuse_b, lr_specular_b + string lr_a(olr_a.str()); + string lr_b(olr_b.str()); + + text << "\t // smoothed transition with linear interpolation\n"; + text << "\t // with t0 = " << t0 << ", s0 = " << s0 << "\n"; + text << "\t const float " << lr_a << " = " << max(t0 - s0, PN_stdfloat(0.0)) << ";\n"; + text << "\t const float " << lr_b << " = " << min(t0 + s0, PN_stdfloat(1.0)) << ";\n"; + text << "\t float " << lr_out << " = (" << lr_in << " < " << lr_a << ") ? 0.0 : ( (" << lr_in << " > " << lr_b << ") ? " << l0 << " : lerp(0.0, " << l0 << ", (" << lr_in << " - " << lr_a << ")/(" << lr_b << " - " << lr_a << ") ) );\n"; + } + + text << "\t " << tot << " = " << tot << " * (" << lr_out << " / " << lr_in << ");\n"; + break; + } + case LightRampAttrib::LRT_double_threshold: // Three lighting levels: zero, l0 and l1. + { + text << "\t // Double-threshold light ramp (for " << rn[j] << " lighting)\n"; + text << "\t float " << lr_in << " = dot(" << tot << ".rgb, float3(0.33,0.34,0.33));\n"; + text << "\t float " << lr_out << " = 0.0;\n"; + + // transition from 0 to l0 + // + if( s0 == 0.0 ) { + text << "\t // 0 -> l0: sharp transition with thresholding only\n"; + text << "\t if (" << lr_in << " > " << t0 << ") " << lr_out << " = " << l0 << ";\n"; + } + else { + ostringstream olr_a, olr_b; + olr_a << "lr_" << rn[j] << "_a"; // lr_diffuse_a, lr_specular_a + olr_b << "lr_" << rn[j] << "_b"; // lr_diffuse_b, lr_specular_b + string lr_a(olr_a.str()); + string lr_b(olr_b.str()); + + text << "\t // 0 -> l0: smoothed transition with linear interpolation\n"; + text << "\t // with t0 = " << t0 << ", s0 = " << s0 << "\n"; + text << "\t const float " << lr_a << " = " << max(t0 - s0, PN_stdfloat(0.0)) << ";\n"; + text << "\t const float " << lr_b << " = " << min(t0 + s0, PN_stdfloat(1.0)) << ";\n"; + text << "\t if (" << lr_in << " > " << lr_b << ") " << lr_out << " =" << l0 << ";\n"; + text << "\t else if (" << lr_in << " > " << lr_a << ") " << lr_out << " = lerp(0.0, " << l0 << ", (" << lr_in << " - " << lr_a << ")/(" << lr_b << " - " << lr_a << "));\n"; + } + + // transition from l0 to l1 + // + if( s1 == 0.0 ) { + text << "\t // l0 -> l1: sharp transition with thresholding only\n"; + text << "\t if (" << lr_in << " > " << t1 << ") " << lr_out << " = " << l1 << ";\n"; + } + else { + ostringstream olr_c, olr_d; + olr_c << "lr_" << rn[j] << "_c"; // lr_diffuse_c, lr_specular_c + olr_d << "lr_" << rn[j] << "_d"; // lr_diffuse_d, lr_specular_d + string lr_c(olr_c.str()); + string lr_d(olr_d.str()); + + text << "\t // l0 -> l1: smoothed transition with linear interpolation\n"; + text << "\t // with t1 = " << t1 << ", s1 = " << s1 << "\n"; + text << "\t const float " << lr_c << " = " << max(t1 - s1, PN_stdfloat(0.0)) << ";\n"; + text << "\t const float " << lr_d << " = " << min(t1 + s1, PN_stdfloat(1.0)) << ";\n"; + text << "\t if (" << lr_in << " > " << lr_d << ") " << lr_out << " = " << l1 << ";\n"; + text << "\t else if (" << lr_in << " > " << lr_c << ") " << lr_out << " = lerp(" << l0 << ", " << l1 << ", (" << lr_in << " - " << lr_c << ")/(" << lr_d << " - " << lr_c << "));\n"; + } + + text << "\t " << tot << " = " << tot << " * (" << lr_out << " / " << lr_in << ");\n"; + break; + } + default: break; } - default: - break; } } + text << "\t // Begin view-space light summation\n"; if (_have_emission) { if (_map_index_glow >= 0 && _auto_glow_on) {