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

This commit is contained in:
Asad M. Zaman 2004-09-09 03:44:59 +00:00
parent 3cf0b32484
commit 7ff0b84f6a
2 changed files with 77 additions and 53 deletions

View File

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

View File

@ -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...