diff --git a/panda/src/pgraph/polylightEffect.cxx b/panda/src/pgraph/polylightEffect.cxx index 382936499a..dca7ad7a84 100755 --- a/panda/src/pgraph/polylightEffect.cxx +++ b/panda/src/pgraph/polylightEffect.cxx @@ -37,7 +37,7 @@ CPT(RenderEffect) PolylightEffect:: make() { PolylightEffect *effect = new PolylightEffect; effect->_contribution_type = CT_proximal; - effect->_weight = 0.9; + effect->_weight = 1.0; // 0.9; // Asad: I don't think we should monkey with the weight. effect->_effect_center = LPoint3f(0.0,0.0,0.0); return return_new(effect); } @@ -116,90 +116,113 @@ cull_callback(CullTraverser *, CullTraverserData &data, // Function: PolylightEffect::do_poly_light // Access: Public // Description: Gets the node's position and based on distance from -// lights in the lightgroup calculates the color to be modulated in +// lights in the lightgroup calculates the color to be +// modulated in //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) PolylightEffect:: do_poly_light(const CullTraverserData *data, const TransformState *node_transform) const { - bool no_lights_closeby = false; - float r,g,b; // To hold the color calculation - float dist; // To calculate the distance of each light from the node - float light_scale = 1.0; // Variable to calculate attenuation float fd; // Variable for quadratic attenuation - float Rcollect = 0.0,Gcollect = 0.0,Bcollect = 0.0; // Color variables + float dist; // To calculate the distance of each light from the node + float r,g,b; // To hold the color calculation int num_lights = 0; // Keep track of number of lights for division - r = 1.0; - g = 1.0; - b = 1.0; - LightGroup::const_iterator light_iter; + float light_scale; // Variable to calculate attenuation + float weight_scale; // Variable to compensate snap of color when you walk inside the light volume + float Rcollect, Gcollect, Bcollect; + + // Initialize Color variables + r = g = b = 1.0; + Rcollect = Gcollect = Bcollect = 0.0; + // Cycle through all the lights in this effect's lightgroup + LightGroup::const_iterator light_iter; for (light_iter = _lightgroup.begin(); light_iter != _lightgroup.end(); light_iter++){ const PolylightNode *light = DCAST(PolylightNode, (*light_iter).node()); + // light holds the current PolylightNode if (light->is_enabled()) { // if enabled get all the properties float light_radius = light->get_radius(); - PolylightNode::Attenuation_Type light_attenuation = light->get_attenuation(); - float light_a0 = light->get_a0(); - float light_a1 = light->get_a1(); - float light_a2 = light->get_a2(); - if (light_a0 == 0 && light_a1 == 0 && light_a2 == 0) { // To prevent division by zero - light_a0 = 1.0; - } - Colorf light_color; - if (light->is_flickering()) { // If flickering, modify color - light_color = light->flicker(); - } else { - light_color = light->get_color_scenegraph(); - } // Calculate the distance of the node from the light //dist = light_iter->second->get_distance(data->_node_path.get_node_path()); const NodePath lightnp = *light_iter; LPoint3f point = data->_node_path.get_node_path().get_relative_point(lightnp, light->get_pos()); - dist = (point - _effect_center).length(); - if (dist < light_radius) { // If node is in range of this light + + if (_effect_center[2]) { + dist = (point - _effect_center).length(); // this counts height difference + } else { + // get distance as if the light is at the same height of player + LVector2f xz(point[0], point[1]); + dist = xz.length(); // this does not count height difference + } + + if (dist < light_radius) { // If node is in range of this light + pgraph_cat.debug() << "light's position = " << light->get_pos() << endl; + pgraph_cat.debug() << "relative position = " << point << endl; + pgraph_cat.debug() << "effect center = " << _effect_center << endl; + pgraph_cat.debug() << "close to this light = " << light->get_name() << endl; + + PolylightNode::Attenuation_Type light_attenuation = light->get_attenuation(); + Colorf light_color; + if (light->is_flickering()) { // If flickering, modify color + light_color = light->flicker(); + } else { + light_color = light->get_color(); + //light_color = light->get_color_scenegraph(); + } + if (light_attenuation == PolylightNode::ALINEAR) { light_scale = (light_radius - dist)/light_radius; } else if (light_attenuation == PolylightNode::AQUADRATIC) { + float light_a0 = light->get_a0(); + float light_a1 = light->get_a1(); + float light_a2 = light->get_a2(); + if (light_a0 == 0 && light_a1 == 0 && light_a2 == 0) { // To prevent division by zero + light_a0 = 1.0; + } fd = 1.0 / (light_a0 + light_a1 * dist + light_a2 * dist * dist); if (fd < 1.0) { light_scale = fd; } else { light_scale = 1.0; } - } else { - light_scale = 1.0; - } - // Keep accumulating each lights contribution... we divide by - // number of lights later. - Rcollect += light_color[0] * light_scale; - Gcollect += light_color[1] * light_scale; - Bcollect += light_color[2] * light_scale; - num_lights++; + } else { + light_scale = 1.0; + } + + pgraph_cat.debug() << "dist = " << dist << ";radius = " << light_radius << endl; + + // Keep accumulating each lights contribution... + // we have to prevent color snap, so factor in the weight. + // weight becomes negligent as you are closer to the light + // and opposite otherwise + weight_scale = _weight * (1.0 - light_scale); + + pgraph_cat.debug() << "weight_scale = " << weight_scale + << "; light_scale " << light_scale << endl; + + Rcollect += light_color[0] * light_scale + weight_scale; + Gcollect += light_color[1] * light_scale + weight_scale; + Bcollect += light_color[2] * light_scale + weight_scale; + + num_lights++; } // if dist< radius } // if light is enabled } // for all lights - if ( _contribution_type == CT_all) { // Sometimes to prevent snapping of color at light volume boundaries // just divide total contribution by all the lights in the effect // whether or not they contribute color num_lights = _lightgroup.size(); } - if (num_lights == 0) { - no_lights_closeby = true; - num_lights = 1; - } - Rcollect /= num_lights; - Gcollect /= num_lights; - Bcollect /= num_lights; - if (!no_lights_closeby) { - //r = 1.0 + ((1.0 - _weight) + Rcollect * _weight); - //g = 1.0 + ((1.0 - _weight) + Gcollect * _weight); - //b = 1.0 + ((1.0 - _weight) + Bcollect * _weight); - r = _weight + Rcollect; - g = _weight + Gcollect; - b = _weight + Bcollect; + + if (num_lights) { + pgraph_cat.debug() << "num lights = " << num_lights << endl; + // divide by number of lights to get average. + r = Rcollect / num_lights; + g = Gcollect / num_lights; + b = Bcollect / num_lights; + pgraph_cat.debug() << "r = " << r << ";g = " << g << ";b = " << b << endl; } return ColorScaleAttrib::make(LVecBase4f(r, g, b, 1.0)); diff --git a/panda/src/pgraph/polylightNode.cxx b/panda/src/pgraph/polylightNode.cxx index 1ca0275cb1..feff3a6d4b 100755 --- a/panda/src/pgraph/polylightNode.cxx +++ b/panda/src/pgraph/polylightNode.cxx @@ -70,7 +70,8 @@ Colorf PolylightNode::flicker() const { float r,g,b; Colorf color; - color = get_color_scenegraph(); + color = get_color(); + //color = get_color_scenegraph(); r = color[0]; g = color[1]; b = color[2]; @@ -81,13 +82,13 @@ Colorf PolylightNode::flicker() const { variation = (rand()%100);// * ClockObject::get_global_clock()->get_dt(); variation /= 100.0; //printf("Random Variation: %f\n",variation); - variation += _offset; + //variation += _offset; variation *= _scale; } else if (_flicker_type == FSIN) { double now = ClockObject::get_global_clock()->get_frame_time(); variation = sinf(now*_sin_freq);// * ClockObject::get_global_clock()->get_dt(); //printf("Variation: %f\n",variation); - variation += _offset; + //variation += _offset; variation *= _scale; } else if (_flicker_type == FCUSTOM) { // fixed point list of variation values coming soon...