Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/shader/shaderTransition.cxx

Go to the documentation of this file.
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 

Generated on Fri May 2 00:44:03 2003 for Panda by doxygen1.3