Panda3D
|
00001 // Filename: shaderAttrib.cxx 00002 // Created by: sshodhan (10Jul04) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "pandabase.h" 00016 #include "shaderAttrib.h" 00017 #include "graphicsStateGuardianBase.h" 00018 #include "bamReader.h" 00019 #include "bamWriter.h" 00020 #include "datagram.h" 00021 #include "datagramIterator.h" 00022 00023 TypeHandle ShaderAttrib::_type_handle; 00024 int ShaderAttrib::_attrib_slot; 00025 00026 //////////////////////////////////////////////////////////////////// 00027 // Function: ShaderAttrib::make_off 00028 // Access: Published, Static 00029 // Description: Constructs a new ShaderAttrib object that disables 00030 // the use of shaders (it does not clear out all shader 00031 // data, however.) 00032 //////////////////////////////////////////////////////////////////// 00033 CPT(RenderAttrib) ShaderAttrib:: 00034 make_off() { 00035 static CPT(RenderAttrib) _off_attrib; 00036 if (_off_attrib == 0) { 00037 ShaderAttrib *attrib = new ShaderAttrib; 00038 attrib->_has_shader = true; 00039 _off_attrib = return_new(attrib); 00040 } 00041 return _off_attrib; 00042 } 00043 00044 //////////////////////////////////////////////////////////////////// 00045 // Function: ShaderAttrib::make 00046 // Access: Published, Static 00047 // Description: Constructs a new ShaderAttrib object with nothing 00048 // set. 00049 //////////////////////////////////////////////////////////////////// 00050 CPT(RenderAttrib) ShaderAttrib:: 00051 make() { 00052 static CPT(RenderAttrib) _null_attrib; 00053 if (_null_attrib == 0) { 00054 ShaderAttrib *attrib = new ShaderAttrib; 00055 _null_attrib = return_new(attrib); 00056 } 00057 return _null_attrib; 00058 } 00059 00060 //////////////////////////////////////////////////////////////////// 00061 // Function: ShaderAttrib::make_default 00062 // Access: Published, Static 00063 // Description: Returns a RenderAttrib that corresponds to whatever 00064 // the standard default properties for render attributes 00065 // of this type ought to be. 00066 //////////////////////////////////////////////////////////////////// 00067 CPT(RenderAttrib) ShaderAttrib:: 00068 make_default() { 00069 return return_new(new ShaderAttrib); 00070 } 00071 00072 //////////////////////////////////////////////////////////////////// 00073 // Function: ShaderAttrib::set_shader 00074 // Access: Published 00075 // Description: 00076 //////////////////////////////////////////////////////////////////// 00077 CPT(RenderAttrib) ShaderAttrib:: 00078 set_shader(const Shader *s, int priority) const { 00079 ShaderAttrib *result = new ShaderAttrib(*this); 00080 result->_shader = s; 00081 result->_shader_priority = priority; 00082 result->_auto_shader = false; 00083 result->_has_shader = true; 00084 return return_new(result); 00085 } 00086 00087 //////////////////////////////////////////////////////////////////// 00088 // Function: ShaderAttrib::set_shader_off 00089 // Access: Published 00090 // Description: 00091 //////////////////////////////////////////////////////////////////// 00092 CPT(RenderAttrib) ShaderAttrib:: 00093 set_shader_off(int priority) const { 00094 ShaderAttrib *result = new ShaderAttrib(*this); 00095 result->_shader = NULL; 00096 result->_shader_priority = priority; 00097 result->_auto_shader = false; 00098 result->_has_shader = true; 00099 return return_new(result); 00100 } 00101 00102 //////////////////////////////////////////////////////////////////// 00103 // Function: ShaderAttrib::set_shader_auto 00104 // Access: Published 00105 // Description: 00106 //////////////////////////////////////////////////////////////////// 00107 CPT(RenderAttrib) ShaderAttrib:: 00108 set_shader_auto(int priority) const { 00109 ShaderAttrib *result = new ShaderAttrib(*this); 00110 result->_shader = NULL; 00111 result->_shader_priority = priority; 00112 result->_auto_shader = true; 00113 result->_has_shader = true; 00114 return return_new(result); 00115 } 00116 00117 //////////////////////////////////////////////////////////////////// 00118 // Function: ShaderAttrib::clear_shader 00119 // Access: Published 00120 // Description: 00121 //////////////////////////////////////////////////////////////////// 00122 CPT(RenderAttrib) ShaderAttrib:: 00123 clear_shader() const { 00124 ShaderAttrib *result = new ShaderAttrib(*this); 00125 result->_shader = NULL; 00126 result->_shader_priority = 0; 00127 result->_auto_shader = false; 00128 result->_has_shader = false; 00129 return return_new(result); 00130 } 00131 00132 //////////////////////////////////////////////////////////////////// 00133 // Function: ShaderAttrib::set_flag 00134 // Access: Published 00135 // Description: 00136 //////////////////////////////////////////////////////////////////// 00137 CPT(RenderAttrib) ShaderAttrib:: 00138 set_flag(int flag, bool value) const { 00139 ShaderAttrib *result = new ShaderAttrib(*this); 00140 int bit = 1<<flag; 00141 if (value) { 00142 result->_flags |= bit; 00143 } else { 00144 result->_flags &= ~bit; 00145 } 00146 result->_has_flags |= bit; 00147 return return_new(result); 00148 } 00149 00150 //////////////////////////////////////////////////////////////////// 00151 // Function: ShaderAttrib::clear_flag 00152 // Access: Published 00153 // Description: 00154 //////////////////////////////////////////////////////////////////// 00155 CPT(RenderAttrib) ShaderAttrib:: 00156 clear_flag(int flag) const { 00157 ShaderAttrib *result = new ShaderAttrib(*this); 00158 int bit = 1<<flag; 00159 result->_flags &= ~bit; 00160 result->_has_flags &= ~bit; 00161 return return_new(result); 00162 } 00163 00164 //////////////////////////////////////////////////////////////////// 00165 // Function: ShaderAttrib::set_shader_input 00166 // Access: Published 00167 // Description: 00168 //////////////////////////////////////////////////////////////////// 00169 CPT(RenderAttrib) ShaderAttrib:: 00170 set_shader_input(const ShaderInput *input) const { 00171 ShaderAttrib *result = new ShaderAttrib(*this); 00172 Inputs::iterator i = result->_inputs.find(input->get_name()); 00173 if (i == result->_inputs.end()) { 00174 result->_inputs.insert(Inputs::value_type(input->get_name(),input)); 00175 } else { 00176 i->second = input; 00177 } 00178 return return_new(result); 00179 } 00180 00181 //////////////////////////////////////////////////////////////////// 00182 // Function: ShaderAttrib::set_shader_input 00183 // Access: Published 00184 // Description: 00185 //////////////////////////////////////////////////////////////////// 00186 CPT(RenderAttrib) ShaderAttrib:: 00187 set_shader_input(InternalName *id, Texture *tex, int priority) const { 00188 return set_shader_input(new ShaderInput(id, tex, priority)); 00189 } 00190 00191 //////////////////////////////////////////////////////////////////// 00192 // Function: ShaderAttrib::set_shader_input 00193 // Access: Published 00194 // Description: 00195 //////////////////////////////////////////////////////////////////// 00196 CPT(RenderAttrib) ShaderAttrib:: 00197 set_shader_input(InternalName *id, const NodePath &np, int priority) const { 00198 return set_shader_input(new ShaderInput(id, np, priority)); 00199 } 00200 00201 //////////////////////////////////////////////////////////////////// 00202 // Function: ShaderAttrib::set_shader_input 00203 // Access: Published 00204 // Description: 00205 //////////////////////////////////////////////////////////////////// 00206 CPT(RenderAttrib) ShaderAttrib:: 00207 set_shader_input(InternalName *id, const LVector4f &v, int priority) const { 00208 return set_shader_input(new ShaderInput(id, v, priority)); 00209 } 00210 00211 //////////////////////////////////////////////////////////////////// 00212 // Function: ShaderAttrib::set_shader_input 00213 // Access: Published 00214 // Description: 00215 //////////////////////////////////////////////////////////////////// 00216 CPT(RenderAttrib) ShaderAttrib:: 00217 set_shader_input(InternalName *id, double n1, double n2, double n3, double n4, int priority) const { 00218 return set_shader_input(new ShaderInput(id, LVector4f(n1,n2,n3,n4), priority)); 00219 } 00220 00221 //////////////////////////////////////////////////////////////////// 00222 // Function: ShaderAttrib::set_shader_input 00223 // Access: Published 00224 // Description: 00225 //////////////////////////////////////////////////////////////////// 00226 CPT(RenderAttrib) ShaderAttrib:: 00227 set_shader_input(const string &id, Texture *tex, int priority) const { 00228 return set_shader_input(new ShaderInput(InternalName::make(id), tex, priority)); 00229 } 00230 00231 //////////////////////////////////////////////////////////////////// 00232 // Function: ShaderAttrib::set_shader_input 00233 // Access: Published 00234 // Description: 00235 //////////////////////////////////////////////////////////////////// 00236 CPT(RenderAttrib) ShaderAttrib:: 00237 set_shader_input(const string &id, const NodePath &np, int priority) const { 00238 return set_shader_input(new ShaderInput(InternalName::make(id), np, priority)); 00239 } 00240 00241 //////////////////////////////////////////////////////////////////// 00242 // Function: ShaderAttrib::set_shader_input 00243 // Access: Published 00244 // Description: 00245 //////////////////////////////////////////////////////////////////// 00246 CPT(RenderAttrib) ShaderAttrib:: 00247 set_shader_input(const string &id, const LVector4f &v, int priority) const { 00248 return set_shader_input(new ShaderInput(InternalName::make(id), v, priority)); 00249 } 00250 00251 //////////////////////////////////////////////////////////////////// 00252 // Function: ShaderAttrib::set_shader_input 00253 // Access: Published 00254 // Description: 00255 //////////////////////////////////////////////////////////////////// 00256 CPT(RenderAttrib) ShaderAttrib:: 00257 set_shader_input(const string &id, double n1, double n2, double n3, double n4, int priority) const { 00258 return set_shader_input(new ShaderInput(InternalName::make(id), LVector4f(n1,n2,n3,n4), priority)); 00259 } 00260 00261 //////////////////////////////////////////////////////////////////// 00262 // Function: ShaderAttrib::set_instance_count 00263 // Access: Published 00264 // Description: Sets the geometry instance count. Do not confuse 00265 // this with instanceTo, which is used for animation 00266 // instancing, and has nothing to do with this. 00267 // A value of 0 means not to use instancing at all. 00268 //////////////////////////////////////////////////////////////////// 00269 CPT(RenderAttrib) ShaderAttrib:: 00270 set_instance_count(int instance_count) const { 00271 ShaderAttrib *result = new ShaderAttrib(*this); 00272 result->_instance_count = instance_count; 00273 return return_new(result); 00274 } 00275 00276 //////////////////////////////////////////////////////////////////// 00277 // Function: ShaderAttrib::clear_shader_input 00278 // Access: Published 00279 // Description: 00280 //////////////////////////////////////////////////////////////////// 00281 CPT(RenderAttrib) ShaderAttrib:: 00282 clear_shader_input(InternalName *id) const { 00283 ShaderAttrib *result = new ShaderAttrib(*this); 00284 result->_inputs.erase(id); 00285 return return_new(result); 00286 } 00287 00288 //////////////////////////////////////////////////////////////////// 00289 // Function: ShaderAttrib::clear_shader_input 00290 // Access: Published 00291 // Description: 00292 //////////////////////////////////////////////////////////////////// 00293 CPT(RenderAttrib) ShaderAttrib:: 00294 clear_shader_input(const string &id) const { 00295 return clear_shader_input(InternalName::make(id)); 00296 } 00297 00298 //////////////////////////////////////////////////////////////////// 00299 // Function: ShaderAttrib::clear_all_shader_inputs 00300 // Access: Published 00301 // Description: Clears all the shader inputs on the attrib. 00302 //////////////////////////////////////////////////////////////////// 00303 CPT(RenderAttrib) ShaderAttrib:: 00304 clear_all_shader_inputs() const { 00305 ShaderAttrib *result = new ShaderAttrib(*this); 00306 result->_inputs.clear(); 00307 return return_new(result); 00308 } 00309 00310 //////////////////////////////////////////////////////////////////// 00311 // Function: ShaderAttrib::get_shader_input 00312 // Access: Published 00313 // Description: Returns the ShaderInput of the given name. If 00314 // no such name is found, this function does not return 00315 // NULL --- it returns the "blank" ShaderInput. 00316 //////////////////////////////////////////////////////////////////// 00317 const ShaderInput *ShaderAttrib:: 00318 get_shader_input(InternalName *id) const { 00319 Inputs::const_iterator i = _inputs.find(id); 00320 if (i == _inputs.end()) { 00321 return ShaderInput::get_blank(); 00322 } else { 00323 return (*i).second; 00324 } 00325 } 00326 00327 //////////////////////////////////////////////////////////////////// 00328 // Function: ShaderAttrib::get_shader_input 00329 // Access: Published 00330 // Description: Returns the ShaderInput of the given name. If 00331 // no such name is found, this function does not return 00332 // NULL --- it returns the "blank" ShaderInput. 00333 //////////////////////////////////////////////////////////////////// 00334 const ShaderInput *ShaderAttrib:: 00335 get_shader_input(const string &id) const { 00336 return get_shader_input(InternalName::make(id)); 00337 } 00338 00339 //////////////////////////////////////////////////////////////////// 00340 // Function: ShaderAttrib::get_shader_input_nodepath 00341 // Access: Published 00342 // Description: Returns the ShaderInput as a nodepath. Assertion 00343 // fails if there is none, or if it is not a nodepath. 00344 //////////////////////////////////////////////////////////////////// 00345 const NodePath &ShaderAttrib:: 00346 get_shader_input_nodepath(InternalName *id) const { 00347 static NodePath resfail; 00348 Inputs::const_iterator i = _inputs.find(id); 00349 if (i == _inputs.end()) { 00350 ostringstream strm; 00351 strm << "Shader input " << id->get_name() << " is not present.\n"; 00352 nassert_raise(strm.str()); 00353 return resfail; 00354 } else { 00355 const ShaderInput *p = (*i).second; 00356 if (p->get_value_type() != ShaderInput::M_nodepath) { 00357 ostringstream strm; 00358 strm << "Shader input " << id->get_name() << " is not a nodepath.\n"; 00359 nassert_raise(strm.str()); 00360 return resfail; 00361 } 00362 return p->get_nodepath(); 00363 } 00364 00365 // Satisfy compiler. 00366 return resfail; 00367 } 00368 00369 //////////////////////////////////////////////////////////////////// 00370 // Function: ShaderAttrib::get_shader_input_vector 00371 // Access: Published 00372 // Description: Returns the ShaderInput as a vector. Assertion 00373 // fails if there is none, or if it is not a vector. 00374 //////////////////////////////////////////////////////////////////// 00375 const LVector4f &ShaderAttrib:: 00376 get_shader_input_vector(InternalName *id) const { 00377 static LVector4f resfail(0,0,0,0); 00378 Inputs::const_iterator i = _inputs.find(id); 00379 if (i == _inputs.end()) { 00380 ostringstream strm; 00381 strm << "Shader input " << id->get_name() << " is not present.\n"; 00382 nassert_raise(strm.str()); 00383 return resfail; 00384 } else { 00385 const ShaderInput *p = (*i).second; 00386 if (p->get_value_type() != ShaderInput::M_vector) { 00387 ostringstream strm; 00388 strm << "Shader input " << id->get_name() << " is not a vector.\n"; 00389 nassert_raise(strm.str()); 00390 return resfail; 00391 } 00392 return p->get_vector(); 00393 } 00394 } 00395 00396 //////////////////////////////////////////////////////////////////// 00397 // Function: ShaderAttrib::get_shader_input_texture 00398 // Access: Published 00399 // Description: Returns the ShaderInput as a texture. Assertion 00400 // fails if there is none, or if it is not a texture. 00401 //////////////////////////////////////////////////////////////////// 00402 Texture *ShaderAttrib:: 00403 get_shader_input_texture(InternalName *id) const { 00404 Inputs::const_iterator i = _inputs.find(id); 00405 if (i == _inputs.end()) { 00406 ostringstream strm; 00407 strm << "Shader input " << id->get_name() << " is not present.\n"; 00408 nassert_raise(strm.str()); 00409 return NULL; 00410 } else { 00411 const ShaderInput *p = (*i).second; 00412 if (p->get_value_type() != ShaderInput::M_texture) { 00413 ostringstream strm; 00414 strm << "Shader input " << id->get_name() << " is not a texture.\n"; 00415 nassert_raise(strm.str()); 00416 return NULL; 00417 } 00418 return p->get_texture(); 00419 } 00420 } 00421 00422 //////////////////////////////////////////////////////////////////// 00423 // Function: ShaderAttrib::get_shader 00424 // Access: Published 00425 // Description: Returns the shader object associated with the node. 00426 // If get_override returns true, but get_shader 00427 // returns NULL, that means that this attribute should 00428 // disable the shader. 00429 //////////////////////////////////////////////////////////////////// 00430 const Shader *ShaderAttrib:: 00431 get_shader() const { 00432 return _shader; 00433 } 00434 00435 //////////////////////////////////////////////////////////////////// 00436 // Function: ShaderAttrib::compare_to_impl 00437 // Access: Protected, Virtual 00438 // Description: Intended to be overridden by derived ShaderAttrib 00439 // types to return a unique number indicating whether 00440 // this ShaderAttrib is equivalent to the other one. 00441 // 00442 // This should return 0 if the two ShaderAttrib objects 00443 // are equivalent, a number less than zero if this one 00444 // should be sorted before the other one, and a number 00445 // greater than zero otherwise. 00446 // 00447 // This will only be called with two ShaderAttrib 00448 // objects whose get_type() functions return the same. 00449 //////////////////////////////////////////////////////////////////// 00450 int ShaderAttrib:: 00451 compare_to_impl(const RenderAttrib *other) const { 00452 const ShaderAttrib *that; 00453 DCAST_INTO_R(that, other, 0); 00454 00455 if (this->_shader != that->_shader) { 00456 return (this->_shader < that->_shader) ? -1 : 1; 00457 } 00458 if (this->_shader_priority != that->_shader_priority) { 00459 return (this->_shader_priority < that->_shader_priority) ? -1 : 1; 00460 } 00461 if (this->_auto_shader != that->_auto_shader) { 00462 return (this->_auto_shader < that->_auto_shader) ? -1 : 1; 00463 } 00464 if (this->_has_shader != that->_has_shader) { 00465 return (this->_has_shader < that->_has_shader) ? -1 : 1; 00466 } 00467 if (this->_flags != that->_flags) { 00468 return (this->_flags < that->_flags) ? -1 : 1; 00469 } 00470 if (this->_has_flags != that->_has_flags) { 00471 return (this->_has_flags < that->_has_flags) ? -1 : 1; 00472 } 00473 if (this->_instance_count != that->_instance_count) { 00474 return (this->_instance_count < that->_instance_count) ? -1 : 1; 00475 } 00476 00477 Inputs::const_iterator i1 = this->_inputs.begin(); 00478 Inputs::const_iterator i2 = that->_inputs.begin(); 00479 while ((i1 != this->_inputs.end()) && (i2 != that->_inputs.end())) { 00480 if (i1->second != i2->second) { 00481 return (i1->second < i2->second) ? -1 : 1; 00482 } 00483 ++i1; 00484 ++i2; 00485 } 00486 if (i1 != this->_inputs.end()) { 00487 return 1; 00488 } 00489 if (i2 != that->_inputs.end()) { 00490 return -1; 00491 } 00492 00493 return 0; 00494 } 00495 00496 //////////////////////////////////////////////////////////////////// 00497 // Function: ShaderAttrib::compose_impl 00498 // Access: Public, Virtual 00499 // Description: 00500 //////////////////////////////////////////////////////////////////// 00501 CPT(RenderAttrib) ShaderAttrib:: 00502 compose_impl(const RenderAttrib *other) const { 00503 ShaderAttrib *attr = new ShaderAttrib(*this); 00504 const ShaderAttrib *over; 00505 DCAST_INTO_R(over, other, 0); 00506 // Update the shader portion. 00507 if (over->_has_shader) { 00508 if ((attr->_has_shader == false) || 00509 (over->_shader_priority >= attr->_shader_priority)) { 00510 attr->_shader = over->_shader; 00511 attr->_shader_priority = over->_shader_priority; 00512 attr->_auto_shader = over->_auto_shader; 00513 attr->_has_shader = over->_has_shader; 00514 } 00515 } 00516 // Update the shader-data portion. 00517 Inputs::const_iterator iover; 00518 for (iover=over->_inputs.begin(); iover!=over->_inputs.end(); ++iover) { 00519 const InternalName *id = (*iover).first; 00520 const ShaderInput *dover = (*iover).second; 00521 Inputs::iterator iattr = attr->_inputs.find(id); 00522 if (iattr == attr->_inputs.end()) { 00523 attr->_inputs.insert(Inputs::value_type(id,dover)); 00524 } else { 00525 const ShaderInput *dattr = (*iattr).second; 00526 if (dattr->get_priority() <= dover->get_priority()) { 00527 iattr->second = iover->second; 00528 } 00529 } 00530 } 00531 // Just copy the instance count. 00532 attr->_instance_count = over->_instance_count; 00533 // Update the flags. 00534 attr->_flags &= ~(over->_has_flags); 00535 attr->_flags |= over->_flags; 00536 attr->_has_flags |= (over->_has_flags); 00537 return return_new(attr); 00538 } 00539 00540 //////////////////////////////////////////////////////////////////// 00541 // Function: ShaderAttrib::register_with_read_factory 00542 // Access: Public, Static 00543 // Description: Factory method to generate a Shader object 00544 //////////////////////////////////////////////////////////////////// 00545 void ShaderAttrib:: 00546 register_with_read_factory() { 00547 // IMPLEMENT ME 00548 } 00549