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);
288 Inputs::const_iterator i = _inputs.find(
id);
289 if (i == _inputs.end()) {
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());
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());
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());
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();
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();
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 && p->get_ptr()._size == 16) {
508 case Shader::SPT_float: {
510 memcpy(&matrixf(0, 0), ptr._ptr,
sizeof(
float) * 16);
511 matrix = LCAST(PN_stdfloat, matrixf);
514 case Shader::SPT_double: {
516 memcpy(&matrixd(0, 0), ptr._ptr,
sizeof(
double) * 16);
517 matrix = LCAST(PN_stdfloat, matrixd);
522 strm <<
"Shader input " <<
id->get_name() <<
" does not contain floating-point data.\n";
523 nassert_raise(strm.str());
530 strm <<
"Shader input " <<
id->get_name() <<
" is not a NodePath or LMatrix4.\n";
531 nassert_raise(strm.str());
567 DCAST_INTO_R(that, other, 0);
569 if (this->_shader != that->_shader) {
570 return (this->_shader < that->_shader) ? -1 : 1;
572 if (this->_shader_priority != that->_shader_priority) {
573 return (this->_shader_priority < that->_shader_priority) ? -1 : 1;
575 if (this->_auto_shader != that->_auto_shader) {
576 return (this->_auto_shader < that->_auto_shader) ? -1 : 1;
578 if (this->_has_shader != that->_has_shader) {
579 return (this->_has_shader < that->_has_shader) ? -1 : 1;
581 if (this->_flags != that->_flags) {
582 return (this->_flags < that->_flags) ? -1 : 1;
584 if (this->_has_flags != that->_has_flags) {
585 return (this->_has_flags < that->_has_flags) ? -1 : 1;
587 if (this->_instance_count != that->_instance_count) {
588 return (this->_instance_count < that->_instance_count) ? -1 : 1;
590 if (this->_auto_normal_on != that->_auto_normal_on) {
591 return (this->_auto_normal_on < that->_auto_normal_on) ? -1 : 1;
593 if (this->_auto_glow_on != that->_auto_glow_on) {
594 return (this->_auto_glow_on < that->_auto_glow_on) ? -1 : 1;
596 if (this->_auto_gloss_on != that->_auto_gloss_on) {
597 return (this->_auto_gloss_on < that->_auto_gloss_on) ? -1 : 1;
599 if (this->_auto_ramp_on != that->_auto_ramp_on) {
600 return (this->_auto_ramp_on < that->_auto_ramp_on) ? -1 : 1;
602 if (this->_auto_shadow_on != that->_auto_shadow_on) {
603 return (this->_auto_shadow_on < that->_auto_shadow_on) ? -1 : 1;
606 Inputs::const_iterator i1 = this->_inputs.begin();
607 Inputs::const_iterator i2 = that->_inputs.begin();
608 while ((i1 != this->_inputs.end()) && (i2 != that->_inputs.end())) {
609 if (i1->second != i2->second) {
610 return (i1->second < i2->second) ? -1 : 1;
615 if (i1 != this->_inputs.end()) {
618 if (i2 != that->_inputs.end()) {
635 size_t ShaderAttrib::
636 get_hash_impl()
const {
650 Inputs::const_iterator ii;
651 for (ii = _inputs.begin(); ii != _inputs.end(); ++ii) {
668 DCAST_INTO_R(over, other, 0);
670 if (over->_has_shader) {
671 if ((attr->_has_shader ==
false) ||
672 (over->_shader_priority >= attr->_shader_priority)) {
673 attr->_shader = over->_shader;
674 attr->_shader_priority = over->_shader_priority;
675 attr->_auto_shader = over->_auto_shader;
676 attr->_has_shader = over->_has_shader;
677 attr->_auto_normal_on = over->_auto_normal_on;
678 attr->_auto_glow_on = over->_auto_glow_on;
679 attr->_auto_gloss_on = over->_auto_gloss_on;
680 attr->_auto_ramp_on = over->_auto_ramp_on;
681 attr->_auto_shadow_on = over->_auto_shadow_on;
685 Inputs::const_iterator iover;
686 for (iover=over->_inputs.begin(); iover!=over->_inputs.end(); ++iover) {
687 const InternalName *
id = (*iover).first;
689 Inputs::iterator iattr = attr->_inputs.find(
id);
690 if (iattr == attr->_inputs.end()) {
691 attr->_inputs.insert(Inputs::value_type(
id,dover));
694 if (dattr->get_priority() <= dover->get_priority()) {
695 iattr->second = iover->second;
700 attr->_instance_count = over->_instance_count;
702 attr->_flags &= ~(over->_has_flags);
703 attr->_flags |= over->_flags;
704 attr->_has_flags |= (over->_has_flags);
705 return return_new(attr);
714 get_auto_shader_attrib_impl(const
RenderState *state)
const {
719 attrib->_auto_shader = _auto_shader;
720 attrib->_has_shader = _has_shader;
721 attrib->_auto_normal_on = _auto_normal_on;
722 attrib->_auto_glow_on = _auto_glow_on;
723 attrib->_auto_gloss_on = _auto_gloss_on;
724 attrib->_auto_ramp_on = _auto_ramp_on;
725 attrib->_auto_shadow_on = _auto_shadow_on;
726 return return_new(attrib);
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.
LVecBase4 get_shader_input_vector(InternalName *id) const
Returns the ShaderInput as a vector.
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...
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Texture * get_shader_input_texture(const InternalName *id) const
Returns the ShaderInput as a texture.
A handy class object for storing simple values (like integers or strings) passed along with an Event ...
const Shader * get_shader() const
Returns the shader object associated with the node.
const LMatrix4 & get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const
Returns the ShaderInput as a matrix.
static size_t add_hash(size_t start, const Key &key)
Adds the indicated key into a running hash.
const ShaderInput * get_shader_input(const InternalName *id) const
Returns the ShaderInput of the given name.
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.
static void register_with_read_factory()
Factory method to generate a Shader object.
This is a four-component vector distance.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
const SamplerState & get_shader_input_sampler(const InternalName *id) const
Returns the ShaderInput as a sampler.
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_empty() const
Returns true if the NodePath contains no nodes.
const NodePath & get_shader_input_nodepath(const InternalName *id) const
Returns the ShaderInput as a nodepath.
TypeHandle is the identifier used to differentiate C++ class types.
const Shader::ShaderPtrData * get_shader_input_ptr(const InternalName *id) const
Returns the ShaderInput as a ShaderPtrData struct.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...