|
|
@@ -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));
|