33 using std::ostringstream;
36 int ShaderAttrib::_attrib_slot;
45 if (_off_attrib ==
nullptr) {
47 attrib->_has_shader =
true;
48 _off_attrib = return_new(attrib);
57 make(
const Shader *shader,
int priority) {
59 if (_null_attrib ==
nullptr) {
61 _null_attrib = return_new(attrib);
64 if (shader ==
nullptr) {
67 return DCAST(
ShaderAttrib, _null_attrib)->set_shader(shader, priority);
84 set_shader(
const Shader *s,
int priority)
const {
87 result->_shader_priority = priority;
88 result->_auto_shader =
false;
89 result->_has_shader =
true;
90 return return_new(result);
97 set_shader_off(
int priority)
const {
99 result->_shader =
nullptr;
100 result->_shader_priority = priority;
101 result->_auto_shader =
false;
102 result->_auto_normal_on =
false;
103 result->_auto_glow_on =
false;
104 result->_auto_gloss_on =
false;
105 result->_auto_ramp_on =
false;
106 result->_auto_shadow_on =
false;
108 result->_has_shader =
true;
109 return return_new(result);
116 set_shader_auto(
int priority)
const {
118 result->_shader =
nullptr;
119 result->_shader_priority = priority;
120 result->_auto_shader =
true;
121 result->_has_shader =
true;
122 result->_auto_normal_on =
true;
123 result->_auto_glow_on =
true;
124 result->_auto_gloss_on =
true;
125 result->_auto_ramp_on =
true;
126 result->_auto_shadow_on =
true;
127 return return_new(result);
135 set_shader_auto(
BitMask32 shader_switch,
int priority)
const {
138 result->_shader =
nullptr;
139 result->_shader_priority = priority;
140 result->_auto_shader =
true;
141 result->_has_shader =
true;
142 result->_auto_normal_on = shader_switch.
get_bit(Shader::bit_AutoShaderNormal);
143 result->_auto_glow_on = shader_switch.
get_bit(Shader::bit_AutoShaderGlow);
144 result->_auto_gloss_on = shader_switch.
get_bit(Shader::bit_AutoShaderGloss);
145 result->_auto_ramp_on = shader_switch.
get_bit(Shader::bit_AutoShaderRamp);
146 result->_auto_shadow_on = shader_switch.
get_bit(Shader::bit_AutoShaderShadow);
148 return return_new(result);
155 clear_shader()
const {
157 result->_shader =
nullptr;
158 result->_shader_priority = 0;
159 result->_auto_shader =
false;
160 result->_has_shader =
false;
161 result->_auto_normal_on =
false;
162 result->_auto_glow_on =
false;
163 result->_auto_gloss_on =
false;
164 result->_auto_ramp_on =
false;
165 result->_auto_shadow_on =
false;
166 return return_new(result);
173 set_flag(
int flag,
bool value)
const {
177 result->_flags |= bit;
179 result->_flags &= ~bit;
181 result->_has_flags |= bit;
182 return return_new(result);
189 clear_flag(
int flag)
const {
192 result->_flags &= ~bit;
193 result->_has_flags &= ~bit;
194 return return_new(result);
203 Inputs::iterator i = result->_inputs.find(input.get_name());
204 if (i == result->_inputs.end()) {
205 result->_inputs.insert(Inputs::value_type(input.get_name(), input));
209 return return_new(result);
218 Inputs::iterator i = result->_inputs.find(input.get_name());
219 if (i == result->_inputs.end()) {
220 result->_inputs.insert(Inputs::value_type(input.get_name(), std::move(input)));
222 i->second = std::move(input);
224 return return_new(result);
233 set_instance_count(
int instance_count)
const {
235 result->_instance_count = instance_count;
236 return return_new(result);
245 result->_inputs.erase(
id);
246 return return_new(result);
253 clear_shader_input(
const std::string &
id)
const {
254 return clear_shader_input(InternalName::make(
id));
261 clear_all_shader_inputs()
const {
263 result->_inputs.clear();
264 return return_new(result);
273 Inputs::const_iterator i = _inputs.find(
id);
274 if (i != _inputs.end()) {
286 get_shader_input(
const std::string &
id)
const {
287 return get_shader_input(InternalName::make(
id));
295 get_shader_input_nodepath(
const InternalName *
id)
const {
297 Inputs::const_iterator i = _inputs.find(
id);
298 if (i != _inputs.end()) {
300 if (p.get_value_type() == ShaderInput::M_nodepath) {
304 strm <<
"Shader input " <<
id->get_name() <<
" is not a nodepath.\n";
305 nassert_raise(strm.str());
310 strm <<
"Shader input " <<
id->
get_name() <<
" is not present.\n";
311 nassert_raise(strm.str());
323 LVecBase4 ShaderAttrib::
325 static LVecBase4 resfail(0,0,0,0);
326 Inputs::const_iterator i = _inputs.find(
id);
327 if (i != _inputs.end()) {
330 if (p.get_value_type() == ShaderInput::M_vector) {
331 return p.get_vector();
333 }
else if (p.get_value_type() == ShaderInput::M_numeric && p.get_ptr()._size <= 4) {
337 case Shader::SPT_float:
340 memcpy(&vectorf[0], ptr._ptr,
sizeof(
float) * ptr._size);
341 return LCAST(PN_stdfloat, vectorf);
343 case Shader::SPT_double:
346 memcpy(&vectord[0], ptr._ptr,
sizeof(
double) * ptr._size);
347 return LCAST(PN_stdfloat, vectord);
352 strm <<
"Shader input " <<
id->get_name() <<
" does not contain floating-point data.\n";
353 nassert_raise(strm.str());
358 }
else if (p.get_value_type() == ShaderInput::M_param) {
361 if (param !=
nullptr && param->
is_of_type(ParamVecBase4::get_class_type())) {
367 strm <<
"Shader input " <<
id->get_name() <<
" is not a vector.\n";
368 nassert_raise(strm.str());
371 strm <<
"Shader input " <<
id->get_name() <<
" is not present.\n";
372 nassert_raise(strm.str());
383 Inputs::const_iterator i = _inputs.find(
id);
384 if (i != _inputs.end()) {
386 if (p.get_value_type() != ShaderInput::M_numeric &&
387 p.get_value_type() != ShaderInput::M_vector) {
389 strm <<
"Shader input " <<
id->get_name() <<
" is not a PTA(float/double) type.\n";
390 nassert_raise(strm.str());
393 return &(p.get_ptr());
396 strm <<
"Shader input " <<
id->get_name() <<
" is not present.\n";
397 nassert_raise(strm.str());
411 Inputs::const_iterator i = _inputs.find(
id);
412 if (i != _inputs.end()) {
414 switch (p.get_value_type()) {
415 case ShaderInput::M_texture:
424 case ShaderInput::M_texture_sampler:
435 strm <<
"Shader input " <<
id->get_name() <<
" is not a texture.\n";
436 nassert_raise(strm.str());
442 strm <<
"Shader input " <<
id->get_name() <<
" is not present.\n";
443 nassert_raise(strm.str());
452 const LMatrix4 &ShaderAttrib::
453 get_shader_input_matrix(
const InternalName *
id, LMatrix4 &matrix)
const {
454 Inputs::const_iterator i = _inputs.find(
id);
455 if (i != _inputs.end()) {
458 if (p.get_value_type() == ShaderInput::M_nodepath) {
460 nassertr(!np.
is_empty(), LMatrix4::ident_mat());
463 }
else if (p.get_value_type() == ShaderInput::M_numeric &&
464 p.get_ptr()._size >= 16 && (p.get_ptr()._size & 15) == 0) {
468 case Shader::SPT_float: {
470 memcpy(&matrixf(0, 0), ptr._ptr,
sizeof(
float) * 16);
471 matrix = LCAST(PN_stdfloat, matrixf);
474 case Shader::SPT_double: {
476 memcpy(&matrixd(0, 0), ptr._ptr,
sizeof(
double) * 16);
477 matrix = LCAST(PN_stdfloat, matrixd);
482 strm <<
"Shader input " <<
id->get_name() <<
" does not contain floating-point data.\n";
483 nassert_raise(strm.str());
484 return LMatrix4::ident_mat();
490 strm <<
"Shader input " <<
id->get_name() <<
" is not a NodePath, LMatrix4 or PTA_LMatrix4.\n";
491 nassert_raise(strm.str());
492 return LMatrix4::ident_mat();
495 strm <<
"Shader input " <<
id->get_name() <<
" is not present.\n";
496 nassert_raise(strm.str());
497 return LMatrix4::ident_mat();
507 Inputs::const_iterator i = _inputs.find(
id);
508 if (i == _inputs.end()) {
510 strm <<
"Shader input " <<
id->get_name() <<
" is not present.\n";
511 nassert_raise(strm.str());
516 if (p.get_value_type() == ShaderInput::M_buffer) {
518 DCAST_INTO_R(value, p._value,
nullptr);
523 strm <<
"Shader input " <<
id->get_name() <<
" is not a ShaderBuffer.\n";
524 nassert_raise(strm.str());
534 const Shader *ShaderAttrib::
543 output(ostream &out)
const {
544 out <<
"ShaderAttrib:";
549 }
else if (_has_shader) {
550 if (_shader ==
nullptr) {
557 out <<
"," << _inputs.size() <<
" inputs";
575 if (this->_shader != that->_shader) {
576 return (this->_shader < that->_shader) ? -1 : 1;
578 if (this->_shader_priority != that->_shader_priority) {
579 return (this->_shader_priority < that->_shader_priority) ? -1 : 1;
581 if (this->_auto_shader != that->_auto_shader) {
582 return (this->_auto_shader < that->_auto_shader) ? -1 : 1;
584 if (this->_has_shader != that->_has_shader) {
585 return (this->_has_shader < that->_has_shader) ? -1 : 1;
587 if (this->_flags != that->_flags) {
588 return (this->_flags < that->_flags) ? -1 : 1;
590 if (this->_has_flags != that->_has_flags) {
591 return (this->_has_flags < that->_has_flags) ? -1 : 1;
593 if (this->_instance_count != that->_instance_count) {
594 return (this->_instance_count < that->_instance_count) ? -1 : 1;
596 if (this->_auto_normal_on != that->_auto_normal_on) {
597 return (this->_auto_normal_on < that->_auto_normal_on) ? -1 : 1;
599 if (this->_auto_glow_on != that->_auto_glow_on) {
600 return (this->_auto_glow_on < that->_auto_glow_on) ? -1 : 1;
602 if (this->_auto_gloss_on != that->_auto_gloss_on) {
603 return (this->_auto_gloss_on < that->_auto_gloss_on) ? -1 : 1;
605 if (this->_auto_ramp_on != that->_auto_ramp_on) {
606 return (this->_auto_ramp_on < that->_auto_ramp_on) ? -1 : 1;
608 if (this->_auto_shadow_on != that->_auto_shadow_on) {
609 return (this->_auto_shadow_on < that->_auto_shadow_on) ? -1 : 1;
612 Inputs::const_iterator i1 = this->_inputs.begin();
613 Inputs::const_iterator i2 = that->_inputs.begin();
614 while ((i1 != this->_inputs.end()) && (i2 != that->_inputs.end())) {
615 if (i1->second != i2->second) {
616 return (i1->second < i2->second) ? -1 : 1;
621 if (i1 != this->_inputs.end()) {
624 if (i2 != that->_inputs.end()) {
637 size_t ShaderAttrib::
638 get_hash_impl()
const {
652 Inputs::const_iterator ii;
653 for (ii = _inputs.begin(); ii != _inputs.end(); ++ii) {
654 hash = (*ii).second.add_hash(hash);
669 if (over->_has_shader) {
670 if ((attr->_has_shader ==
false) ||
671 (over->_shader_priority >= attr->_shader_priority)) {
672 attr->_shader = over->_shader;
673 attr->_shader_priority = over->_shader_priority;
674 attr->_auto_shader = over->_auto_shader;
675 attr->_has_shader = over->_has_shader;
676 attr->_auto_normal_on = over->_auto_normal_on;
677 attr->_auto_glow_on = over->_auto_glow_on;
678 attr->_auto_gloss_on = over->_auto_gloss_on;
679 attr->_auto_ramp_on = over->_auto_ramp_on;
680 attr->_auto_shadow_on = over->_auto_shadow_on;
684 Inputs::const_iterator iover;
685 for (iover=over->_inputs.begin(); iover!=over->_inputs.end(); ++iover) {
688 Inputs::iterator iattr = attr->_inputs.find(
id);
689 if (iattr == attr->_inputs.end()) {
690 attr->_inputs.insert(Inputs::value_type(
id,dover));
693 if (dattr.get_priority() <= dover.get_priority()) {
694 iattr->second = iover->second;
700 if (attr->_instance_count == 0) {
701 attr->_instance_count = over->_instance_count;
706 if (over->_instance_count > 0) {
707 attr->_instance_count = over->_instance_count;
712 attr->_flags &= ~(over->_has_flags);
713 attr->_flags |= over->_flags;
714 attr->_has_flags |= (over->_has_flags);
715 return return_new(attr);
722 register_with_read_factory() {
static size_t add_hash(size_t start, const void *key)
Adds the indicated key into a running hash.
This is a generic buffer object that lives in graphics memory.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
A class object for storing a NodePath as a parameter.
bool is_empty() const
Returns true if the NodePath contains no nodes.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CPT(RenderAttrib) ShaderAttrib
Constructs a new ShaderAttrib object that disables the use of shaders (it does not clear out all shad...
Filename get_filename(ShaderType type=ST_none) const
Return the Shader's filename for the given shader type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A handy class object for storing simple values (like integers or strings) passed along with an Event ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_default_sampler
This returns the default sampler state for this texture, containing the wrap and filter properties sp...
static size_t add_hash(size_t start, const Key &key)
Adds the indicated key into a running hash.
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_name
Returns the name of the referenced node.
get_texture
Retrieves the texture stored in the parameter.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
Encodes a string name in a hash table, mapping it to a pointer.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string get_basename() const
Returns the basename part of the filename.
Represents a set of settings that indicate how a texture is sampled.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A class object for storing a pointer to a Texture along with a sampler state that indicates how to to...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
TypeHandle is the identifier used to differentiate C++ class types.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_sampler
Retrieves the sampler state stored in the parameter.