Panda3D
shaderAttrib.cxx
1 // Filename: shaderAttrib.cxx
2 // Created by: sshodhan (10Jul04)
3 // Updated by: fperazzi, PandaSE (06Apr10) (added more overloads
4 // for set_shader_input)
5 // Updated by: weifengh, PandaSE(15Apr10) (added overload for
6 // set_shader_auto)
7 //
8 ////////////////////////////////////////////////////////////////////
9 //
10 // PANDA 3D SOFTWARE
11 // Copyright (c) Carnegie Mellon University. All rights reserved.
12 //
13 // All use of this software is subject to the terms of the revised BSD
14 // license. You should have received a copy of this license along
15 // with this source code in a file named "LICENSE."
16 //
17 ////////////////////////////////////////////////////////////////////
18 
19 #include "pandabase.h"
20 #include "shaderAttrib.h"
21 #include "graphicsStateGuardianBase.h"
22 #include "bamReader.h"
23 #include "bamWriter.h"
24 #include "datagram.h"
25 #include "datagramIterator.h"
26 #include "nodePath.h"
27 
28 TypeHandle ShaderAttrib::_type_handle;
29 int ShaderAttrib::_attrib_slot;
30 
31 ////////////////////////////////////////////////////////////////////
32 // Function: ShaderAttrib::make_off
33 // Access: Published, Static
34 // Description: Constructs a new ShaderAttrib object that disables
35 // the use of shaders (it does not clear out all shader
36 // data, however.)
37 ////////////////////////////////////////////////////////////////////
38 CPT(RenderAttrib) ShaderAttrib::
39 make_off() {
40  static CPT(RenderAttrib) _off_attrib;
41  if (_off_attrib == 0) {
42  ShaderAttrib *attrib = new ShaderAttrib;
43  attrib->_has_shader = true;
44  _off_attrib = return_new(attrib);
45  }
46  return _off_attrib;
47 }
48 
49 ////////////////////////////////////////////////////////////////////
50 // Function: ShaderAttrib::make
51 // Access: Published, Static
52 // Description: Constructs a new ShaderAttrib object with nothing
53 // set.
54 ////////////////////////////////////////////////////////////////////
55 CPT(RenderAttrib) ShaderAttrib::
56 make(const Shader *shader) {
57  static CPT(RenderAttrib) _null_attrib;
58  if (_null_attrib == 0) {
59  ShaderAttrib *attrib = new ShaderAttrib;
60  _null_attrib = return_new(attrib);
61  }
62 
63  if (shader == NULL) {
64  return _null_attrib;
65  } else {
66  return DCAST(ShaderAttrib, _null_attrib)->set_shader(shader);
67  }
68 }
69 
70 ////////////////////////////////////////////////////////////////////
71 // Function: ShaderAttrib::make_default
72 // Access: Published, Static
73 // Description: Returns a RenderAttrib that corresponds to whatever
74 // the standard default properties for render attributes
75 // of this type ought to be.
76 ////////////////////////////////////////////////////////////////////
77 CPT(RenderAttrib) ShaderAttrib::
78 make_default() {
79  return return_new(new ShaderAttrib);
80 }
81 
82 ////////////////////////////////////////////////////////////////////
83 // Function: ShaderAttrib::set_shader
84 // Access: Published
85 // Description:
86 ////////////////////////////////////////////////////////////////////
87 CPT(RenderAttrib) ShaderAttrib::
88 set_shader(const Shader *s, int priority) const {
89  ShaderAttrib *result = new ShaderAttrib(*this);
90  result->_shader = s;
91  result->_shader_priority = priority;
92  result->_auto_shader = false;
93  result->_has_shader = true;
94  return return_new(result);
95 }
96 
97 ////////////////////////////////////////////////////////////////////
98 // Function: ShaderAttrib::set_shader_off
99 // Access: Published
100 // Description:
101 ////////////////////////////////////////////////////////////////////
102 CPT(RenderAttrib) ShaderAttrib::
103 set_shader_off(int priority) const {
104  ShaderAttrib *result = new ShaderAttrib(*this);
105  result->_shader = NULL;
106  result->_shader_priority = priority;
107  result->_auto_shader = false;
108  result->_auto_normal_on = false;
109  result->_auto_glow_on = false;
110  result->_auto_gloss_on = false;
111  result->_auto_ramp_on = false;
112  result->_auto_shadow_on = false;
113 
114  result->_has_shader = true;
115  return return_new(result);
116 }
117 
118 ////////////////////////////////////////////////////////////////////
119 // Function: ShaderAttrib::set_shader_auto
120 // Access: Published
121 // Description:
122 ////////////////////////////////////////////////////////////////////
123 CPT(RenderAttrib) ShaderAttrib::
124 set_shader_auto(int priority) const {
125  ShaderAttrib *result = new ShaderAttrib(*this);
126  result->_shader = NULL;
127  result->_shader_priority = priority;
128  result->_auto_shader = true;
129  result->_has_shader = true;
130  result->_auto_normal_on = true;
131  result->_auto_glow_on = true;
132  result->_auto_gloss_on = true;
133  result->_auto_ramp_on = true;
134  result->_auto_shadow_on = true;
135  return return_new(result);
136 }
137 
138 ////////////////////////////////////////////////////////////////////
139 // Function: ShaderAttrib::set_shader_auto
140 // Access: Published
141 // Description: Set auto shader with bitmask to customize use,
142 // e.g., to keep normal, glow, etc., on or off
143 ////////////////////////////////////////////////////////////////////
144 CPT(RenderAttrib) ShaderAttrib::
145 set_shader_auto(BitMask32 shader_switch, int priority) const {
146 
147  ShaderAttrib *result = new ShaderAttrib(*this);
148  result->_shader = NULL;
149  result->_shader_priority = priority;
150  result->_auto_shader = true;
151  result->_has_shader = true;
152  result->_auto_normal_on = shader_switch.get_bit(Shader::bit_AutoShaderNormal);
153  result->_auto_glow_on = shader_switch.get_bit(Shader::bit_AutoShaderGlow);
154  result->_auto_gloss_on = shader_switch.get_bit(Shader::bit_AutoShaderGloss);
155  result->_auto_ramp_on = shader_switch.get_bit(Shader::bit_AutoShaderRamp);
156  result->_auto_shadow_on = shader_switch.get_bit(Shader::bit_AutoShaderShadow);
157 
158  return return_new(result);
159 }
160 
161 ////////////////////////////////////////////////////////////////////
162 // Function: ShaderAttrib::clear_shader
163 // Access: Published
164 // Description:
165 ////////////////////////////////////////////////////////////////////
166 CPT(RenderAttrib) ShaderAttrib::
167 clear_shader() const {
168  ShaderAttrib *result = new ShaderAttrib(*this);
169  result->_shader = NULL;
170  result->_shader_priority = 0;
171  result->_auto_shader = false;
172  result->_has_shader = false;
173  result->_auto_normal_on = false;
174  result->_auto_glow_on = false;
175  result->_auto_gloss_on = false;
176  result->_auto_ramp_on = false;
177  result->_auto_shadow_on = false;
178  return return_new(result);
179 }
180 
181 ////////////////////////////////////////////////////////////////////
182 // Function: ShaderAttrib::set_flag
183 // Access: Published
184 // Description:
185 ////////////////////////////////////////////////////////////////////
186 CPT(RenderAttrib) ShaderAttrib::
187 set_flag(int flag, bool value) const {
188  ShaderAttrib *result = new ShaderAttrib(*this);
189  int bit = 1<<flag;
190  if (value) {
191  result->_flags |= bit;
192  } else {
193  result->_flags &= ~bit;
194  }
195  result->_has_flags |= bit;
196  return return_new(result);
197 }
198 
199 ////////////////////////////////////////////////////////////////////
200 // Function: ShaderAttrib::clear_flag
201 // Access: Published
202 // Description:
203 ////////////////////////////////////////////////////////////////////
204 CPT(RenderAttrib) ShaderAttrib::
205 clear_flag(int flag) const {
206  ShaderAttrib *result = new ShaderAttrib(*this);
207  int bit = 1<<flag;
208  result->_flags &= ~bit;
209  result->_has_flags &= ~bit;
210  return return_new(result);
211 }
212 
213 ////////////////////////////////////////////////////////////////////
214 // Function: ShaderAttrib::set_shader_input
215 // Access: Published
216 // Description:
217 ////////////////////////////////////////////////////////////////////
218 CPT(RenderAttrib) ShaderAttrib::
219 set_shader_input(const ShaderInput *input) const {
220  ShaderAttrib *result = new ShaderAttrib(*this);
221  Inputs::iterator i = result->_inputs.find(input->get_name());
222  if (i == result->_inputs.end()) {
223  result->_inputs.insert(Inputs::value_type(input->get_name(), input));
224  } else {
225  i->second = input;
226  }
227  return return_new(result);
228 }
229 
230 ////////////////////////////////////////////////////////////////////
231 // Function: ShaderAttrib::set_instance_count
232 // Access: Published
233 // Description: Sets the geometry instance count. Do not confuse
234 // this with instanceTo, which is used for animation
235 // instancing, and has nothing to do with this.
236 // A value of 0 means not to use instancing at all.
237 ////////////////////////////////////////////////////////////////////
238 CPT(RenderAttrib) ShaderAttrib::
239 set_instance_count(int instance_count) const {
240  ShaderAttrib *result = new ShaderAttrib(*this);
241  result->_instance_count = instance_count;
242  return return_new(result);
243 }
244 
245 ////////////////////////////////////////////////////////////////////
246 // Function: ShaderAttrib::clear_shader_input
247 // Access: Published
248 // Description:
249 ////////////////////////////////////////////////////////////////////
250 CPT(RenderAttrib) ShaderAttrib::
251 clear_shader_input(const InternalName *id) const {
252  ShaderAttrib *result = new ShaderAttrib(*this);
253  result->_inputs.erase(id);
254  return return_new(result);
255 }
256 
257 ////////////////////////////////////////////////////////////////////
258 // Function: ShaderAttrib::clear_shader_input
259 // Access: Published
260 // Description:
261 ////////////////////////////////////////////////////////////////////
262 CPT(RenderAttrib) ShaderAttrib::
263 clear_shader_input(const string &id) const {
264  return clear_shader_input(InternalName::make(id));
265 }
266 
267 ////////////////////////////////////////////////////////////////////
268 // Function: ShaderAttrib::clear_all_shader_inputs
269 // Access: Published
270 // Description: Clears all the shader inputs on the attrib.
271 ////////////////////////////////////////////////////////////////////
272 CPT(RenderAttrib) ShaderAttrib::
273 clear_all_shader_inputs() const {
274  ShaderAttrib *result = new ShaderAttrib(*this);
275  result->_inputs.clear();
276  return return_new(result);
277 }
278 
279 ////////////////////////////////////////////////////////////////////
280 // Function: ShaderAttrib::get_shader_input
281 // Access: Published
282 // Description: Returns the ShaderInput of the given name. If
283 // no such name is found, this function does not return
284 // NULL --- it returns the "blank" ShaderInput.
285 ////////////////////////////////////////////////////////////////////
286 const ShaderInput *ShaderAttrib::
287 get_shader_input(const InternalName *id) const {
288  Inputs::const_iterator i = _inputs.find(id);
289  if (i == _inputs.end()) {
290  return ShaderInput::get_blank();
291  } else {
292  return (*i).second;
293  }
294 }
295 
296 ////////////////////////////////////////////////////////////////////
297 // Function: ShaderAttrib::get_shader_input
298 // Access: Published
299 // Description: Returns the ShaderInput of the given name. If
300 // no such name is found, this function does not return
301 // NULL --- it returns the "blank" ShaderInput.
302 ////////////////////////////////////////////////////////////////////
303 const ShaderInput *ShaderAttrib::
304 get_shader_input(const string &id) const {
305  return get_shader_input(InternalName::make(id));
306 }
307 
308 ////////////////////////////////////////////////////////////////////
309 // Function: ShaderAttrib::get_shader_input_nodepath
310 // Access: Published
311 // Description: Returns the ShaderInput as a nodepath. Assertion
312 // fails if there is none, or if it is not a nodepath.
313 ////////////////////////////////////////////////////////////////////
314 const NodePath &ShaderAttrib::
315 get_shader_input_nodepath(const InternalName *id) const {
316  static NodePath resfail;
317  Inputs::const_iterator i = _inputs.find(id);
318  if (i == _inputs.end()) {
319  ostringstream strm;
320  strm << "Shader input " << id->get_name() << " is not present.\n";
321  nassert_raise(strm.str());
322  return resfail;
323  } else {
324  const ShaderInput *p = (*i).second;
325  if (p->get_value_type() != ShaderInput::M_nodepath) {
326  ostringstream strm;
327  strm << "Shader input " << id->get_name() << " is not a nodepath.\n";
328  nassert_raise(strm.str());
329  return resfail;
330  }
331  return p->get_nodepath();
332  }
333 
334  // Satisfy compiler.
335  return resfail;
336 }
337 
338 ////////////////////////////////////////////////////////////////////
339 // Function: ShaderAttrib::get_shader_input_vector
340 // Access: Published
341 // Description: Returns the ShaderInput as a vector. Assertion
342 // fails if there is none, or if it is not a vector.
343 ////////////////////////////////////////////////////////////////////
344 LVecBase4 ShaderAttrib::
345 get_shader_input_vector(InternalName *id) const {
346  static LVecBase4 resfail(0,0,0,0);
347  Inputs::const_iterator i = _inputs.find(id);
348  if (i == _inputs.end()) {
349  ostringstream strm;
350  strm << "Shader input " << id->get_name() << " is not present.\n";
351  nassert_raise(strm.str());
352  return resfail;
353  } else {
354  const ShaderInput *p = (*i).second;
355 
356  if (p->get_value_type() == ShaderInput::M_vector) {
357  return p->get_vector();
358 
359  } else if (p->get_value_type() == ShaderInput::M_numeric && p->get_ptr()._size <= 4) {
360  const Shader::ShaderPtrData &ptr = p->get_ptr();
361 
362  switch (ptr._type) {
363  case Shader::SPT_float:
364  {
365  LVector4f vectorf;
366  memcpy(&vectorf[0], ptr._ptr, sizeof(float) * ptr._size);
367  return LCAST(PN_stdfloat, vectorf);
368  }
369  case Shader::SPT_double:
370  {
371  LVector4d vectord;
372  memcpy(&vectord[0], ptr._ptr, sizeof(double) * ptr._size);
373  return LCAST(PN_stdfloat, vectord);
374  }
375  default:
376  {
377  ostringstream strm;
378  strm << "Shader input " << id->get_name() << " does not contain floating-point data.\n";
379  nassert_raise(strm.str());
380  return resfail;
381  }
382  }
383 
384  } else if (p->get_value_type() == ShaderInput::M_param) {
385  // Temporary solution until the new param system
386  ParamValueBase *param = p->get_param();
387  if (param != NULL && param->is_of_type(ParamVecBase4::get_class_type())) {
388  return ((const ParamVecBase4 *) param)->get_value();
389  }
390  }
391 
392  ostringstream strm;
393  strm << "Shader input " << id->get_name() << " is not a vector.\n";
394  nassert_raise(strm.str());
395  return resfail;
396  }
397 }
398 
399 ////////////////////////////////////////////////////////////////////
400 // Function: ShaderAttrib::get_shader_input_ptr
401 // Access: Published
402 // Description: Returns the ShaderInput as a ShaderPtrData struct.
403 // Assertion fails if there is none. or if it is not
404 // a PTA(double/float)
405 ////////////////////////////////////////////////////////////////////
406 const Shader::ShaderPtrData *ShaderAttrib::
407 get_shader_input_ptr(const InternalName *id) const {
408  Inputs::const_iterator i = _inputs.find(id);
409  if (i == _inputs.end()) {
410  ostringstream strm;
411  strm << "Shader input " << id->get_name() << " is not present.\n";
412  nassert_raise(strm.str());
413  return NULL;
414  } else {
415  const ShaderInput *p = (*i).second;
416  if (p->get_value_type() != ShaderInput::M_numeric &&
417  p->get_value_type() != ShaderInput::M_vector) {
418  ostringstream strm;
419  strm << "Shader input " << id->get_name() << " is not a PTA(float/double) type.\n";
420  nassert_raise(strm.str());
421  return NULL;
422  }
423  return &(p->get_ptr());
424  }
425 }
426 
427 ////////////////////////////////////////////////////////////////////
428 // Function: ShaderAttrib::get_shader_input_texture
429 // Access: Published
430 // Description: Returns the ShaderInput as a texture. Assertion
431 // fails if there is none, or if it is not a texture.
432 ////////////////////////////////////////////////////////////////////
433 Texture *ShaderAttrib::
434 get_shader_input_texture(const InternalName *id) const {
435  Inputs::const_iterator i = _inputs.find(id);
436  if (i == _inputs.end()) {
437  ostringstream strm;
438  strm << "Shader input " << id->get_name() << " is not present.\n";
439  nassert_raise(strm.str());
440  return NULL;
441  } else {
442  const ShaderInput *p = (*i).second;
443  if (p->get_value_type() != ShaderInput::M_texture &&
444  p->get_value_type() != ShaderInput::M_texture_sampler) {
445  ostringstream strm;
446  strm << "Shader input " << id->get_name() << " is not a texture.\n";
447  nassert_raise(strm.str());
448  return NULL;
449  }
450  return p->get_texture();
451  }
452 }
453 
454 ////////////////////////////////////////////////////////////////////
455 // Function: ShaderAttrib::get_shader_input_sampler
456 // Access: Published
457 // Description: Returns the ShaderInput as a sampler. Assertion
458 // fails if there is none, or if it is not a texture.
459 ////////////////////////////////////////////////////////////////////
460 const SamplerState &ShaderAttrib::
461 get_shader_input_sampler(const InternalName *id) const {
462  Inputs::const_iterator i = _inputs.find(id);
463  if (i == _inputs.end()) {
464  ostringstream strm;
465  strm << "Shader input " << id->get_name() << " is not present.\n";
466  nassert_raise(strm.str());
467  return SamplerState::get_default();
468  } else {
469  const ShaderInput *p = (*i).second;
470  if (p->get_value_type() != ShaderInput::M_texture &&
471  p->get_value_type() != ShaderInput::M_texture_sampler) {
472  ostringstream strm;
473  strm << "Shader input " << id->get_name() << " is not a texture.\n";
474  nassert_raise(strm.str());
475  return SamplerState::get_default();
476  }
477  return p->get_sampler();
478  }
479 }
480 
481 ////////////////////////////////////////////////////////////////////
482 // Function: ShaderAttrib::get_shader_input_matrix
483 // Access: Published
484 // Description: Returns the ShaderInput as a matrix. Assertion
485 // fails if there is none, or if it is not a matrix
486 // or NodePath.
487 ////////////////////////////////////////////////////////////////////
488 const LMatrix4 &ShaderAttrib::
489 get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const {
490  Inputs::const_iterator i = _inputs.find(id);
491  if (i == _inputs.end()) {
492  ostringstream strm;
493  strm << "Shader input " << id->get_name() << " is not present.\n";
494  nassert_raise(strm.str());
495  return LMatrix4::ident_mat();
496  } else {
497  const ShaderInput *p = (*i).second;
498 
499  if (p->get_value_type() == ShaderInput::M_nodepath) {
500  const NodePath &np = p->get_nodepath();
501  nassertr(!np.is_empty(), LMatrix4::ident_mat());
502  return np.get_transform()->get_mat();
503 
504  } else if (p->get_value_type() == ShaderInput::M_numeric &&
505  p->get_ptr()._size >= 16 && (p->get_ptr()._size & 15) == 0) {
506  const Shader::ShaderPtrData &ptr = p->get_ptr();
507 
508  switch (ptr._type) {
509  case Shader::SPT_float: {
510  LMatrix4f matrixf;
511  memcpy(&matrixf(0, 0), ptr._ptr, sizeof(float) * 16);
512  matrix = LCAST(PN_stdfloat, matrixf);
513  return matrix;
514  }
515  case Shader::SPT_double: {
516  LMatrix4d matrixd;
517  memcpy(&matrixd(0, 0), ptr._ptr, sizeof(double) * 16);
518  matrix = LCAST(PN_stdfloat, matrixd);
519  return matrix;
520  }
521  default: {
522  ostringstream strm;
523  strm << "Shader input " << id->get_name() << " does not contain floating-point data.\n";
524  nassert_raise(strm.str());
525  return LMatrix4::ident_mat();
526  }
527  }
528  }
529 
530  ostringstream strm;
531  strm << "Shader input " << id->get_name() << " is not a NodePath, LMatrix4 or PTA_LMatrix4.\n";
532  nassert_raise(strm.str());
533  return LMatrix4::ident_mat();
534  }
535 }
536 
537 ////////////////////////////////////////////////////////////////////
538 // Function: ShaderAttrib::get_shader
539 // Access: Published
540 // Description: Returns the shader object associated with the node.
541 // If get_override returns true, but get_shader
542 // returns NULL, that means that this attribute should
543 // disable the shader.
544 ////////////////////////////////////////////////////////////////////
545 const Shader *ShaderAttrib::
546 get_shader() const {
547  return _shader;
548 }
549 
550 ////////////////////////////////////////////////////////////////////
551 // Function: ShaderAttrib::compare_to_impl
552 // Access: Protected, Virtual
553 // Description: Intended to be overridden by derived ShaderAttrib
554 // types to return a unique number indicating whether
555 // this ShaderAttrib is equivalent to the other one.
556 //
557 // This should return 0 if the two ShaderAttrib objects
558 // are equivalent, a number less than zero if this one
559 // should be sorted before the other one, and a number
560 // greater than zero otherwise.
561 //
562 // This will only be called with two ShaderAttrib
563 // objects whose get_type() functions return the same.
564 ////////////////////////////////////////////////////////////////////
565 int ShaderAttrib::
566 compare_to_impl(const RenderAttrib *other) const {
567  const ShaderAttrib *that;
568  DCAST_INTO_R(that, other, 0);
569 
570  if (this->_shader != that->_shader) {
571  return (this->_shader < that->_shader) ? -1 : 1;
572  }
573  if (this->_shader_priority != that->_shader_priority) {
574  return (this->_shader_priority < that->_shader_priority) ? -1 : 1;
575  }
576  if (this->_auto_shader != that->_auto_shader) {
577  return (this->_auto_shader < that->_auto_shader) ? -1 : 1;
578  }
579  if (this->_has_shader != that->_has_shader) {
580  return (this->_has_shader < that->_has_shader) ? -1 : 1;
581  }
582  if (this->_flags != that->_flags) {
583  return (this->_flags < that->_flags) ? -1 : 1;
584  }
585  if (this->_has_flags != that->_has_flags) {
586  return (this->_has_flags < that->_has_flags) ? -1 : 1;
587  }
588  if (this->_instance_count != that->_instance_count) {
589  return (this->_instance_count < that->_instance_count) ? -1 : 1;
590  }
591  if (this->_auto_normal_on != that->_auto_normal_on) {
592  return (this->_auto_normal_on < that->_auto_normal_on) ? -1 : 1;
593  }
594  if (this->_auto_glow_on != that->_auto_glow_on) {
595  return (this->_auto_glow_on < that->_auto_glow_on) ? -1 : 1;
596  }
597  if (this->_auto_gloss_on != that->_auto_gloss_on) {
598  return (this->_auto_gloss_on < that->_auto_gloss_on) ? -1 : 1;
599  }
600  if (this->_auto_ramp_on != that->_auto_ramp_on) {
601  return (this->_auto_ramp_on < that->_auto_ramp_on) ? -1 : 1;
602  }
603  if (this->_auto_shadow_on != that->_auto_shadow_on) {
604  return (this->_auto_shadow_on < that->_auto_shadow_on) ? -1 : 1;
605  }
606 
607  Inputs::const_iterator i1 = this->_inputs.begin();
608  Inputs::const_iterator i2 = that->_inputs.begin();
609  while ((i1 != this->_inputs.end()) && (i2 != that->_inputs.end())) {
610  if (i1->second != i2->second) {
611  return (i1->second < i2->second) ? -1 : 1;
612  }
613  ++i1;
614  ++i2;
615  }
616  if (i1 != this->_inputs.end()) {
617  return 1;
618  }
619  if (i2 != that->_inputs.end()) {
620  return -1;
621  }
622 
623  return 0;
624 }
625 
626 ////////////////////////////////////////////////////////////////////
627 // Function: ShaderAttrib::get_hash_impl
628 // Access: Protected, Virtual
629 // Description: Intended to be overridden by derived RenderAttrib
630 // types to return a unique hash for these particular
631 // properties. RenderAttribs that compare the same with
632 // compare_to_impl(), above, should return the same
633 // hash; RenderAttribs that compare differently should
634 // return a different hash.
635 ////////////////////////////////////////////////////////////////////
636 size_t ShaderAttrib::
637 get_hash_impl() const {
638  size_t hash = 0;
639  hash = pointer_hash::add_hash(hash, _shader);
640  hash = int_hash::add_hash(hash, _shader_priority);
641  hash = int_hash::add_hash(hash, (int)_auto_shader);
642  hash = int_hash::add_hash(hash, (int)_has_shader);
643  hash = int_hash::add_hash(hash, _flags);
644  hash = int_hash::add_hash(hash, _has_flags);
645  hash = int_hash::add_hash(hash, _instance_count);
646  hash = int_hash::add_hash(hash, (int)_auto_normal_on);
647  hash = int_hash::add_hash(hash, (int)_auto_glow_on);
648  hash = int_hash::add_hash(hash, (int)_auto_gloss_on);
649  hash = int_hash::add_hash(hash, (int)_auto_shadow_on);
650 
651  Inputs::const_iterator ii;
652  for (ii = _inputs.begin(); ii != _inputs.end(); ++ii) {
653  hash = pointer_hash::add_hash(hash, (*ii).first);
654  hash = pointer_hash::add_hash(hash, (*ii).second);
655  }
656 
657  return hash;
658 }
659 
660 ////////////////////////////////////////////////////////////////////
661 // Function: ShaderAttrib::compose_impl
662 // Access: Public, Virtual
663 // Description:
664 ////////////////////////////////////////////////////////////////////
665 CPT(RenderAttrib) ShaderAttrib::
666 compose_impl(const RenderAttrib *other) const {
667  ShaderAttrib *attr = new ShaderAttrib(*this);
668  const ShaderAttrib *over;
669  DCAST_INTO_R(over, other, 0);
670  // Update the shader portion.
671  if (over->_has_shader) {
672  if ((attr->_has_shader == false) ||
673  (over->_shader_priority >= attr->_shader_priority)) {
674  attr->_shader = over->_shader;
675  attr->_shader_priority = over->_shader_priority;
676  attr->_auto_shader = over->_auto_shader;
677  attr->_has_shader = over->_has_shader;
678  attr->_auto_normal_on = over->_auto_normal_on;
679  attr->_auto_glow_on = over->_auto_glow_on;
680  attr->_auto_gloss_on = over->_auto_gloss_on;
681  attr->_auto_ramp_on = over->_auto_ramp_on;
682  attr->_auto_shadow_on = over->_auto_shadow_on;
683  }
684  }
685  // Update the shader-data portion.
686  Inputs::const_iterator iover;
687  for (iover=over->_inputs.begin(); iover!=over->_inputs.end(); ++iover) {
688  const InternalName *id = (*iover).first;
689  const ShaderInput *dover = (*iover).second;
690  Inputs::iterator iattr = attr->_inputs.find(id);
691  if (iattr == attr->_inputs.end()) {
692  attr->_inputs.insert(Inputs::value_type(id,dover));
693  } else {
694  const ShaderInput *dattr = (*iattr).second;
695  if (dattr->get_priority() <= dover->get_priority()) {
696  iattr->second = iover->second;
697  }
698  }
699  }
700  // Just copy the instance count.
701  attr->_instance_count = over->_instance_count;
702  // Update the flags.
703  attr->_flags &= ~(over->_has_flags);
704  attr->_flags |= over->_flags;
705  attr->_has_flags |= (over->_has_flags);
706  return return_new(attr);
707 }
708 
709 ////////////////////////////////////////////////////////////////////
710 // Function: ShaderAttrib::get_auto_shader_attrib_impl
711 // Access: Protected, Virtual
712 // Description:
713 ////////////////////////////////////////////////////////////////////
714 CPT(RenderAttrib) ShaderAttrib::
715 get_auto_shader_attrib_impl(const RenderState *state) const {
716  // For a ShaderAttrib, we only need to preserve the auto-shader
717  // flags. Custom shaders, and custom shader inputs, aren't relevant
718  // to the shader generator.
719  ShaderAttrib *attrib = new ShaderAttrib;
720  attrib->_auto_shader = _auto_shader;
721  attrib->_has_shader = _has_shader;
722  attrib->_auto_normal_on = _auto_normal_on;
723  attrib->_auto_glow_on = _auto_glow_on;
724  attrib->_auto_gloss_on = _auto_gloss_on;
725  attrib->_auto_ramp_on = _auto_ramp_on;
726  attrib->_auto_shadow_on = _auto_shadow_on;
727  return return_new(attrib);
728 }
729 
730 ////////////////////////////////////////////////////////////////////
731 // Function: ShaderAttrib::register_with_read_factory
732 // Access: Public, Static
733 // Description: Factory method to generate a Shader object
734 ////////////////////////////////////////////////////////////////////
735 void ShaderAttrib::
736 register_with_read_factory() {
737  // IMPLEMENT ME
738 }
739 
static const LMatrix4f & ident_mat()
Returns an identity matrix.
Definition: lmatrix.h:903
static size_t add_hash(size_t start, const void *key)
Adds the indicated key into a running hash.
Definition: stl_compares.I:133
This is a four-component vector distance.
Definition: lvector4.h:441
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:4716
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:60
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:236
const NodePath & get_nodepath() const
Warning: no error checking is done.
Definition: shaderInput.cxx:60
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:75
Definition: shader.h:50
This is a small container class that can hold any one of the value types that can be passed as input ...
Definition: shaderInput.h:41
static const ShaderInput * get_blank()
Returns a static ShaderInput object with name NULL, priority zero, type INVALID, and all value-fields...
Definition: shaderInput.cxx:28
A handy class object for storing simple values (like integers or strings) passed along with an Event ...
Definition: paramValue.h:109
static size_t add_hash(size_t start, const Key &key)
Adds the indicated key into a running hash.
Definition: stl_compares.I:122
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
Definition: bitMask.I:212
A non-template base class of ParamValue (below), which serves mainly to define the placeholder for th...
Definition: paramValue.h:34
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
This is a four-component vector distance.
Definition: lvector4.h:91
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:53
Represents a set of settings that indicate how a texture is sampled.
Definition: samplerState.h:39
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
static const SamplerState & get_default()
Returns a reference to the global default immutable SamplerState object.
Definition: samplerState.I:44
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
Definition: nodePath.cxx:925
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165