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;
134 const NodePath &root = scene->get_scene_root();
136 const NodePath &camera = scene->get_cull_center();
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;
159 LPoint3 relative_point = data->_node_path.get_node_path().get_relative_point(lightnp, light->
get_pos());
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);
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 <<
")**";
bool is_flickering() const
Check is this light is flickering.
virtual bool has_cull_callback() const
Should be overridden by derived classes to return true if cull_callback() has been defined...
This is the base class for a number of render attributes (other than transform) that may be set on sc...
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.
SceneSetup * get_scene() const
Returns the SceneSetup object.
A PolylightEffect can be used on a node to define a LightGroup for that node.
LColor get_color() const
Returns the light's color as LColor.
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...
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...
bool has_light(const NodePath &light) const
Returns true if the indicated light is listed in the PolylightEffect, false otherwise.
LColor flicker() const
If flickering is on, the do_poly_light function in PolylightNodeEffect will compute this light's colo...
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
bool is_enabled() const
Is this light is enabled/disabled?
This is the base class for all three-component vectors and points.
This is a two-component vector offset.
LPoint3 get_pos() const
Returns position as a LPoint3.
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 ...
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.
static int size()
Returns 4: the number of components of a LVecBase4.
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...