Browse Source

cleaned up Shalin's polylight code. Still need to work on the flicker code, will do it tomorrow

Asad M. Zaman 21 years ago
parent
commit
7ff0b84f6a
2 changed files with 77 additions and 53 deletions
  1. 73 50
      panda/src/pgraph/polylightEffect.cxx
  2. 4 3
      panda/src/pgraph/polylightNode.cxx

+ 73 - 50
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));

+ 4 - 3
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...