19 #include "pandabase.h" 20 #include "shaderAttrib.h" 21 #include "graphicsStateGuardianBase.h" 22 #include "bamReader.h" 23 #include "bamWriter.h" 25 #include "datagramIterator.h" 29 int ShaderAttrib::_attrib_slot;
41 if (_off_attrib == 0) {
43 attrib->_has_shader =
true;
44 _off_attrib = return_new(attrib);
56 make(
const Shader *shader) {
58 if (_null_attrib == 0) {
60 _null_attrib = return_new(attrib);
66 return DCAST(
ShaderAttrib, _null_attrib)->set_shader(shader);
88 set_shader(
const Shader *s,
int priority)
const {
91 result->_shader_priority = priority;
92 result->_auto_shader =
false;
93 result->_has_shader =
true;
94 return return_new(result);
103 set_shader_off(
int priority)
const {
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;
114 result->_has_shader =
true;
115 return return_new(result);
124 set_shader_auto(
int priority)
const {
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);
145 set_shader_auto(
BitMask32 shader_switch,
int priority)
const {
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);
158 return return_new(result);
167 clear_shader()
const {
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);
187 set_flag(
int flag,
bool value)
const {
191 result->_flags |= bit;
193 result->_flags &= ~bit;
195 result->_has_flags |= bit;
196 return return_new(result);
205 clear_flag(
int flag)
const {
208 result->_flags &= ~bit;
209 result->_has_flags &= ~bit;
210 return return_new(result);
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));
227 return return_new(result);
239 set_instance_count(
int instance_count)
const {
241 result->_instance_count = instance_count;
242 return return_new(result);
251 clear_shader_input(
const InternalName *
id)
const {
253 result->_inputs.erase(
id);
254 return return_new(result);
263 clear_shader_input(
const string &
id)
const {
264 return clear_shader_input(InternalName::make(
id));
273 clear_all_shader_inputs()
const {
275 result->_inputs.clear();
276 return return_new(result);
287 get_shader_input(
const InternalName *
id)
const {
288 Inputs::const_iterator i = _inputs.find(
id);
289 if (i == _inputs.end()) {
304 get_shader_input(
const string &
id)
const {
305 return get_shader_input(InternalName::make(
id));
315 get_shader_input_nodepath(
const InternalName *
id)
const {
317 Inputs::const_iterator i = _inputs.find(
id);
318 if (i == _inputs.end()) {
320 strm <<
"Shader input " <<
id->get_name() <<
" is not present.\n";
321 nassert_raise(strm.str());
325 if (p->get_value_type() != ShaderInput::M_nodepath) {
327 strm <<
"Shader input " <<
id->get_name() <<
" is not a nodepath.\n";
328 nassert_raise(strm.str());
345 get_shader_input_vector(InternalName *
id)
const {
347 Inputs::const_iterator i = _inputs.find(
id);
348 if (i == _inputs.end()) {
350 strm <<
"Shader input " <<
id->get_name() <<
" is not present.\n";
351 nassert_raise(strm.str());
356 if (p->get_value_type() == ShaderInput::M_vector) {
357 return p->get_vector();
359 }
else if (p->get_value_type() == ShaderInput::M_numeric && p->get_ptr()._size <= 4) {
363 case Shader::SPT_float:
366 memcpy(&vectorf[0], ptr._ptr,
sizeof(
float) * ptr._size);
367 return LCAST(PN_stdfloat, vectorf);
369 case Shader::SPT_double:
372 memcpy(&vectord[0], ptr._ptr,
sizeof(
double) * ptr._size);
373 return LCAST(PN_stdfloat, vectord);
378 strm <<
"Shader input " <<
id->get_name() <<
" does not contain floating-point data.\n";
379 nassert_raise(strm.str());
384 }
else if (p->get_value_type() == ShaderInput::M_param) {
387 if (param != NULL && param->
is_of_type(ParamVecBase4::get_class_type())) {
393 strm <<
"Shader input " <<
id->get_name() <<
" is not a vector.\n";
394 nassert_raise(strm.str());
407 get_shader_input_ptr(
const InternalName *
id)
const {
408 Inputs::const_iterator i = _inputs.find(
id);
409 if (i == _inputs.end()) {
411 strm <<
"Shader input " <<
id->get_name() <<
" is not present.\n";
412 nassert_raise(strm.str());
416 if (p->get_value_type() != ShaderInput::M_numeric &&
417 p->get_value_type() != ShaderInput::M_vector) {
419 strm <<
"Shader input " <<
id->get_name() <<
" is not a PTA(float/double) type.\n";
420 nassert_raise(strm.str());
423 return &(p->get_ptr());
434 get_shader_input_texture(
const InternalName *
id)
const {
435 Inputs::const_iterator i = _inputs.find(
id);
436 if (i == _inputs.end()) {
438 strm <<
"Shader input " <<
id->get_name() <<
" is not present.\n";
439 nassert_raise(strm.str());
443 if (p->get_value_type() != ShaderInput::M_texture &&
444 p->get_value_type() != ShaderInput::M_texture_sampler) {
446 strm <<
"Shader input " <<
id->get_name() <<
" is not a texture.\n";
447 nassert_raise(strm.str());
450 return p->get_texture();
461 get_shader_input_sampler(
const InternalName *
id)
const {
462 Inputs::const_iterator i = _inputs.find(
id);
463 if (i == _inputs.end()) {
465 strm <<
"Shader input " <<
id->get_name() <<
" is not present.\n";
466 nassert_raise(strm.str());
470 if (p->get_value_type() != ShaderInput::M_texture &&
471 p->get_value_type() != ShaderInput::M_texture_sampler) {
473 strm <<
"Shader input " <<
id->get_name() <<
" is not a texture.\n";
474 nassert_raise(strm.str());
477 return p->get_sampler();
489 get_shader_input_matrix(
const InternalName *
id,
LMatrix4 &matrix)
const {
490 Inputs::const_iterator i = _inputs.find(
id);
491 if (i == _inputs.end()) {
493 strm <<
"Shader input " <<
id->get_name() <<
" is not present.\n";
494 nassert_raise(strm.str());
499 if (p->get_value_type() == ShaderInput::M_nodepath) {
504 }
else if (p->get_value_type() == ShaderInput::M_numeric &&
505 p->get_ptr()._size >= 16 && (p->get_ptr()._size & 15) == 0) {
509 case Shader::SPT_float: {
511 memcpy(&matrixf(0, 0), ptr._ptr,
sizeof(
float) * 16);
512 matrix = LCAST(PN_stdfloat, matrixf);
515 case Shader::SPT_double: {
517 memcpy(&matrixd(0, 0), ptr._ptr,
sizeof(
double) * 16);
518 matrix = LCAST(PN_stdfloat, matrixd);
523 strm <<
"Shader input " <<
id->get_name() <<
" does not contain floating-point data.\n";
524 nassert_raise(strm.str());
531 strm <<
"Shader input " <<
id->get_name() <<
" is not a NodePath, LMatrix4 or PTA_LMatrix4.\n";
532 nassert_raise(strm.str());
545 const Shader *ShaderAttrib::
568 DCAST_INTO_R(that, other, 0);
570 if (this->_shader != that->_shader) {
571 return (this->_shader < that->_shader) ? -1 : 1;
573 if (this->_shader_priority != that->_shader_priority) {
574 return (this->_shader_priority < that->_shader_priority) ? -1 : 1;
576 if (this->_auto_shader != that->_auto_shader) {
577 return (this->_auto_shader < that->_auto_shader) ? -1 : 1;
579 if (this->_has_shader != that->_has_shader) {
580 return (this->_has_shader < that->_has_shader) ? -1 : 1;
582 if (this->_flags != that->_flags) {
583 return (this->_flags < that->_flags) ? -1 : 1;
585 if (this->_has_flags != that->_has_flags) {
586 return (this->_has_flags < that->_has_flags) ? -1 : 1;
588 if (this->_instance_count != that->_instance_count) {
589 return (this->_instance_count < that->_instance_count) ? -1 : 1;
591 if (this->_auto_normal_on != that->_auto_normal_on) {
592 return (this->_auto_normal_on < that->_auto_normal_on) ? -1 : 1;
594 if (this->_auto_glow_on != that->_auto_glow_on) {
595 return (this->_auto_glow_on < that->_auto_glow_on) ? -1 : 1;
597 if (this->_auto_gloss_on != that->_auto_gloss_on) {
598 return (this->_auto_gloss_on < that->_auto_gloss_on) ? -1 : 1;
600 if (this->_auto_ramp_on != that->_auto_ramp_on) {
601 return (this->_auto_ramp_on < that->_auto_ramp_on) ? -1 : 1;
603 if (this->_auto_shadow_on != that->_auto_shadow_on) {
604 return (this->_auto_shadow_on < that->_auto_shadow_on) ? -1 : 1;
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;
616 if (i1 != this->_inputs.end()) {
619 if (i2 != that->_inputs.end()) {
636 size_t ShaderAttrib::
637 get_hash_impl()
const {
651 Inputs::const_iterator ii;
652 for (ii = _inputs.begin(); ii != _inputs.end(); ++ii) {
669 DCAST_INTO_R(over, other, 0);
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;
686 Inputs::const_iterator iover;
687 for (iover=over->_inputs.begin(); iover!=over->_inputs.end(); ++iover) {
688 const InternalName *
id = (*iover).first;
690 Inputs::iterator iattr = attr->_inputs.find(
id);
691 if (iattr == attr->_inputs.end()) {
692 attr->_inputs.insert(Inputs::value_type(
id,dover));
695 if (dattr->get_priority() <= dover->get_priority()) {
696 iattr->second = iover->second;
701 attr->_instance_count = over->_instance_count;
703 attr->_flags &= ~(over->_has_flags);
704 attr->_flags |= over->_flags;
705 attr->_has_flags |= (over->_has_flags);
706 return return_new(attr);
715 get_auto_shader_attrib_impl(
const RenderState *state)
const {
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);
736 register_with_read_factory() {
static const LMatrix4f & ident_mat()
Returns an identity matrix.
static size_t add_hash(size_t start, const void *key)
Adds the indicated key into a running hash.
This is a four-component vector distance.
This is a 4-by-4 transform matrix.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
bool is_empty() const
Returns true if the NodePath contains no nodes.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
A handy class object for storing simple values (like integers or strings) passed along with an Event ...
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.
A non-template base class of ParamValue (below), which serves mainly to define the placeholder for th...
This is a 4-by-4 transform matrix.
This is a four-component vector distance.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Represents a set of settings that indicate how a texture is sampled.
This is the base class for all three-component vectors and points.
static const SamplerState & get_default()
Returns a reference to the global default immutable SamplerState object.
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...