Browse Source

Add RenderState::get_auto_shader_state()

David Rose 14 years ago
parent
commit
2a3ad0d4e5
36 changed files with 347 additions and 10 deletions
  1. 4 3
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  2. 10 0
      panda/src/pgraph/alphaTestAttrib.cxx
  3. 1 0
      panda/src/pgraph/alphaTestAttrib.h
  4. 10 0
      panda/src/pgraph/auxBitplaneAttrib.cxx
  5. 1 0
      panda/src/pgraph/auxBitplaneAttrib.h
  6. 10 0
      panda/src/pgraph/clipPlaneAttrib.cxx
  7. 1 0
      panda/src/pgraph/clipPlaneAttrib.h
  8. 15 0
      panda/src/pgraph/colorAttrib.cxx
  9. 1 0
      panda/src/pgraph/colorAttrib.h
  10. 10 0
      panda/src/pgraph/colorBlendAttrib.cxx
  11. 1 0
      panda/src/pgraph/colorBlendAttrib.h
  12. 14 0
      panda/src/pgraph/colorScaleAttrib.cxx
  13. 1 0
      panda/src/pgraph/colorScaleAttrib.h
  14. 10 0
      panda/src/pgraph/fogAttrib.cxx
  15. 1 0
      panda/src/pgraph/fogAttrib.h
  16. 10 0
      panda/src/pgraph/lightAttrib.cxx
  17. 1 0
      panda/src/pgraph/lightAttrib.h
  18. 10 0
      panda/src/pgraph/lightRampAttrib.cxx
  19. 1 0
      panda/src/pgraph/lightRampAttrib.h
  20. 10 0
      panda/src/pgraph/materialAttrib.cxx
  21. 1 0
      panda/src/pgraph/materialAttrib.h
  22. 25 0
      panda/src/pgraph/renderAttrib.I
  23. 10 0
      panda/src/pgraph/renderAttrib.cxx
  24. 3 0
      panda/src/pgraph/renderAttrib.h
  25. 95 2
      panda/src/pgraph/renderState.cxx
  26. 11 5
      panda/src/pgraph/renderState.h
  27. 21 0
      panda/src/pgraph/shaderAttrib.cxx
  28. 1 0
      panda/src/pgraph/shaderAttrib.h
  29. 10 0
      panda/src/pgraph/texGenAttrib.cxx
  30. 1 0
      panda/src/pgraph/texGenAttrib.h
  31. 24 0
      panda/src/pgraph/texMatrixAttrib.cxx
  32. 1 0
      panda/src/pgraph/texMatrixAttrib.h
  33. 10 0
      panda/src/pgraph/textureAttrib.cxx
  34. 1 0
      panda/src/pgraph/textureAttrib.h
  35. 10 0
      panda/src/pgraph/transparencyAttrib.cxx
  36. 1 0
      panda/src/pgraph/transparencyAttrib.h

