00001 // Filename: shaderTransition.cxx 00002 // Created by: mike (06Feb99) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "shaderTransition.h" 00020 00021 #include <indent.h> 00022 #include <graphicsStateGuardian.h> 00023 #include <textureTransition.h> 00024 #include <attribTraverser.h> 00025 #include <directRenderTraverser.h> 00026 #include <renderRelation.h> 00027 00028 #include "config_shader.h" 00029 00030 TypeHandle ShaderTransition::_type_handle; 00031 ShaderTransition::ShaderOrder* ShaderTransition::_shader_order = (ShaderTransition::ShaderOrder *)NULL; 00032 ShaderTransition::ShaderBlend* ShaderTransition::_shader_always_blend = (ShaderTransition::ShaderBlend *)NULL; 00033 00034 //////////////////////////////////////////////////////////////////// 00035 // Function: ShaderTransition::make_copy 00036 // Access: Public, Virtual 00037 // Description: Returns a newly allocated ShaderTransition just like 00038 // this one. 00039 //////////////////////////////////////////////////////////////////// 00040 NodeTransition *ShaderTransition:: 00041 make_copy() const { 00042 return new ShaderTransition(*this); 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: ShaderTransition::set_shader_order 00047 // Access: Public, Static 00048 // Description: Stores the order "priority" of a shader. (Note, there 00049 // is nothing to prevent you from adding a none shader 00050 // handle type, but it won't really do you any good). 00051 // This order value is used to make sure that multiple 00052 // shaders are ordered in a defined, hopefully 00053 // intelligent order. 00054 //////////////////////////////////////////////////////////////////// 00055 void ShaderTransition:: 00056 set_shader_order(TypeHandle shader, int order) { 00057 if (_shader_order == (ShaderOrder *)NULL) 00058 { 00059 _shader_order = new ShaderOrder; 00060 } 00061 (*_shader_order)[shader] = order; 00062 } 00063 00064 //////////////////////////////////////////////////////////////////// 00065 // Function: ShaderTransition::set_shader_blend 00066 // Access: Public, Static 00067 // Description: Some shaders (i.e. spotlight and highlight) need to 00068 // blend with the scene no matter what. 00069 //////////////////////////////////////////////////////////////////// 00070 void ShaderTransition:: 00071 set_shader_always_blend(TypeHandle shader) { 00072 if (_shader_always_blend == (ShaderBlend *)NULL) 00073 { 00074 _shader_always_blend = new ShaderBlend; 00075 } 00076 _shader_always_blend->insert(shader); 00077 } 00078 00079 00080 //////////////////////////////////////////////////////////////////// 00081 // Function: ShaderTransition::clear 00082 // Access: Public 00083 // Description: 00084 //////////////////////////////////////////////////////////////////// 00085 void ShaderTransition:: 00086 clear() { 00087 _shaders.clear(); 00088 } 00089 00090 //////////////////////////////////////////////////////////////////// 00091 // Function: ShaderTransition::is_empty 00092 // Access: Public 00093 // Description: 00094 //////////////////////////////////////////////////////////////////// 00095 bool ShaderTransition:: 00096 is_empty() const { 00097 return _shaders.empty(); 00098 } 00099 00100 //////////////////////////////////////////////////////////////////// 00101 // Function: ShaderTransition::insert 00102 // Access: Public 00103 // Description: Inserts the shader into the list, based 00104 // on the set order of the list. If there is no order set for 00105 // the shader, it is put at the end of the list. 00106 //////////////////////////////////////////////////////////////////// 00107 void ShaderTransition:: 00108 insert(Shader *shader) { 00109 PT(Shader) sp(shader); 00110 Shaders::iterator si = _shaders.begin(); 00111 int order = -1; 00112 00113 if ((_shader_order == NULL) && (_overrides.find(sp) == _overrides.end())) 00114 { 00115 si = _shaders.end(); 00116 } 00117 00118 if (_overrides.find(sp) != _overrides.end()) 00119 { 00120 order = _overrides[sp]; 00121 } 00122 else if (_shader_order->find(sp->get_type()) != _shader_order->end()) 00123 { 00124 order = (*_shader_order)[sp->get_type()]; 00125 } 00126 00127 if (order == -1) 00128 { 00129 si = _shaders.end(); 00130 } 00131 00132 while(si != _shaders.end()) 00133 { 00134 if (_overrides.find((*si)) != _overrides.end()) 00135 { 00136 if (order < _overrides[(*si)]) 00137 { 00138 break; 00139 } 00140 } 00141 else if (order < (*_shader_order)[(*si)->get_type()]) 00142 { 00143 break; 00144 } 00145 si++; 00146 } 00147 00148 _shaders.insert(si, shader); 00149 } 00150 00151 //////////////////////////////////////////////////////////////////// 00152 // Function: ShaderTransition::set_shader 00153 // Access: Public 00154 // Description: Adds the shader to the transition, if it is not 00155 // already there. Returns true if the shader was added, 00156 // false if it was there already. If the shader *was* 00157 // already on the list, it is moved to the end of the 00158 // list. 00159 //////////////////////////////////////////////////////////////////// 00160 bool ShaderTransition:: 00161 set_shader(Shader *shader, int override) { 00162 // We need to search for a PT(Shader), not a Shader* . 00163 PT(Shader) sp(shader); 00164 00165 if (override != -1) 00166 { 00167 _overrides[sp] = override; 00168 } 00169 00170 Shaders::iterator si = find(_shaders.begin(), _shaders.end(), sp); 00171 if (si != _shaders.end()) { 00172 // The shader was there already; move it to the end. 00173 return false; 00174 } 00175 insert(shader); 00176 return true; 00177 } 00178 00179 //////////////////////////////////////////////////////////////////// 00180 // Function: ShaderTransition::clear_shader 00181 // Access: Public 00182 // Description: Removes the first occurrence of the indicated shader 00183 // from the list, and returns true if anything was 00184 // removed, false if there were no occurrences. 00185 //////////////////////////////////////////////////////////////////// 00186 bool ShaderTransition:: 00187 clear_shader(Shader *shader) { 00188 // We need to search for a PT(Shader), not a Shader* . 00189 PT(Shader) sp(shader); 00190 Shaders::iterator si = find(_shaders.begin(), _shaders.end(), sp); 00191 if (si != _shaders.end()) { 00192 _shaders.erase(si); 00193 return true; 00194 } 00195 return false; 00196 } 00197 00198 //////////////////////////////////////////////////////////////////// 00199 // Function: ShaderTransition::has_shader 00200 // Access: Public 00201 // Description: Returns true if the indicated shader appears on the 00202 // list, false otherwise. 00203 //////////////////////////////////////////////////////////////////// 00204 bool ShaderTransition:: 00205 has_shader(Shader *shader) const { 00206 // We need to search for a PT(Shader), not a Shader* . 00207 PT(Shader) sp(shader); 00208 Shaders::const_iterator si = find(_shaders.begin(), _shaders.end(), sp); 00209 return (si != _shaders.end()); 00210 } 00211 00212 //////////////////////////////////////////////////////////////////// 00213 // Function: ShaderTransition::begin 00214 // Access: Public 00215 // Description: 00216 //////////////////////////////////////////////////////////////////// 00217 ShaderTransition::const_iterator ShaderTransition:: 00218 begin() const { 00219 return _shaders.begin(); 00220 } 00221 00222 //////////////////////////////////////////////////////////////////// 00223 // Function: ShaderTransition::end 00224 // Access: Public 00225 // Description: 00226 //////////////////////////////////////////////////////////////////// 00227 ShaderTransition::const_iterator ShaderTransition:: 00228 end() const { 00229 return _shaders.end(); 00230 } 00231 00232 //////////////////////////////////////////////////////////////////// 00233 // Function: ShaderTransition::must_blend 00234 // Access: Public 00235 // Description: Checks to see if one of the shaders on the shaderTransition 00236 // is a kind that requires blending 00237 //////////////////////////////////////////////////////////////////// 00238 bool ShaderTransition:: 00239 must_blend() 00240 { 00241 const_iterator si; 00242 for(si = begin(); si != end(); si++) 00243 { 00244 if (_shader_always_blend->find((*si)->get_type()) != _shader_always_blend->end()) 00245 { 00246 return true; 00247 } 00248 } 00249 00250 return false; 00251 } 00252 00253 //////////////////////////////////////////////////////////////////// 00254 // Function: ShaderTransition::sub_render 00255 // Access: Public, Virtual 00256 // Description: This is called by the RenderTraverser to tell the 00257 // shader to do its thing. 00258 //////////////////////////////////////////////////////////////////// 00259 bool ShaderTransition:: 00260 sub_render(NodeRelation *arc, const AllAttributesWrapper &attrib, 00261 AllTransitionsWrapper &trans, RenderTraverser *trav) { 00262 Node *node = arc->get_child(); 00263 GraphicsStateGuardian *gsg = trav->get_gsg(); 00264 bool multipass_on = false; 00265 00266 // No shaders; never mind. 00267 if (is_empty()) { 00268 return true; 00269 } 00270 00271 AllAttributesWrapper node_attrib; 00272 node_attrib.apply_from(attrib, trans); 00273 00274 multipass_on = must_blend() | is_textured(node, node_attrib) | 00275 is_shaded(node) | (_shaders.size() > 1); 00276 00277 const_iterator si; 00278 // In order to avoid strange nasty looking artifacts due to(?) the 00279 // depth buffer not being restored properly when we employ scratch 00280 // display regions. Call pre-apply before the scene has been 00281 // rendered. Any shader that uses a scratch region will do it's 00282 // thing and then when the scene is actually rendered, it will blow 00283 // those artifacts away. Those shaders will store their work to be 00284 // actually applied later when we call apply. 00285 for (si = begin(); si != end(); ++si) 00286 { 00287 // We'll go ahead and tell each shader in turn if multipass is 00288 // needed or not now. 00289 (*si)->set_multipass(multipass_on); 00290 (*si)->pre_apply(node, node_attrib, AllTransitionsWrapper(), gsg); 00291 } 00292 00293 if ( multipass_on ) 00294 { 00295 // Multipass is needed at this point. Render the node with its normal 00296 // attributes (including texturing). 00297 DirectRenderTraverser drt(gsg, RenderRelation::get_class_type()); 00298 gsg->render_subgraph(&drt, node, node_attrib, AllTransitionsWrapper()); 00299 } 00300 00301 // Now apply each shader in turn. 00302 for (si = begin(); si != end(); ++si) 00303 { 00304 (*si)->apply(node, node_attrib, AllTransitionsWrapper(), gsg); 00305 } 00306 00307 return false; 00308 } 00309 00310 //////////////////////////////////////////////////////////////////// 00311 // Function: ShaderTransition::has_sub_render 00312 // Access: Public, Virtual 00313 // Description: Should be redefined to return true if the function 00314 // sub_render(), above, expects to be called during 00315 // traversal. 00316 //////////////////////////////////////////////////////////////////// 00317 bool ShaderTransition:: 00318 has_sub_render() const { 00319 return true; 00320 } 00321 00322 00323