mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
has a new quadratic formula for attenuation and better weighing for multiple lights
This commit is contained in:
parent
19e402be97
commit
34f16c04b0
@ -117,13 +117,17 @@ cull_callback(CullTraverser *, CullTraverserData &data,
|
|||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Gets the node's position and based on distance from
|
// Description: Gets the node's position and based on distance from
|
||||||
// lights in the lightgroup calculates the color to be
|
// lights in the lightgroup calculates the color to be
|
||||||
// modulated in
|
// modulated in. If the avatar is in the range of
|
||||||
|
// multiple lights, then determine, which light it is
|
||||||
|
// closer to, and get the weight of the scene_color
|
||||||
|
// in respect to that light's proximity.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
CPT(RenderAttrib) PolylightEffect::
|
CPT(RenderAttrib) PolylightEffect::
|
||||||
do_poly_light(const CullTraverserData *data, const TransformState *node_transform) const {
|
do_poly_light(const CullTraverserData *data, const TransformState *node_transform) const {
|
||||||
float fd; // Variable for quadratic attenuation
|
//static bool was_under_polylight = false;
|
||||||
float dist; // To calculate the distance of each light from the node
|
float dist; // To calculate the distance of each light from the node
|
||||||
float r,g,b; // To hold the color calculation
|
float r,g,b; // To hold the color calculation
|
||||||
|
float min_dist; // hold the dist from light that avatar is closer to
|
||||||
int num_lights = 0; // Keep track of number of lights for division
|
int num_lights = 0; // Keep track of number of lights for division
|
||||||
float light_scale; // Variable to calculate attenuation
|
float light_scale; // Variable to calculate attenuation
|
||||||
float weight_scale; // Variable to compensate snap of color when you walk inside the light volume
|
float weight_scale; // Variable to compensate snap of color when you walk inside the light volume
|
||||||
@ -133,6 +137,14 @@ do_poly_light(const CullTraverserData *data, const TransformState *node_transfor
|
|||||||
r = g = b = 1.0;
|
r = g = b = 1.0;
|
||||||
Rcollect = Gcollect = Bcollect = 0.0;
|
Rcollect = Gcollect = Bcollect = 0.0;
|
||||||
|
|
||||||
|
// get the avatar's base color scale
|
||||||
|
NodePath parent = data->_node_path.get_node_path().get_parent();
|
||||||
|
Colorf scene_color = parent.get_color_scale();
|
||||||
|
if (polylight_info) {
|
||||||
|
pgraph_cat.info() << "parent node name " << parent.get_name() << endl;
|
||||||
|
pgraph_cat.info() << "parent color scale = " << scene_color << endl;
|
||||||
|
}
|
||||||
|
min_dist = 100000.0;
|
||||||
// Cycle through all the lights in this effect's lightgroup
|
// Cycle through all the lights in this effect's lightgroup
|
||||||
LightGroup::const_iterator light_iter;
|
LightGroup::const_iterator light_iter;
|
||||||
for (light_iter = _lightgroup.begin(); light_iter != _lightgroup.end(); light_iter++){
|
for (light_iter = _lightgroup.begin(); light_iter != _lightgroup.end(); light_iter++){
|
||||||
@ -157,9 +169,9 @@ do_poly_light(const CullTraverserData *data, const TransformState *node_transfor
|
|||||||
|
|
||||||
if (dist <= light_radius) { // If node is in range of this light
|
if (dist <= light_radius) { // If node is in range of this light
|
||||||
if (polylight_info) {
|
if (polylight_info) {
|
||||||
pgraph_cat.info() << "light's position = " << light->get_pos() << endl;
|
pgraph_cat.debug() << "light's position = " << light->get_pos() << endl;
|
||||||
pgraph_cat.info() << "relative position = " << point << endl;
|
pgraph_cat.debug() << "relative position = " << point << endl;
|
||||||
pgraph_cat.info() << "effect center = " << _effect_center << endl;
|
pgraph_cat.debug() << "effect center = " << _effect_center << endl;
|
||||||
//pgraph_cat.info() << "close to this light = " << light->get_name() << endl;
|
//pgraph_cat.info() << "close to this light = " << light->get_name() << endl;
|
||||||
pgraph_cat.info() << "dist = " << dist << ";radius = " << light_radius << endl;
|
pgraph_cat.info() << "dist = " << dist << ";radius = " << light_radius << endl;
|
||||||
}
|
}
|
||||||
@ -173,9 +185,12 @@ do_poly_light(const CullTraverserData *data, const TransformState *node_transfor
|
|||||||
//light_color = light->get_color_scenegraph();
|
//light_color = light->get_color_scenegraph();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float ratio = dist/light_radius;
|
||||||
if (light_attenuation == PolylightNode::ALINEAR) {
|
if (light_attenuation == PolylightNode::ALINEAR) {
|
||||||
light_scale = (light_radius - dist)/light_radius;
|
light_scale = 1.0 - ratio;
|
||||||
} else if (light_attenuation == PolylightNode::AQUADRATIC) {
|
} else if (light_attenuation == PolylightNode::AQUADRATIC) {
|
||||||
|
/*
|
||||||
|
float fd; // Variable for quadratic attenuation
|
||||||
float light_a0 = light->get_a0();
|
float light_a0 = light->get_a0();
|
||||||
float light_a1 = light->get_a1();
|
float light_a1 = light->get_a1();
|
||||||
float light_a2 = light->get_a2();
|
float light_a2 = light->get_a2();
|
||||||
@ -188,24 +203,45 @@ do_poly_light(const CullTraverserData *data, const TransformState *node_transfor
|
|||||||
} else {
|
} else {
|
||||||
light_scale = 1.0;
|
light_scale = 1.0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
//light_scale = 1.0 - ratio*ratio; // graph of 1-x^2
|
||||||
|
ratio = 1 - ratio;
|
||||||
|
if (ratio <= 0.8)
|
||||||
|
light_scale = (ratio*ratio)*(3-2*ratio); //graph of x^2(3-x)
|
||||||
|
else
|
||||||
|
light_scale = 1.0;
|
||||||
} else {
|
} else {
|
||||||
light_scale = 1.0;
|
light_scale = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep accumulating each lights contribution...
|
if (min_dist > dist) {
|
||||||
// we have to prevent color snap, so factor in the weight.
|
min_dist = dist;
|
||||||
// weight becomes negligent as you are closer to the light
|
// Keep accumulating each lights contribution...
|
||||||
// and opposite otherwise
|
// we have to prevent color snap, so factor in the weight.
|
||||||
weight_scale = _weight * (1.0 - light_scale);
|
// weight becomes negligent as you are closer to the light
|
||||||
|
// and opposite otherwise
|
||||||
|
weight_scale = _weight * (1.0 - light_scale);
|
||||||
|
}
|
||||||
|
|
||||||
if (polylight_info) {
|
if (polylight_info) {
|
||||||
pgraph_cat.debug() << "weight_scale = " << weight_scale
|
pgraph_cat.info() << "weight_scale = " << weight_scale
|
||||||
<< "; light_scale " << light_scale << endl;
|
<< "; light_scale " << light_scale << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rcollect += light_color[0] * light_scale;
|
||||||
|
Gcollect += light_color[1] * light_scale;
|
||||||
|
Bcollect += light_color[2] * light_scale;
|
||||||
|
/*
|
||||||
|
Rcollect += light_color[0] * light_scale + scene_color[0] * weight_scale;
|
||||||
|
Gcollect += light_color[1] * light_scale + scene_color[1] * weight_scale;
|
||||||
|
Bcollect += light_color[2] * light_scale + scene_color[2] * weight_scale;
|
||||||
|
*/
|
||||||
|
/*
|
||||||
Rcollect += light_color[0] * light_scale + weight_scale;
|
Rcollect += light_color[0] * light_scale + weight_scale;
|
||||||
Gcollect += light_color[1] * light_scale + weight_scale;
|
Gcollect += light_color[1] * light_scale + weight_scale;
|
||||||
Bcollect += light_color[2] * light_scale + weight_scale;
|
Bcollect += light_color[2] * light_scale + weight_scale;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
num_lights++;
|
num_lights++;
|
||||||
} // if dist< radius
|
} // if dist< radius
|
||||||
@ -220,14 +256,70 @@ do_poly_light(const CullTraverserData *data, const TransformState *node_transfor
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (num_lights) {
|
if (num_lights) {
|
||||||
pgraph_cat.debug() << "num lights = " << num_lights << endl;
|
//was_under_polylight = true;
|
||||||
// divide by number of lights to get average.
|
//data->_node_path.get_node_path().set_color_scale_off();
|
||||||
r = Rcollect / num_lights;
|
|
||||||
g = Gcollect / num_lights;
|
|
||||||
b = Bcollect / num_lights;
|
|
||||||
if (polylight_info)
|
if (polylight_info)
|
||||||
pgraph_cat.info() << "r=" << r << "; g=" << g << "; b=" << b << endl;
|
pgraph_cat.info() << "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;
|
||||||
|
|
||||||
|
if (polylight_info)
|
||||||
|
pgraph_cat.info() << "avg: r=" << r << "; g=" << g << "; b=" << b << endl;
|
||||||
|
|
||||||
|
// Now add the scene_color multiplied by weight_scale
|
||||||
|
r += scene_color[0] * weight_scale;
|
||||||
|
g += scene_color[1] * weight_scale;
|
||||||
|
b += scene_color[2] * weight_scale;
|
||||||
|
if (polylight_info)
|
||||||
|
pgraph_cat.info() << "weighed: r=" << r << "; g=" << g << "; b=" << b << endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// normalize the color
|
||||||
|
LVector3f color_vector(r, g, b);
|
||||||
|
color_vector.normalize();
|
||||||
|
r = color_vector[0];
|
||||||
|
g = color_vector[1];
|
||||||
|
b = color_vector[2];
|
||||||
|
|
||||||
|
if (polylight_info)
|
||||||
|
pgraph_cat.info() << "unit: r=" << r << "; g=" << g << "; b=" << b << endl;
|
||||||
|
*/
|
||||||
|
|
||||||
|
// cap it
|
||||||
|
r = (r > 1.0)? 1.0 : r;
|
||||||
|
g = (g > 1.0)? 1.0 : g;
|
||||||
|
b = (b > 1.0)? 1.0 : b;
|
||||||
|
|
||||||
|
if (polylight_info)
|
||||||
|
pgraph_cat.info() << "capped: r=" << r << "; g=" << g << "; b=" << b << endl;
|
||||||
|
|
||||||
|
// since this rgb will be scaled by scene_color by day night
|
||||||
|
// cycle, lets undo that effect by dividing this rgb by the
|
||||||
|
// scene_color. That way, the final render will contain this rgb
|
||||||
|
if (scene_color[0] >= 0.01)
|
||||||
|
r /= scene_color[0];
|
||||||
|
if (scene_color[1] >= 0.01)
|
||||||
|
g /= scene_color[1];
|
||||||
|
if (scene_color[2] >= 0.01)
|
||||||
|
b /= scene_color[2];
|
||||||
|
|
||||||
|
if (polylight_info)
|
||||||
|
pgraph_cat.info() << "final: r=" << r << "; g=" << g << "; b=" << b << endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
else {
|
||||||
|
if (was_under_polylight) {
|
||||||
|
// under no polylight influence...so clear the color scale
|
||||||
|
//data->_node_path.get_node_path().clear_color_scale();
|
||||||
|
//data->_node_path.get_node_path().set_color_scale(scene_color);
|
||||||
|
was_under_polylight = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
return ColorScaleAttrib::make(LVecBase4f(r, g, b, 1.0));
|
return ColorScaleAttrib::make(LVecBase4f(r, g, b, 1.0));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user