+ 4 - 3
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -7141,13 +7141,14 @@ set_state_and_transform(const RenderState *target,
 #ifndef OPENGLES_1
 #ifndef OPENGLES_1
   if (_target_shader->auto_shader()) {
   if (_target_shader->auto_shader()) {
     // If we don't have a generated shader, make sure we have a ShaderGenerator, then generate the shader.
     // If we don't have a generated shader, make sure we have a ShaderGenerator, then generate the shader.
-    if (_target_rs->_generated_shader == NULL) {
+    CPT(RenderState) shader = _target_rs->get_auto_shader_state();
+    if (shader->_generated_shader == NULL) {
       if (_shader_generator == NULL) {
       if (_shader_generator == NULL) {
         _shader_generator = new ShaderGenerator(this, _scene_setup->get_display_region()->get_window());
         _shader_generator = new ShaderGenerator(this, _scene_setup->get_display_region()->get_window());
       }
       }
-      const_cast<RenderState*>(_target_rs.p())->_generated_shader = DCAST(ShaderAttrib, _shader_generator->synthesize_shader(_target_rs));
+      const_cast<RenderState*>(shader.p())->_generated_shader = DCAST(ShaderAttrib, _shader_generator->synthesize_shader(shader));
     }
     }
-    _target_shader = DCAST(ShaderAttrib, _target_rs->_generated_shader);
+    _target_shader = DCAST(ShaderAttrib, shader->_generated_shader);
   }
   }
 #endif
 #endif
 
 

+ 10 - 0
panda/src/pgraph/alphaTestAttrib.cxx

@@ -108,6 +108,16 @@ get_hash_impl() const {
   return hash;
   return hash;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AlphaTestAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AlphaTestAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AlphaTestAttrib::register_with_read_factory
 //     Function: AlphaTestAttrib::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 1 - 0
panda/src/pgraph/alphaTestAttrib.h

@@ -44,6 +44,7 @@ public:
 protected:
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   PandaCompareFunc _mode;
   PandaCompareFunc _mode;

+ 10 - 0
panda/src/pgraph/auxBitplaneAttrib.cxx

@@ -114,6 +114,16 @@ get_hash_impl() const {
   return hash;
   return hash;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AuxBitplaneAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AuxBitplaneAttrib::register_with_read_factory
 //     Function: AuxBitplaneAttrib::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 1 - 0
panda/src/pgraph/auxBitplaneAttrib.h

@@ -77,6 +77,7 @@ public:
 protected:
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
   
   
 private:
 private:
   int _outputs;
   int _outputs;

+ 10 - 0
panda/src/pgraph/clipPlaneAttrib.cxx

@@ -908,6 +908,16 @@ invert_compose_impl(const RenderAttrib *other) const {
   return other;
   return other;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ClipPlaneAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ClipPlaneAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ClipPlaneAttrib::sort_on_planes
 //     Function: ClipPlaneAttrib::sort_on_planes
 //       Access: Private
 //       Access: Private

+ 1 - 0
panda/src/pgraph/clipPlaneAttrib.h

@@ -103,6 +103,7 @@ protected:
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   INLINE void check_filtered() const;
   INLINE void check_filtered() const;

+ 15 - 0
panda/src/pgraph/colorAttrib.cxx

@@ -153,6 +153,21 @@ get_hash_impl() const {
   return hash;
   return hash;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ColorAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ColorAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  // For a ColorAttrib, the only relevant information is the type: is
+  // it flat-shaded or vertex-shaded?  The actual color value is read
+  // by the shader from the graphics state.
+
+  ColorAttrib *attrib = new ColorAttrib(_type, LColor(1.0f, 1.0f, 1.0f, 1.0f));
+  return return_new(attrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorAttrib::quantize_color
 //     Function: ColorAttrib::quantize_color
 //       Access: Private
 //       Access: Private

+ 1 - 0
panda/src/pgraph/colorAttrib.h

@@ -51,6 +51,7 @@ public:
 protected:
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   void quantize_color();
   void quantize_color();

+ 10 - 0
panda/src/pgraph/colorBlendAttrib.cxx

@@ -152,6 +152,16 @@ get_hash_impl() const {
   return hash;
   return hash;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ColorBlendAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ColorBlendAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorBlendAttrib::register_with_read_factory
 //     Function: ColorBlendAttrib::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 1 - 0
panda/src/pgraph/colorBlendAttrib.h

@@ -96,6 +96,7 @@ public:
 protected:
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   Mode _mode;
   Mode _mode;

+ 14 - 0
panda/src/pgraph/colorScaleAttrib.cxx

@@ -274,6 +274,20 @@ invert_compose_impl(const RenderAttrib *other) const {
   return return_new(attrib);
   return return_new(attrib);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ColorScaleAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ColorScaleAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  // A ColorScaleAttrib doesn't directly contribute to the auto-shader
+  // contents--instead, the shader is always written to query
+  // attr_colorscale at runtime.  So the attrib itself means nothing
+  // to the shader.
+  return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorScaleAttrib::quantize_scale
 //     Function: ColorScaleAttrib::quantize_scale
 //       Access: Private
 //       Access: Private

+ 1 - 0
panda/src/pgraph/colorScaleAttrib.h

@@ -55,6 +55,7 @@ protected:
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   void quantize_scale();
   void quantize_scale();

+ 10 - 0
panda/src/pgraph/fogAttrib.cxx

@@ -120,6 +120,16 @@ get_hash_impl() const {
   return hash;
   return hash;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: FogAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) FogAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: FogAttrib::register_with_read_factory
 //     Function: FogAttrib::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 1 - 0
panda/src/pgraph/fogAttrib.h

@@ -42,6 +42,7 @@ public:
 protected:
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   PT(Fog) _fog;
   PT(Fog) _fog;

+ 10 - 0
panda/src/pgraph/lightAttrib.cxx

@@ -940,6 +940,16 @@ invert_compose_impl(const RenderAttrib *other) const {
   return other;
   return other;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: LightAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) LightAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: LightAttrib::sort_on_lights
 //     Function: LightAttrib::sort_on_lights
 //       Access: Private
 //       Access: Private

+ 1 - 0
panda/src/pgraph/lightAttrib.h

@@ -102,6 +102,7 @@ protected:
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   INLINE void check_filtered() const;
   INLINE void check_filtered() const;

+ 10 - 0
panda/src/pgraph/lightRampAttrib.cxx

@@ -282,6 +282,16 @@ get_hash_impl() const {
   return hash;
   return hash;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: LightRampAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) LightRampAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: LightRampAttrib::register_with_read_factory
 //     Function: LightRampAttrib::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 1 - 0
panda/src/pgraph/lightRampAttrib.h

@@ -62,6 +62,7 @@ public:
 protected:
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
   
   
 private:
 private:
   LightRampMode _mode;
   LightRampMode _mode;

+ 10 - 0
panda/src/pgraph/materialAttrib.cxx

@@ -121,6 +121,16 @@ get_hash_impl() const {
   return hash;
   return hash;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: MaterialAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) MaterialAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MaterialAttrib::register_with_read_factory
 //     Function: MaterialAttrib::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 1 - 0
panda/src/pgraph/materialAttrib.h

@@ -45,6 +45,7 @@ public:
 protected:
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   PT(Material) _material;
   PT(Material) _material;

+ 25 - 0
panda/src/pgraph/renderAttrib.I

@@ -118,6 +118,31 @@ get_unique() const {
   return return_unique((RenderAttrib *)this);
   return return_unique((RenderAttrib *)this);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttrib::get_auto_shader_attrib
+//       Access: Published
+//  Description: Returns the variant of this RenderAttrib that's most
+//               relevant for associating with an auto-generated
+//               shader.  This should be a new RenderAttrib of the
+//               same type as this one, with any superfluous data set
+//               to neutral.  Only the parts of the attrib that
+//               contribute to the shader should be reflected in the
+//               returned attrib.  The idea is to associate the
+//               auto-generated shader with the most neutral form of
+//               all states, to allow it to be shared across as many
+//               RenderState objects as possible.
+//
+//               If this RenderAttrib is completely irrelevant to the
+//               auto-shader, this should return NULL to indicate that
+//               the attrib won't be assocaited with the shader at
+//               all.  In this case the attrib does not contribute to
+//               the shader meaningfully.
+////////////////////////////////////////////////////////////////////
+INLINE CPT(RenderAttrib) RenderAttrib::
+get_auto_shader_attrib(const RenderState *state) const {
+  return get_auto_shader_attrib_impl(state);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderAttrib::register_slot
 //     Function: RenderAttrib::register_slot
 //       Access: Public, Static
 //       Access: Public, Static

+ 10 - 0
panda/src/pgraph/renderAttrib.cxx

@@ -140,6 +140,16 @@ cull_callback(CullTraverser *, const CullTraverserData &) const {
   return true;
   return true;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: RenderAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) RenderAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderAttrib::unref
 //     Function: RenderAttrib::unref
 //       Access: Published, Virtual
 //       Access: Published, Virtual

+ 3 - 0
panda/src/pgraph/renderAttrib.h

@@ -28,6 +28,7 @@ class AttribSlots;
 class GraphicsStateGuardianBase;
 class GraphicsStateGuardianBase;
 class CullTraverser;
 class CullTraverser;
 class CullTraverserData;
 class CullTraverserData;
+class RenderState;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : RenderAttrib
 //       Class : RenderAttrib
@@ -81,6 +82,7 @@ PUBLISHED:
   INLINE int compare_to(const RenderAttrib &other) const;
   INLINE int compare_to(const RenderAttrib &other) const;
   INLINE size_t get_hash() const;
   INLINE size_t get_hash() const;
   INLINE CPT(RenderAttrib) get_unique() const;
   INLINE CPT(RenderAttrib) get_unique() const;
+  INLINE CPT(RenderAttrib) get_auto_shader_attrib(const RenderState *state) const;
 
 
   virtual bool unref() const;
   virtual bool unref() const;
 
 
@@ -185,6 +187,7 @@ protected:
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
   void output_comparefunc(ostream &out, PandaCompareFunc fn) const;
   void output_comparefunc(ostream &out, PandaCompareFunc fn) const;
 
 
 public:
 public:

+ 95 - 2
panda/src/pgraph/renderState.cxx

@@ -69,6 +69,7 @@ TypeHandle RenderState::_type_handle;
 RenderState::
 RenderState::
 RenderState() : 
 RenderState() : 
   _flags(0),
   _flags(0),
+  _auto_shader_state(NULL),
   _lock("RenderState")
   _lock("RenderState")
 {
 {
   // Allocate the _attributes array.
   // Allocate the _attributes array.
@@ -99,6 +100,7 @@ RenderState::
 RenderState(const RenderState &copy) :
 RenderState(const RenderState &copy) :
   _filled_slots(copy._filled_slots),
   _filled_slots(copy._filled_slots),
   _flags(0),
   _flags(0),
+  _auto_shader_state(NULL),
   _lock("RenderState")
   _lock("RenderState")
 {
 {
   // Allocate the _attributes array.
   // Allocate the _attributes array.
@@ -145,6 +147,14 @@ RenderState::
   nassertv(_saved_entry == -1);
   nassertv(_saved_entry == -1);
   nassertv(_composition_cache.is_empty() && _invert_composition_cache.is_empty());
   nassertv(_composition_cache.is_empty() && _invert_composition_cache.is_empty());
 
 
+  // Make sure the _auto_shader_state cache pointer is cleared.
+  if (_auto_shader_state != (const RenderState *)NULL) {
+    if (_auto_shader_state != this) {
+      cache_unref_delete(_auto_shader_state);
+    }
+    _auto_shader_state = NULL;
+  }
+
   // If this was true at the beginning of the destructor, but is no
   // If this was true at the beginning of the destructor, but is no
   // longer true now, probably we've been double-deleted.
   // longer true now, probably we've been double-deleted.
   nassertv(get_ref_count() == 0);
   nassertv(get_ref_count() == 0);
@@ -843,9 +853,32 @@ get_invert_composition_cache() const {
 }
 }
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::get_auto_shader_state
+//       Access: Published
+//  Description: Returns the base RenderState that should have the
+//               generated_shader stored within it, for generated
+//               shader states.  The returned object might be the same
+//               as this object, or it might be a different
+//               RenderState with certain attributes removed, or set
+//               to their default values.
+//
+//               The point is to avoid needless regeneration of the
+//               shader attrib by storing the generated shader on a
+//               common RenderState object, with all irrelevant
+//               attributes removed.
+////////////////////////////////////////////////////////////////////
+const RenderState *RenderState::
+get_auto_shader_state() const {
+  if (_auto_shader_state == (const RenderState *)NULL) {
+    ((RenderState *)this)->assign_auto_shader_state();
+  }
+  return _auto_shader_state;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::output
 //     Function: RenderState::output
-//       Access: Published, Virtual
+//       Access: Published
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RenderState::
 void RenderState::
@@ -875,7 +908,7 @@ output(ostream &out) const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::write
 //     Function: RenderState::write
-//       Access: Published, Virtual
+//       Access: Published
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RenderState::
 void RenderState::
@@ -1490,6 +1523,58 @@ do_calc_hash() {
   _flags |= F_hash_known;
   _flags |= F_hash_known;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::assign_auto_shader_state
+//       Access: Private
+//  Description: Sets _auto_shader_state to the appropriate
+//               RenderState object pointer, either the same pointer
+//               as this object, or some other (simpler) RenderState.
+////////////////////////////////////////////////////////////////////
+void RenderState::
+assign_auto_shader_state() {
+  CPT(RenderState) state = do_calc_auto_shader_state();
+
+  {
+    LightReMutexHolder holder(*_states_lock);
+    if (_auto_shader_state == (const RenderState *)NULL) {
+      _auto_shader_state = state;
+      if (_auto_shader_state != this) {
+        _auto_shader_state->cache_ref();
+      }
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::do_calc_auto_shader_state
+//       Access: Private
+//  Description: Returns the appropriate RenderState that should be
+//               used to store the auto shader pointer for nodes that
+//               shader this RenderState.
+////////////////////////////////////////////////////////////////////
+CPT(RenderState) RenderState::
+do_calc_auto_shader_state() {
+  RenderState *state = new RenderState;
+
+  SlotMask mask = _filled_slots;
+  int slot = mask.get_lowest_on_bit();
+  while (slot >= 0) {
+    const Attribute &attrib = _attributes[slot];
+    nassertr(attrib._attrib != (RenderAttrib *)NULL, this);
+    CPT(RenderAttrib) new_attrib = attrib._attrib->get_auto_shader_attrib(this);
+    if (new_attrib != NULL) {
+      nassertr(new_attrib->get_slot() == slot, this);
+      state->_attributes[slot].set(new_attrib, 0);
+      state->_filled_slots.set_bit(slot);
+    }
+    
+    mask.clear_bit(slot);
+    slot = mask.get_lowest_on_bit();
+  }
+
+  return return_new(state);
+}
+
   
   
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::return_new
 //     Function: RenderState::return_new
@@ -1941,6 +2026,14 @@ void RenderState::
 remove_cache_pointers() {
 remove_cache_pointers() {
   nassertv(_states_lock->debug_is_locked());
   nassertv(_states_lock->debug_is_locked());
 
 
+  // First, make sure the _auto_shader_state cache pointer is cleared.
+  if (_auto_shader_state != (const RenderState *)NULL) {
+    if (_auto_shader_state != this) {
+      cache_unref_delete(_auto_shader_state);
+    }
+    _auto_shader_state = NULL;
+  }
+
   // Fortunately, since we added CompositionCache records in pairs, we
   // Fortunately, since we added CompositionCache records in pairs, we
   // know exactly the set of RenderState objects that have us in their
   // know exactly the set of RenderState objects that have us in their
   // cache: it's the same set of RenderState objects that we have in
   // cache: it's the same set of RenderState objects that we have in

+ 11 - 5
panda/src/pgraph/renderState.h

@@ -131,6 +131,8 @@ PUBLISHED:
   PyObject *get_invert_composition_cache() const;
   PyObject *get_invert_composition_cache() const;
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON
 
 
+  const RenderState *get_auto_shader_state() const;
+
   void output(ostream &out) const;
   void output(ostream &out) const;
   void write(ostream &out, int indent_level) const;
   void write(ostream &out, int indent_level) const;
 
 
@@ -167,6 +169,8 @@ private:
   INLINE bool do_node_unref() const;
   INLINE bool do_node_unref() const;
   INLINE void calc_hash();
   INLINE void calc_hash();
   void do_calc_hash();
   void do_calc_hash();
+  void assign_auto_shader_state();
+  CPT(RenderState) do_calc_auto_shader_state();
 
 
   class CompositionCycleDescEntry {
   class CompositionCycleDescEntry {
   public:
   public:
@@ -311,12 +315,14 @@ private:
   int _draw_order;
   int _draw_order;
   size_t _hash;
   size_t _hash;
 
 
+  const RenderState *_auto_shader_state;
+
   enum Flags {
   enum Flags {
-    F_checked_bin_index     = 0x000001,
-    F_checked_cull_callback = 0x000002,
-    F_has_cull_callback     = 0x000004,
-    F_is_destructing        = 0x000008,
-    F_hash_known            = 0x000010,
+    F_checked_bin_index       = 0x000001,
+    F_checked_cull_callback   = 0x000002,
+    F_has_cull_callback       = 0x000004,
+    F_is_destructing          = 0x000008,
+    F_hash_known              = 0x000010,
   };
   };
   unsigned int _flags;
   unsigned int _flags;
 
 

+ 21 - 0
panda/src/pgraph/shaderAttrib.cxx

@@ -732,6 +732,27 @@ compose_impl(const RenderAttrib *other) const {
   return return_new(attr);
   return return_new(attr);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ShaderAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  // For a ShaderAttrib, we only need to preserve the auto-shader
+  // flags.  Custom shaders, and custom shader inputs, aren't relevant
+  // to the shader generator.
+  ShaderAttrib *attrib = new ShaderAttrib;
+  attrib->_auto_shader = _auto_shader;
+  attrib->_has_shader = _has_shader;
+  attrib->_auto_normal_on = _auto_normal_on;
+  attrib->_auto_glow_on = _auto_glow_on;
+  attrib->_auto_gloss_on = _auto_gloss_on;
+  attrib->_auto_ramp_on = _auto_ramp_on;
+  attrib->_auto_shadow_on = _auto_shadow_on;
+  return return_new(attrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ShaderAttrib::register_with_read_factory
 //     Function: ShaderAttrib::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 1 - 0
panda/src/pgraph/shaderAttrib.h

@@ -119,6 +119,7 @@ protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
   
   
 private:
 private:
 
 

+ 10 - 0
panda/src/pgraph/texGenAttrib.cxx

@@ -563,6 +563,16 @@ invert_compose_impl(const RenderAttrib *other) const {
   return return_new(attrib);
   return return_new(attrib);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: TexGenAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) TexGenAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TexGenAttrib::filled_stages
 //     Function: TexGenAttrib::filled_stages
 //       Access: Private
 //       Access: Private

+ 1 - 0
panda/src/pgraph/texGenAttrib.h

@@ -79,6 +79,7 @@ protected:
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   class ModeDef;
   class ModeDef;

+ 24 - 0
panda/src/pgraph/texMatrixAttrib.cxx

@@ -472,6 +472,30 @@ invert_compose_impl(const RenderAttrib *other) const {
   return return_new(attrib);
   return return_new(attrib);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: TexMatrixAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) TexMatrixAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  // For a TexMatrixAttrib, the particular matrix per TextureStage
+  // isn't important, just whether there is a matrix at all.  So we
+  // create a new state with an identity matrix everywhere there is a
+  // matrix at all in the original.
+
+  TexMatrixAttrib *attrib = new TexMatrixAttrib;
+
+  Stages::const_iterator ai;
+  for (ai = _stages.begin(); ai != _stages.end(); ++ai) {
+    StageNode sn((*ai)._stage);
+    sn._transform = TransformState::make_identity();
+    attrib->_stages.insert(attrib->_stages.end(), sn);
+  }
+
+  return return_new(attrib);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TexMatrixAttrib::register_with_read_factory
 //     Function: TexMatrixAttrib::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 1 - 0
panda/src/pgraph/texMatrixAttrib.h

@@ -70,6 +70,7 @@ protected:
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   INLINE void check_stage_list() const;
   INLINE void check_stage_list() const;

+ 10 - 0
panda/src/pgraph/textureAttrib.cxx

@@ -769,6 +769,16 @@ invert_compose_impl(const RenderAttrib *other) const {
   return other;
   return other;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: TextureAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) TextureAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TextureAttrib::register_with_read_factory
 //     Function: TextureAttrib::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 1 - 0
panda/src/pgraph/textureAttrib.h

@@ -93,6 +93,7 @@ protected:
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
   virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   INLINE void check_sorted() const;
   INLINE void check_sorted() const;

+ 10 - 0
panda/src/pgraph/transparencyAttrib.cxx

@@ -123,6 +123,16 @@ get_hash_impl() const {
   return hash;
   return hash;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: TransparencyAttrib::get_auto_shader_attrib_impl
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) TransparencyAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return this;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TransparencyAttrib::register_with_read_factory
 //     Function: TransparencyAttrib::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 1 - 0
panda/src/pgraph/transparencyAttrib.h

@@ -63,6 +63,7 @@ public:
 protected:
 protected:
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual size_t get_hash_impl() const;
   virtual size_t get_hash_impl() const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
 
 
 private:
 private:
   Mode _mode;
   Mode _mode;