15 #include "polylightEffect.h" 16 #include "polylightNode.h" 17 #include "config_pgraph.h" 20 #include "colorScaleAttrib.h" 21 #include "cullTraverserData.h" 22 #include "cullTraverser.h" 36 effect->_contribution_type = CT_proximal;
37 effect->_weight = 1.0;
38 effect->_effect_center =
LPoint3(0.0,0.0,0.0);
39 return return_new(effect);
48 make(PN_stdfloat weight, ContribType contrib,
const LPoint3 &effect_center) {
50 effect->_contribution_type = contrib;
51 effect->_weight = weight;
52 effect->_effect_center = effect_center;
53 return return_new(effect);
62 make(PN_stdfloat weight, ContribType contrib,
const LPoint3 &effect_center,
63 const LightGroup &lights) {
65 effect->_contribution_type = contrib;
66 effect->_weight = weight;
67 effect->_effect_center = effect_center;
68 effect->_lightgroup = lights;
69 return return_new(effect);
83 return !_lightgroup.empty();
105 CPT(TransformState) &node_transform,
109 CPT(
RenderState) poly_light_state = RenderState::make(poly_light_attrib);
110 node_state = node_state->compose(poly_light_state);
128 PN_stdfloat min_dist;
130 PN_stdfloat light_scale;
131 PN_stdfloat weight_scale = 1.0f;
132 PN_stdfloat Rcollect, Gcollect, Bcollect;
140 Rcollect = Gcollect = Bcollect = 0.0;
144 if (polylight_info) {
145 pgraph_cat.debug() <<
"scene color scale = " << scene_color << endl;
149 LightGroup::const_iterator light_iter;
150 for (light_iter = _lightgroup.begin(); light_iter != _lightgroup.end(); light_iter++){
155 PN_stdfloat light_radius = light->
get_radius();
158 const NodePath lightnp = *light_iter;
161 if (_effect_center[2]) {
162 dist = (relative_point - _effect_center).length();
165 LVector2 xz(relative_point[0], relative_point[1]);
169 if (dist <= light_radius) {
175 LVector3 light_camera = camera_position - light_position;
176 LVector3 light_avatar = avatar_position - light_position;
179 PN_stdfloat intensity = light_camera.dot(light_avatar);
181 if (polylight_info) {
182 pgraph_cat.debug() <<
"light position = " << light_position << endl;
183 pgraph_cat.debug() <<
"relative avatar position = " << avatar_position << endl;
184 pgraph_cat.debug() <<
"relative camera position = " << camera_position << endl;
185 pgraph_cat.debug() <<
"light->camera " << light_camera << endl;
186 pgraph_cat.debug() <<
"light->avatar " << light_avatar << endl;
187 pgraph_cat.debug() <<
"light->camera.light->avatar = " << intensity << endl;
188 pgraph_cat.debug() <<
"effect center = " << _effect_center << endl;
190 pgraph_cat.debug() <<
"dist = " << dist <<
";radius = " << light_radius << endl;
194 intensity = 1.0 - ((intensity + 1.0) * 0.5);
195 if (polylight_info) {
196 pgraph_cat.debug() <<
"remapped intensity = " << intensity << endl;
199 PolylightNode::Attenuation_Type light_attenuation = light->
get_attenuation();
202 light_color = light->
flicker();
208 PN_stdfloat ratio = dist/light_radius;
209 if (light_attenuation == PolylightNode::ALINEAR) {
210 light_scale = 1.0 - ratio;
211 }
else if (light_attenuation == PolylightNode::AQUADRATIC) {
230 light_scale = (ratio*ratio)*(3-2*ratio);
237 light_scale *= intensity;
239 if (min_dist > dist) {
245 weight_scale = _weight * (1.0 - light_scale);
248 if (polylight_info) {
249 pgraph_cat.debug() <<
"weight_scale = " << weight_scale
250 <<
"; light_scale " << light_scale << endl;
253 Rcollect += light_color[0] * light_scale;
254 Gcollect += light_color[1] * light_scale;
255 Bcollect += light_color[2] * light_scale;
273 if ( _contribution_type == CT_all) {
277 num_lights = _lightgroup.size();
284 pgraph_cat.debug() <<
"num lights = " << num_lights << endl;
292 pgraph_cat.debug() <<
"avg: r=" << r <<
"; g=" << g <<
"; b=" << b << endl;
295 r += scene_color[0] * weight_scale;
296 g += scene_color[1] * weight_scale;
297 b += scene_color[2] * weight_scale;
299 pgraph_cat.debug() <<
"weighed: r=" << r <<
"; g=" << g <<
"; b=" << b << endl;
314 r = (r > 1.0)? 1.0 : r;
315 g = (g > 1.0)? 1.0 : g;
316 b = (b > 1.0)? 1.0 : b;
319 pgraph_cat.debug() <<
"capped: r=" << r <<
"; g=" << g <<
"; b=" << b << endl;
324 if (scene_color[0] >= 0.01)
326 if (scene_color[1] >= 0.01)
328 if (scene_color[2] >= 0.01)
332 pgraph_cat.debug() <<
"final: r=" << r <<
"; g=" << g <<
"; b=" << b << endl;
346 return ColorScaleAttrib::make(
LVecBase4(r, g, b, 1.0));
354 void PolylightEffect::
355 output(ostream &out)
const {
356 out << get_type() <<
":";
358 LightGroup::const_iterator li;
359 for (li = _lightgroup.begin(); li != _lightgroup.end(); ++li) {
363 out <<
" weight " << _weight <<
" contrib " << _contribution_type
364 <<
" center " << _effect_center;
383 int PolylightEffect::
386 DCAST_INTO_R(ta, other, 0);
388 if (_contribution_type != ta->_contribution_type) {
389 return _contribution_type < ta->_contribution_type ? -1 : 1;
392 if (_weight != ta->_weight) {
393 return _weight < ta->_weight ? -1 :1;
396 if (_lightgroup != ta->_lightgroup) {
397 return _lightgroup < ta->_lightgroup ? -1 : 1;
412 add_light(
const NodePath &newlight)
const {
414 effect->_lightgroup.push_back(newlight);
415 return return_new(effect);
426 remove_light(
const NodePath &newlight)
const {
428 LightGroup::iterator light_iter;
429 light_iter = find(effect->_lightgroup.begin(),effect->_lightgroup.end(), newlight);
430 if (light_iter == effect->_lightgroup.end()) {
432 <<
"Attempt to remove Polylight " << newlight <<
"; not found.\n";
435 effect->_lightgroup.erase(light_iter);
437 return return_new(effect);
451 set_weight(PN_stdfloat w)
const {
454 return return_new(effect);
467 set_contrib(ContribType ct)
const {
469 effect->_contribution_type = ct;
470 return return_new(effect);
483 set_effect_center(
const LPoint3 &ec)
const{
485 effect->_effect_center = ec;
486 return return_new(effect);
495 bool PolylightEffect::
496 has_light(
const NodePath &light)
const {
497 LightGroup::const_iterator li;
498 li = find(_lightgroup.begin(), _lightgroup.end(), light);
499 return (li != _lightgroup.end());
503 operator << (ostream &out, PolylightEffect::ContribType ct) {
505 case PolylightEffect::CT_proximal:
506 return out <<
"proximal";
508 case PolylightEffect::CT_all:
512 return out <<
"**Invalid ContribType(" << (int)ct <<
")**";
This is the base class for a number of render attributes (other than transform) that may be set on sc...
const LVecBase4 & get_color_scale() const
Returns the complete color scale vector that has been applied to this node via a previous call to set...
PN_stdfloat get_radius() const
Get radius of the spherical light volume.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
This is the base class for a number of special render effects that may be set on scene graph nodes to...
Attenuation_Type get_attenuation() const
Get "linear" or "quadratic" attenuation type.
virtual bool has_cull_callback() const
Should be overridden by derived classes to return true if cull_callback() has been defined...
bool is_enabled() const
Is this light is enabled/disabled?
A PolylightEffect can be used on a node to define a LightGroup for that node.
virtual void cull_callback(CullTraverser *trav, CullTraverserData &data, CPT(TransformState) &node_transform, CPT(RenderState) &node_state) const
If has_cull_callback() returns true, this function will be called during the cull traversal to perfor...
NodePath get_node_path() const
Constructs and returns an actual NodePath that represents the same path we have just traversed...
LPoint3 get_pos() const
Returns position as a LPoint3.
const NodePath & get_scene_root() const
Returns the root node of the scene.
bool is_flickering() const
Check is this light is flickering.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
LColor flicker() const
If flickering is on, the do_poly_light function in PolylightNodeEffect will compute this light's colo...
This is the base class for all three-component vectors and points.
const NodePath & get_cull_center() const
Returns the point from which the culling operations will be performed.
This is a two-component vector offset.
SceneSetup * get_scene() const
Returns the SceneSetup object.
LPoint3 get_relative_point(const NodePath &other, const LVecBase3 &point) const
Given that the indicated point is in the coordinate system of the other node, returns the same point ...
float length() const
Returns the length of the vector, by the Pythagorean theorem.
TypeHandle is the identifier used to differentiate C++ class types.
This object holds the camera position, etc., and other general setup information for rendering a part...
bool normalize()
Normalizes the vector in place.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
LColor get_color() const
Returns the light's color as LColor.