Browse Source

New shader system

Josh Yelon 20 years ago
parent
commit
2095d8c44f
61 changed files with 2259 additions and 1518 deletions
  1. 602 535
      doc/makepanda/makepanda.py
  2. 10 19
      panda/src/display/graphicsStateGuardian.cxx
  3. 3 2
      panda/src/display/graphicsStateGuardian.h
  4. 12 12
      panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx
  5. 181 189
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  6. 6 8
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  7. 76 81
      panda/src/glstuff/glShaderContext_src.cxx
  8. 11 9
      panda/src/glstuff/glShaderContext_src.h
  9. 2 3
      panda/src/gobj/config_gobj.cxx
  10. 1 1
      panda/src/gobj/gobj_composite2.cxx
  11. 47 0
      panda/src/gobj/internalName.I
  12. 3 0
      panda/src/gobj/internalName.cxx
  13. 6 0
      panda/src/gobj/internalName.h
  14. 13 13
      panda/src/gobj/preparedGraphicsObjects.cxx
  15. 5 5
      panda/src/gobj/preparedGraphicsObjects.h
  16. 2 2
      panda/src/gobj/shaderContext.I
  17. 3 8
      panda/src/gobj/shaderContext.h
  18. 11 11
      panda/src/gobj/shaderExpansion.I
  19. 62 65
      panda/src/gobj/shaderExpansion.cxx
  20. 30 46
      panda/src/gobj/shaderExpansion.h
  21. 2 4
      panda/src/gsgbase/graphicsStateGuardianBase.h
  22. 2 3
      panda/src/pgraph/alphaTestAttrib.cxx
  23. 2 3
      panda/src/pgraph/antialiasAttrib.cxx
  24. 2 3
      panda/src/pgraph/clipPlaneAttrib.cxx
  25. 2 3
      panda/src/pgraph/colorAttrib.cxx
  26. 2 3
      panda/src/pgraph/colorBlendAttrib.cxx
  27. 2 3
      panda/src/pgraph/colorScaleAttrib.cxx
  28. 2 3
      panda/src/pgraph/colorWriteAttrib.cxx
  29. 6 3
      panda/src/pgraph/config_pgraph.cxx
  30. 2 3
      panda/src/pgraph/cullBinAttrib.cxx
  31. 2 3
      panda/src/pgraph/cullFaceAttrib.cxx
  32. 2 3
      panda/src/pgraph/depthOffsetAttrib.cxx
  33. 2 3
      panda/src/pgraph/depthTestAttrib.cxx
  34. 2 3
      panda/src/pgraph/depthWriteAttrib.cxx
  35. 2 3
      panda/src/pgraph/fogAttrib.cxx
  36. 2 3
      panda/src/pgraph/lightAttrib.cxx
  37. 2 3
      panda/src/pgraph/materialAttrib.cxx
  38. 226 0
      panda/src/pgraph/nodePath.cxx
  39. 20 1
      panda/src/pgraph/nodePath.h
  40. 2 1
      panda/src/pgraph/pgraph_composite4.cxx
  41. 2 3
      panda/src/pgraph/renderModeAttrib.cxx
  42. 20 0
      panda/src/pgraph/renderState.I
  43. 2 0
      panda/src/pgraph/renderState.cxx
  44. 8 0
      panda/src/pgraph/renderState.h
  45. 2 3
      panda/src/pgraph/rescaleNormalAttrib.cxx
  46. 2 3
      panda/src/pgraph/shadeModelAttrib.cxx
  47. 69 0
      panda/src/pgraph/shader.I
  48. 163 0
      panda/src/pgraph/shader.cxx
  49. 93 0
      panda/src/pgraph/shader.h
  50. 55 14
      panda/src/pgraph/shaderAttrib.I
  51. 166 24
      panda/src/pgraph/shaderAttrib.cxx
  52. 26 17
      panda/src/pgraph/shaderAttrib.h
  53. 152 0
      panda/src/pgraph/shaderInput.I
  54. 26 25
      panda/src/pgraph/shaderInput.cxx
  55. 93 0
      panda/src/pgraph/shaderInput.h
  56. 0 237
      panda/src/pgraph/shaderMode.cxx
  57. 0 117
      panda/src/pgraph/shaderMode.h
  58. 2 3
      panda/src/pgraph/texGenAttrib.cxx
  59. 2 3
      panda/src/pgraph/texMatrixAttrib.cxx
  60. 2 3
      panda/src/pgraph/textureAttrib.cxx
  61. 2 3
      panda/src/pgraph/transparencyAttrib.cxx

File diff suppressed because it is too large
+ 602 - 535
doc/makepanda/makepanda.py


+ 10 - 19
panda/src/display/graphicsStateGuardian.cxx

@@ -23,17 +23,7 @@
 #include "vertexBufferContext.h"
 #include "vertexBufferContext.h"
 #include "indexBufferContext.h"
 #include "indexBufferContext.h"
 #include "renderBuffer.h"
 #include "renderBuffer.h"
-#include "colorAttrib.h"
-#include "colorScaleAttrib.h"
-#include "lightAttrib.h"
-#include "textureAttrib.h"
-#include "texGenAttrib.h"
-#include "renderState.h"
-#include "depthWriteAttrib.h"
-#include "colorWriteAttrib.h"
-#include "textureAttrib.h"
-#include "lightAttrib.h"
-#include "clipPlaneAttrib.h"
+#include "attribSlots.h"
 #include "light.h"
 #include "light.h"
 #include "planeNode.h"
 #include "planeNode.h"
 #include "ambientLight.h"
 #include "ambientLight.h"
@@ -279,7 +269,8 @@ reset() {
   _frame_buffer_stack_level = 0;
   _frame_buffer_stack_level = 0;
   _lens_stack_level = 0;
   _lens_stack_level = 0;
 
 
-  _last_state = NULL;
+  _state_rs = NULL;
+  _target_rs = NULL;
   _state.clear_to_zero();
   _state.clear_to_zero();
   _target.clear_to_defaults();
   _target.clear_to_defaults();
   _external_transform = TransformState::make_identity();
   _external_transform = TransformState::make_identity();
@@ -430,7 +421,7 @@ release_geom(GeomContext *) {
 //  Description: Compile a vertex/fragment shader body.
 //  Description: Compile a vertex/fragment shader body.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 ShaderContext *GraphicsStateGuardian::
 ShaderContext *GraphicsStateGuardian::
-prepare_shader(Shader *shader) {
+prepare_shader(ShaderExpansion *shader) {
   return (ShaderContext *)NULL;
   return (ShaderContext *)NULL;
 }
 }
 
 
@@ -672,7 +663,7 @@ begin_frame() {
   // have changed properties since last time without changing
   // have changed properties since last time without changing
   // attribute pointers--like textures, lighting, or fog--will still
   // attribute pointers--like textures, lighting, or fog--will still
   // be accurately updated.
   // be accurately updated.
-  _last_state = 0;
+  _state_rs = 0;
   _state.clear_to_zero();
   _state.clear_to_zero();
   
   
   return true;
   return true;
@@ -751,7 +742,7 @@ end_scene() {
   }
   }
 
 
   // Put the state into the 'unknown' state, forcing a reload.
   // Put the state into the 'unknown' state, forcing a reload.
-  _last_state = 0;
+  _state_rs = 0;
   _state.clear_to_zero();
   _state.clear_to_zero();
 
 
   // We need to reset this to force a dynamic texture to be reloaded
   // We need to reset this to force a dynamic texture to be reloaded
@@ -1033,15 +1024,15 @@ do_issue_color_scale() {
   _current_color_scale = attrib->get_scale();
   _current_color_scale = attrib->get_scale();
   
   
   if (_color_blend_involves_color_scale) {
   if (_color_blend_involves_color_scale) {
-    _last_state = 0;
+    _state_rs = 0;
     _state._transparency = 0;
     _state._transparency = 0;
   }
   }
   if (_texture_involves_color_scale) {
   if (_texture_involves_color_scale) {
-    _last_state = 0;
+    _state_rs = 0;
     _state._texture = 0;
     _state._texture = 0;
   }
   }
   if (_color_scale_via_lighting) {
   if (_color_scale_via_lighting) {
-    _last_state = 0;
+    _state_rs = 0;
     _state._light = 0;
     _state._light = 0;
     _state._material = 0;
     _state._material = 0;
 
 
@@ -1090,7 +1081,7 @@ do_issue_color() {
   }
   }
 
 
   if (_color_scale_via_lighting) {
   if (_color_scale_via_lighting) {
-    _last_state = 0;
+    _state_rs = 0;
     _state._light = 0;
     _state._light = 0;
     _state._material = 0;
     _state._material = 0;
 
 

+ 3 - 2
panda/src/display/graphicsStateGuardian.h

@@ -132,7 +132,7 @@ public:
   virtual GeomContext *prepare_geom(Geom *geom);
   virtual GeomContext *prepare_geom(Geom *geom);
   virtual void release_geom(GeomContext *gc);
   virtual void release_geom(GeomContext *gc);
 
 
-  virtual ShaderContext *prepare_shader(Shader *shader);
+  virtual ShaderContext *prepare_shader(ShaderExpansion *shader);
   virtual void release_shader(ShaderContext *sc);
   virtual void release_shader(ShaderContext *sc);
   
   
   virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
   virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
@@ -281,9 +281,10 @@ protected:
   PT(SceneSetup) _scene_null;
   PT(SceneSetup) _scene_null;
   PT(SceneSetup) _scene_setup;
   PT(SceneSetup) _scene_setup;
   
   
-  CPT(RenderState) _last_state;
   AttribSlots _state;
   AttribSlots _state;
   AttribSlots _target;
   AttribSlots _target;
+  CPT(RenderState) _state_rs;
+  CPT(RenderState) _target_rs;
   CPT(TransformState) _external_transform;
   CPT(TransformState) _external_transform;
   CPT(TransformState) _internal_transform;
   CPT(TransformState) _internal_transform;
   CPT(GeomMunger) _munger;
   CPT(GeomMunger) _munger;

+ 12 - 12
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -1965,12 +1965,12 @@ do_issue_shade_model() {
 //               state is already stored in _target.
 //               state is already stored in _target.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 void DXGraphicsStateGuardian8::
-set_state_and_transform(const RenderState *state,
+set_state_and_transform(const RenderState *target,
                         const TransformState *transform) {
                         const TransformState *transform) {
 #ifndef NDEBUG
 #ifndef NDEBUG
   if (gsg_cat.is_spam()) {
   if (gsg_cat.is_spam()) {
-    gsg_cat.spam() << "Setting GSG state to " << (void *)state << ":\n";
-    state->write(gsg_cat.spam(false), 2);
+    gsg_cat.spam() << "Setting GSG state to " << (void *)target << ":\n";
+    target->write(gsg_cat.spam(false), 2);
   }
   }
 #endif
 #endif
   _state_pcollector.add_level(1);
   _state_pcollector.add_level(1);
@@ -1982,15 +1982,13 @@ set_state_and_transform(const RenderState *state,
     do_issue_transform();
     do_issue_transform();
   }
   }
   
   
-  if (state) {
-    if (state == _last_state) {
-      return;
-    }
-    _target.clear_to_defaults();
-    state->store_into_slots(&_target);
+  if (target == _state_rs) {
+    return;
   }
   }
-  _last_state = state;
-  
+  _target_rs = target;
+  _target.clear_to_defaults();
+  target->store_into_slots(&_target);
+  _state_rs = 0;
   
   
   if (_target._alpha_test != _state._alpha_test) {
   if (_target._alpha_test != _state._alpha_test) {
     do_issue_alpha_test();
     do_issue_alpha_test();
@@ -2097,6 +2095,8 @@ set_state_and_transform(const RenderState *state,
     do_issue_light();
     do_issue_light();
     _state._light = _target._light;
     _state._light = _target._light;
   }
   }
+
+  _state_rs = _target_rs;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -2724,7 +2724,7 @@ free_nondx_resources() {
 void DXGraphicsStateGuardian8::
 void DXGraphicsStateGuardian8::
 free_d3d_device() {
 free_d3d_device() {
   // dont want a full reset of gsg, just a state clear
   // dont want a full reset of gsg, just a state clear
-  _last_state = 0;
+  _state_rs = 0;
   _state.clear_to_zero();
   _state.clear_to_zero();
   // want gsg to pass all state settings through
   // want gsg to pass all state settings through
 
 

+ 181 - 189
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -35,23 +35,7 @@
 #include "pointLight.h"
 #include "pointLight.h"
 #include "spotlight.h"
 #include "spotlight.h"
 #include "planeNode.h"
 #include "planeNode.h"
-#include "textureAttrib.h"
-#include "lightAttrib.h"
-#include "cullFaceAttrib.h"
-#include "transparencyAttrib.h"
-#include "alphaTestAttrib.h"
-#include "depthTestAttrib.h"
-#include "depthWriteAttrib.h"
-#include "colorWriteAttrib.h"
-#include "texMatrixAttrib.h"
-#include "texGenAttrib.h"
-#include "materialAttrib.h"
-#include "renderModeAttrib.h"
-#include "rescaleNormalAttrib.h"
-#include "fogAttrib.h"
-#include "depthOffsetAttrib.h"
-#include "shadeModelAttrib.h"
-#include "shaderAttrib.h"
+#include "attribSlots.h"
 #include "fog.h"
 #include "fog.h"
 #include "clockObject.h"
 #include "clockObject.h"
 #include "string_utils.h"
 #include "string_utils.h"
@@ -65,8 +49,6 @@
 #include "mutexHolder.h"
 #include "mutexHolder.h"
 #include "indirectLess.h"
 #include "indirectLess.h"
 #include "pStatTimer.h"
 #include "pStatTimer.h"
-#include "shader.h"
-#include "shaderMode.h"
 
 
 #include <algorithm>
 #include <algorithm>
 
 
@@ -771,9 +753,9 @@ reset() {
 
 
   _texgen_forced_normal = false;
   _texgen_forced_normal = false;
 
 
-  _current_shader_mode = (ShaderMode *)NULL;
+  _current_shader_expansion = (ShaderExpansion *)NULL;
   _current_shader_context = (CLP(ShaderContext) *)NULL;
   _current_shader_context = (CLP(ShaderContext) *)NULL;
-  _vertex_array_shader_mode = (ShaderMode *)NULL;
+  _vertex_array_shader_expansion = (ShaderExpansion *)NULL;
   _vertex_array_shader_context = (CLP(ShaderContext) *)NULL;
   _vertex_array_shader_context = (CLP(ShaderContext) *)NULL;
   
   
   // Count the max number of lights
   // Count the max number of lights
@@ -863,18 +845,14 @@ do_clear(const RenderBuffer &buffer) {
                     _color_clear_value[1],
                     _color_clear_value[1],
                     _color_clear_value[2],
                     _color_clear_value[2],
                     _color_clear_value[3]);
                     _color_clear_value[3]);
-    _target._color_write = AttribSlots::get_defaults()._color_write;
     mask |= GL_COLOR_BUFFER_BIT;
     mask |= GL_COLOR_BUFFER_BIT;
-
+    _target._color_write = AttribSlots::get_defaults()._color_write;
     set_draw_buffer(buffer);
     set_draw_buffer(buffer);
   }
   }
-
+  
   if (buffer_type & RenderBuffer::T_depth) {
   if (buffer_type & RenderBuffer::T_depth) {
     GLP(ClearDepth)(_depth_clear_value);
     GLP(ClearDepth)(_depth_clear_value);
     mask |= GL_DEPTH_BUFFER_BIT;
     mask |= GL_DEPTH_BUFFER_BIT;
-
-    // In order to clear the depth buffer, the depth mask must enable
-    // writing to the depth buffer.
     _target._depth_write = AttribSlots::get_defaults()._depth_write;
     _target._depth_write = AttribSlots::get_defaults()._depth_write;
   }
   }
 
 
@@ -908,7 +886,19 @@ do_clear(const RenderBuffer &buffer) {
     GLCAT.spam(false) << ")" << endl;
     GLCAT.spam(false) << ")" << endl;
   }
   }
   
   
-  set_state_and_transform(NULL, _external_transform);
+  if (_target._depth_write != _state._depth_write) {
+    do_issue_depth_write();
+    _state._depth_write = _target._depth_write;
+  }
+  if ((_target._transparency != _state._transparency)||
+      (_target._color_write != _state._color_write)||
+      (_target._color_blend != _state._color_blend)) {
+    do_issue_blending();
+    _state._transparency = _target._transparency;
+    _state._color_write = _target._color_write;
+    _state._color_blend = _target._color_blend;
+  }
+  _state_rs = 0;
   
   
   GLP(Clear)(mask);
   GLP(Clear)(mask);
   report_my_gl_errors();
   report_my_gl_errors();
@@ -1312,7 +1302,7 @@ begin_draw_primitives(const Geom *geom, const GeomMunger *munger,
         update_shader_vertex_arrays(_vertex_array_shader_context,this);
         update_shader_vertex_arrays(_vertex_array_shader_context,this);
     }
     }
   }
   }
-  _vertex_array_shader_mode = _current_shader_mode;
+  _vertex_array_shader_expansion = _current_shader_expansion;
   _vertex_array_shader_context = _current_shader_context;
   _vertex_array_shader_context = _current_shader_context;
   
   
   report_my_gl_errors();
   report_my_gl_errors();
@@ -2008,8 +1998,8 @@ release_geom(GeomContext *gc) {
 //  Description: yadda.
 //  Description: yadda.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 ShaderContext *CLP(GraphicsStateGuardian)::
 ShaderContext *CLP(GraphicsStateGuardian)::
-prepare_shader(Shader *shader) {
-  CLP(ShaderContext) *result = new CLP(ShaderContext)(shader);
+prepare_shader(ShaderExpansion *se) {
+  CLP(ShaderContext) *result = new CLP(ShaderContext)(se);
   if (result->valid()) return result;
   if (result->valid()) return result;
   delete result;
   delete result;
   return NULL;
   return NULL;
@@ -2438,7 +2428,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
   report_my_gl_errors();
   report_my_gl_errors();
 
 
   // Force reload of texture state, since we've just monkeyed with it.
   // Force reload of texture state, since we've just monkeyed with it.
-  _last_state = 0;
+  _state_rs = 0;
   _state._texture = 0;
   _state._texture = 0;
 }
 }
 
 
@@ -2464,7 +2454,11 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
   // NOTE: reading the depth buffer is *much* slower than reading the
   // NOTE: reading the depth buffer is *much* slower than reading the
   // color buffer
   // color buffer
   _target._texture = AttribSlots::get_defaults()._texture;
   _target._texture = AttribSlots::get_defaults()._texture;
-  set_state_and_transform(NULL, _external_transform);
+  if (_target._texture != _state._texture) {
+    do_issue_texture();
+    _state._texture = _target._texture;
+  }
+  _state_rs = 0;
   
   
   int xo, yo, w, h;
   int xo, yo, w, h;
   dr->get_region_pixels(xo, yo, w, h);
   dr->get_region_pixels(xo, yo, w, h);
@@ -2641,7 +2635,7 @@ do_issue_transform() {
   }
   }
 
 
   if (_current_shader_context)
   if (_current_shader_context)
-    _current_shader_context->issue_transform(_current_shader_mode, this);
+    _current_shader_context->issue_transform(this);
   
   
   report_my_gl_errors();
   report_my_gl_errors();
 }
 }
@@ -2670,28 +2664,30 @@ do_issue_shade_model() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::do_issue_shader
 //     Function: GLGraphicsStateGuardian::do_issue_shader
 //       Access: Protected
 //       Access: Protected
-//  Description: Bind a shader.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 void CLP(GraphicsStateGuardian)::
 do_issue_shader() {
 do_issue_shader() {
-  const ShaderAttrib *attrib = _target._shader;
-  ShaderMode *mode = attrib->get_shader_mode();
-  if (mode == 0) {
-    if (_current_shader_context != 0) {
-      _current_shader_context->unbind();
-      _current_shader_mode = 0;
-      _current_shader_context = 0;
+  CLP(ShaderContext) *context = 0;
+  ShaderExpansion *expansion = _target_rs->get_shader_expansion();
+  if (expansion == 0) {
+    if (_target._shader->get_shader() != 0) {
+      expansion = _target._shader->get_shader()->macroexpand(_target_rs);
+      // I am casting away the const-ness of this pointer, because
+      // the 'shader-expansion' field is just a cache.
+      ((RenderState *)((const RenderState*)_target_rs))->
+        set_shader_expansion(expansion);
     }
     }
-    return;
   }
   }
   
   
-  Shader *shader = mode->get_shader();
-  CLP(ShaderContext) *context = (CLP(ShaderContext) *)(shader->prepare_now(get_prepared_objects(), this));
+  if (expansion) {
+    context = (CLP(ShaderContext) *)(expansion->prepare_now(get_prepared_objects(), this));
+  }
 
 
   if (context == 0) {
   if (context == 0) {
     if (_current_shader_context != 0) {
     if (_current_shader_context != 0) {
       _current_shader_context->unbind();
       _current_shader_context->unbind();
-      _current_shader_mode = 0;
+      _current_shader_expansion = 0;
       _current_shader_context = 0;
       _current_shader_context = 0;
     }
     }
     return;
     return;
@@ -2703,19 +2699,18 @@ do_issue_shader() {
     if (_current_shader_context != 0) {
     if (_current_shader_context != 0) {
       _current_shader_context->unbind();
       _current_shader_context->unbind();
       _current_shader_context = 0;
       _current_shader_context = 0;
+      _current_shader_expansion = 0;
     }
     }
     if (context != 0) {
     if (context != 0) {
-      context->bind(mode, this);
-      _current_shader_mode = mode;
+      context->bind(this);
+      _current_shader_expansion = expansion;
       _current_shader_context = context;
       _current_shader_context = context;
     }
     }
   } else {
   } else {
     // Use the same shader as before, but with new input arguments.
     // Use the same shader as before, but with new input arguments.
-    _current_shader_mode = mode;
-    _current_shader_context = context;
-    context->issue_parameters(mode, this);
+    context->issue_parameters(this);
   }
   }
-
+  
   report_my_gl_errors();
   report_my_gl_errors();
 }
 }
 
 
@@ -3062,6 +3057,128 @@ do_issue_material() {
   report_my_gl_errors();
   report_my_gl_errors();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::do_issue_blending
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+do_issue_blending() {
+
+  // Handle the color_write attrib.  If color_write is off, then
+  // all the other blending-related stuff doesn't matter.  If the
+  // device doesn't support color-write, we use blending tricks
+  // to effectively disable color write.
+  if (_target._color_write->get_mode() == ColorWriteAttrib::M_off) {
+    if (_target._color_write != _state._color_write) {
+      enable_multisample_alpha_one(false);
+      enable_multisample_alpha_mask(false);
+      if (CLP(color_mask)) {
+        enable_blend(false);
+        GLP(ColorMask)(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+      } else {
+        enable_blend(true);
+        _glBlendEquation(GL_FUNC_ADD);
+        GLP(BlendFunc)(GL_ZERO, GL_ONE);
+      }
+    }
+    return;
+  } else {
+    if (_target._color_write != _state._color_write) {
+      if (CLP(color_mask)) {
+        GLP(ColorMask)(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+      }
+    }
+  }
+  
+  CPT(ColorBlendAttrib) color_blend = _target._color_blend;
+  ColorBlendAttrib::Mode color_blend_mode = _target._color_blend->get_mode();
+  TransparencyAttrib::Mode transparency_mode = _target._transparency->get_mode();
+
+  _color_blend_involves_color_scale = color_blend->involves_color_scale();
+
+  // Is there a color blend set?
+  if (color_blend_mode != ColorBlendAttrib::M_none) {
+    enable_multisample_alpha_one(false);
+    enable_multisample_alpha_mask(false);
+    enable_blend(true);
+    _glBlendEquation(get_blend_equation_type(color_blend_mode));
+    GLP(BlendFunc)(get_blend_func(color_blend->get_operand_a()),
+                   get_blend_func(color_blend->get_operand_b()));
+
+    if (_color_blend_involves_color_scale) {
+      // Apply the current color scale to the blend mode.
+      _glBlendColor(_current_color_scale[0], _current_color_scale[1], 
+                    _current_color_scale[2], _current_color_scale[3]);
+      
+    } else {
+      Colorf c = color_blend->get_color();
+      _glBlendColor(c[0], c[1], c[2], c[3]);
+    }
+    return;
+  }
+
+  // No color blend; is there a transparency set?
+  switch (transparency_mode) {
+  case TransparencyAttrib::M_none:
+  case TransparencyAttrib::M_binary:
+    break;
+    
+  case TransparencyAttrib::M_alpha:
+  case TransparencyAttrib::M_dual:
+    enable_multisample_alpha_one(false);
+    enable_multisample_alpha_mask(false);
+    enable_blend(true);
+    _glBlendEquation(GL_FUNC_ADD);
+    GLP(BlendFunc)(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    return;
+    
+  case TransparencyAttrib::M_multisample:
+    // We need to enable *both* of these in M_multisample case.
+    enable_multisample_alpha_one(true);
+    enable_multisample_alpha_mask(true);
+    enable_blend(false);
+    return;
+    
+  case TransparencyAttrib::M_multisample_mask:
+    enable_multisample_alpha_one(false);
+    enable_multisample_alpha_mask(true);
+    enable_blend(false);
+    return;
+    
+  default:
+    GLCAT.error()
+      << "invalid transparency mode " << (int)transparency_mode << endl;
+    break;
+  }
+
+  if (_line_smooth_enabled || _point_smooth_enabled) {
+    // If we have either of these turned on, we also need to have
+    // blend mode enabled in order to see it.
+    enable_multisample_alpha_one(false);
+    enable_multisample_alpha_mask(false);
+    enable_blend(true);
+    _glBlendEquation(GL_FUNC_ADD);
+    GLP(BlendFunc)(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    return;
+  }
+
+  // For best polygon smoothing, we need:
+  // (1) a frame buffer that supports alpha
+  // (2) sort polygons front-to-back
+  // (3) glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE);
+  //
+  // Since these modes have other implications for the application, we
+  // don't attempt to do this by default.  If you really want good
+  // polygon smoothing (and you don't have multisample support), do
+  // all this yourself.
+
+  // Nothing's set, so disable blending.
+  enable_multisample_alpha_one(false);
+  enable_multisample_alpha_mask(false);
+  enable_blend(false);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::bind_light
 //     Function: GLGraphicsStateGuardian::bind_light
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -4429,128 +4546,6 @@ end_bind_clip_planes() {
   GLP(PopMatrix)();
   GLP(PopMatrix)();
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: GLGraphicsStateGuardian::do_issue_blending
-//       Access: Protected
-//  Description:
-////////////////////////////////////////////////////////////////////
-void CLP(GraphicsStateGuardian)::
-do_issue_blending() {
-
-  // If necessary, we disable writing to the color buffer using
-  // blending.  This case is only used if we can't use GLP(ColorMask)
-  // to disable the color writing for some reason (usually a driver
-  // problem).
-  if (_target._color_write->get_mode() == ColorWriteAttrib::M_off) {
-    if (_target._color_write != _state._color_write) {
-      enable_multisample_alpha_one(false);
-      enable_multisample_alpha_mask(false);
-      if (CLP(color_mask)) {
-        enable_blend(false);
-        GLP(ColorMask)(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-      } else {
-        enable_blend(true);
-        _glBlendEquation(GL_FUNC_ADD);
-        GLP(BlendFunc)(GL_ZERO, GL_ONE);
-      }
-    }
-    return;
-  } else {
-    if (_target._color_write != _state._color_write) {
-      if (CLP(color_mask)) {
-        GLP(ColorMask)(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-      }
-    }
-  }
-  
-  CPT(ColorBlendAttrib) color_blend = _target._color_blend;
-  ColorBlendAttrib::Mode color_blend_mode = _target._color_blend->get_mode();
-  TransparencyAttrib::Mode transparency_mode = _target._transparency->get_mode();
-
-  _color_blend_involves_color_scale = color_blend->involves_color_scale();
-
-  // Is there a color blend set?
-  if (color_blend_mode != ColorBlendAttrib::M_none) {
-    enable_multisample_alpha_one(false);
-    enable_multisample_alpha_mask(false);
-    enable_blend(true);
-    _glBlendEquation(get_blend_equation_type(color_blend_mode));
-    GLP(BlendFunc)(get_blend_func(color_blend->get_operand_a()),
-                   get_blend_func(color_blend->get_operand_b()));
-
-    if (_color_blend_involves_color_scale) {
-      // Apply the current color scale to the blend mode.
-      _glBlendColor(_current_color_scale[0], _current_color_scale[1], 
-                    _current_color_scale[2], _current_color_scale[3]);
-      
-    } else {
-      Colorf c = color_blend->get_color();
-      _glBlendColor(c[0], c[1], c[2], c[3]);
-    }
-    return;
-  }
-
-  // No color blend; is there a transparency set?
-  switch (transparency_mode) {
-  case TransparencyAttrib::M_none:
-  case TransparencyAttrib::M_binary:
-    break;
-    
-  case TransparencyAttrib::M_alpha:
-  case TransparencyAttrib::M_dual:
-    enable_multisample_alpha_one(false);
-    enable_multisample_alpha_mask(false);
-    enable_blend(true);
-    _glBlendEquation(GL_FUNC_ADD);
-    GLP(BlendFunc)(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    return;
-    
-  case TransparencyAttrib::M_multisample:
-    // We need to enable *both* of these in M_multisample case.
-    enable_multisample_alpha_one(true);
-    enable_multisample_alpha_mask(true);
-    enable_blend(false);
-    return;
-    
-  case TransparencyAttrib::M_multisample_mask:
-    enable_multisample_alpha_one(false);
-    enable_multisample_alpha_mask(true);
-    enable_blend(false);
-    return;
-    
-  default:
-    GLCAT.error()
-      << "invalid transparency mode " << (int)transparency_mode << endl;
-    break;
-  }
-
-  if (_line_smooth_enabled || _point_smooth_enabled) {
-    // If we have either of these turned on, we also need to have
-    // blend mode enabled in order to see it.
-    enable_multisample_alpha_one(false);
-    enable_multisample_alpha_mask(false);
-    enable_blend(true);
-    _glBlendEquation(GL_FUNC_ADD);
-    GLP(BlendFunc)(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    return;
-  }
-
-  // For best polygon smoothing, we need:
-  // (1) a frame buffer that supports alpha
-  // (2) sort polygons front-to-back
-  // (3) glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE);
-  //
-  // Since these modes have other implications for the application, we
-  // don't attempt to do this by default.  If you really want good
-  // polygon smoothing (and you don't have multisample support), do
-  // all this yourself.
-
-  // Nothing's set, so disable blending.
-  enable_multisample_alpha_one(false);
-  enable_multisample_alpha_mask(false);
-  enable_blend(false);
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::set_state_and_transform
 //     Function: GLGraphicsStateGuardian::set_state_and_transform
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -4562,17 +4557,14 @@ do_issue_blending() {
 //               space; internally, it will be pretransformed by
 //               space; internally, it will be pretransformed by
 //               get_cs_transform() to express it in the GSG's
 //               get_cs_transform() to express it in the GSG's
 //               internal coordinate space.
 //               internal coordinate space.
-//
-//               Special case: if (state==NULL), then the target
-//               state is already stored in _target.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 void CLP(GraphicsStateGuardian)::
-set_state_and_transform(const RenderState *state,
+set_state_and_transform(const RenderState *target,
                         const TransformState *transform) {
                         const TransformState *transform) {
 #ifndef NDEBUG
 #ifndef NDEBUG
   if (gsg_cat.is_spam()) {
   if (gsg_cat.is_spam()) {
-    gsg_cat.spam() << "Setting GSG state to " << (void *)state << ":\n";
-    state->write(gsg_cat.spam(false), 2);
+    gsg_cat.spam() << "Setting GSG state to " << (void *)target << ":\n";
+    target->write(gsg_cat.spam(false), 2);
   }
   }
 #endif
 #endif
   _state_pcollector.add_level(1);
   _state_pcollector.add_level(1);
@@ -4584,15 +4576,13 @@ set_state_and_transform(const RenderState *state,
     do_issue_transform();
     do_issue_transform();
   }
   }
   
   
-  if (state) {
-    if (state == _last_state) {
-      return;
-    }
-    _target.clear_to_defaults();
-    state->store_into_slots(&_target);
+  if (target == _state_rs) {
+    return;
   }
   }
-  _last_state = state;
-  
+  _target_rs = target;
+  _target.clear_to_defaults();
+  target->store_into_slots(&_target);
+  _state_rs = 0;
   
   
   if (_target._alpha_test != _state._alpha_test) {
   if (_target._alpha_test != _state._alpha_test) {
     do_issue_alpha_test();
     do_issue_alpha_test();
@@ -4978,6 +4968,8 @@ set_state_and_transform(const RenderState *state,
 
 
     report_my_gl_errors();
     report_my_gl_errors();
   }
   }
+
+  _state_rs = _target_rs;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -5234,7 +5226,7 @@ do_issue_texture() {
   // texgen and texmat attribs.
   // texgen and texmat attribs.
   _needs_tex_gen = true;
   _needs_tex_gen = true;
   _needs_tex_mat = true;
   _needs_tex_mat = true;
-
+  
   report_my_gl_errors();
   report_my_gl_errors();
 }
 }
 
 

+ 6 - 8
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -38,8 +38,6 @@
 #include "pmap.h"
 #include "pmap.h"
 #include "geomVertexArrayData.h"
 #include "geomVertexArrayData.h"
 #include "pmutex.h"
 #include "pmutex.h"
-#include "shader.h"
-#include "shaderMode.h"
 
 
 class PlaneNode;
 class PlaneNode;
 class Light;
 class Light;
@@ -104,9 +102,9 @@ public:
   virtual GeomContext *prepare_geom(Geom *geom);
   virtual GeomContext *prepare_geom(Geom *geom);
   virtual void release_geom(GeomContext *gc);
   virtual void release_geom(GeomContext *gc);
 
 
-  virtual ShaderContext *prepare_shader(Shader *shader);
+  virtual ShaderContext *prepare_shader(ShaderExpansion *shader);
   virtual void release_shader(ShaderContext *sc);
   virtual void release_shader(ShaderContext *sc);
-
+  
   void record_deleted_display_list(GLuint index);
   void record_deleted_display_list(GLuint index);
 
 
   virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
   virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
@@ -308,10 +306,10 @@ protected:
   bool _point_perspective;
   bool _point_perspective;
   bool _vertex_blending_enabled;
   bool _vertex_blending_enabled;
   
   
-  PT(ShaderMode) _current_shader_mode;
-  CLP(ShaderContext) *_current_shader_context;
-  PT(ShaderMode) _vertex_array_shader_mode;
-  CLP(ShaderContext) *_vertex_array_shader_context;
+  PT(ShaderExpansion)  _current_shader_expansion;
+  CLP(ShaderContext)  *_current_shader_context;
+  PT(ShaderExpansion)  _vertex_array_shader_expansion;
+  CLP(ShaderContext)  *_vertex_array_shader_context;
   
   
   CPT(DisplayRegion) _actual_display_region;
   CPT(DisplayRegion) _actual_display_region;
 
 

+ 76 - 81
panda/src/glstuff/glShaderContext_src.cxx

@@ -24,7 +24,7 @@ TypeHandle CLP(ShaderContext)::_type_handle;
 //  Description: xyz
 //  Description: xyz
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CLP(ShaderContext)::
 CLP(ShaderContext)::
-CLP(ShaderContext)(Shader *s) : ShaderContext(s) {
+CLP(ShaderContext)(ShaderExpansion *s) : ShaderContext(s) {
   string header;
   string header;
   s->parse_init();
   s->parse_init();
   s->parse_line(header, true, true);
   s->parse_line(header, true, true);
@@ -58,13 +58,13 @@ CLP(ShaderContext)(Shader *s) : ShaderContext(s) {
     _cg_program[0] =
     _cg_program[0] =
       cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
       cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
                       _cg_profile[0], "vshader", (const char**)NULL);
                       _cg_profile[0], "vshader", (const char**)NULL);
-    print_cg_compile_errors(s->_file, _cg_context);
+    print_cg_compile_errors(s->get_name(), _cg_context);
 
 
     cgGetError();
     cgGetError();
     _cg_program[1] =
     _cg_program[1] =
       cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
       cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
                       _cg_profile[1], "fshader", (const char**)NULL);
                       _cg_profile[1], "fshader", (const char**)NULL);
-    print_cg_compile_errors(s->_file, _cg_context);
+    print_cg_compile_errors(s->get_name(), _cg_context);
 
 
     if ((_cg_program[SHADER_type_vert]==0)||(_cg_program[SHADER_type_frag]==0)) {
     if ((_cg_program[SHADER_type_vert]==0)||(_cg_program[SHADER_type_frag]==0)) {
       release_resources();
       release_resources();
@@ -88,12 +88,12 @@ CLP(ShaderContext)(Shader *s) : ShaderContext(s) {
     cgGLLoadProgram(_cg_program[SHADER_type_vert]);
     cgGLLoadProgram(_cg_program[SHADER_type_vert]);
     cgGLLoadProgram(_cg_program[SHADER_type_frag]);
     cgGLLoadProgram(_cg_program[SHADER_type_frag]);
     
     
-    cerr << s->_file << ": compiled ok.\n";
+    cerr << s->get_name() << ": compiled ok.\n";
     return;
     return;
   }
   }
 #endif
 #endif
   
   
-  cerr << s->_file << ": unrecognized shader language " << header << "\n";
+  cerr << s->get_name() << ": unrecognized shader language " << header << "\n";
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -134,13 +134,13 @@ release_resources() {
 //               input parameters.
 //               input parameters.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 void CLP(ShaderContext)::
-bind(ShaderMode *m, GSG *gsg) {
+bind(GSG *gsg) {
 #ifdef HAVE_CGGL
 #ifdef HAVE_CGGL
   if (_cg_context != 0) {
   if (_cg_context != 0) {
 
 
     // Pass in k-parameters and transform-parameters
     // Pass in k-parameters and transform-parameters
-    issue_parameters(m, gsg);
-    issue_transform(m, gsg);
+    issue_parameters(gsg);
+    issue_transform(gsg);
     
     
     // Bind the shaders.
     // Bind the shaders.
     cgGLEnableProfile(_cg_profile[SHADER_type_vert]);
     cgGLEnableProfile(_cg_profile[SHADER_type_vert]);
@@ -171,39 +171,42 @@ unbind()
 //     Function: GLShaderContext::issue_parameters
 //     Function: GLShaderContext::issue_parameters
 //       Access: Public
 //       Access: Public
 //  Description: This function is to be called whenever
 //  Description: This function is to be called whenever
-//               the ShaderMode has changed, but the Shader
-//               itself has not changed.  It loads the new
-//               input parameters into the already-bound shader.
+//               the RenderState has changed, but the ShaderExpansion
+//               has not changed.  It loads the new input parameters
+//               into the already-bound shader.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 void CLP(ShaderContext)::
-issue_parameters(ShaderMode *m, GSG *gsg)
+issue_parameters(GSG *gsg)
 {
 {
 #ifdef HAVE_CGGL
 #ifdef HAVE_CGGL
   if (_cg_context != 0) {
   if (_cg_context != 0) {
     // Pass in k-float parameters.
     // Pass in k-float parameters.
     for (int i=0; i<(int)_cg_fbind.size(); i++) {
     for (int i=0; i<(int)_cg_fbind.size(); i++) {
-      int index = _cg_fbind[i].argindex;
-      if (index >= (int)m->_args.size()) continue;
-      if (m->_args[index]._type != ShaderModeArg::SAT_FLOAT) continue;
-      cgGLSetParameter4dv(_cg_fbind[i].parameter, m->_args[index]._fvalue.get_data());
+      InternalName *id = _cg_fbind[i].name;
+      const ShaderInput *input = gsg->_target._shader->get_input(id);
+      cgGLSetParameter4fv(_cg_fbind[i].parameter, input->get_vector().get_data());
     }
     }
-
+    
     // Pass in k-float4x4 parameters.
     // Pass in k-float4x4 parameters.
     for (int i=0; i<(int)_cg_npbind.size(); i++) {
     for (int i=0; i<(int)_cg_npbind.size(); i++) {
-      int index = _cg_npbind[i].argindex;
-      if (index >= (int)m->_args.size()) continue;
-      if (m->_args[index]._type != ShaderModeArg::SAT_NODEPATH) continue;
-      const float *dat = m->_args[index]._nvalue.node()->get_transform()->get_mat().get_data();
+      InternalName *id = _cg_npbind[i].name;
+      const ShaderInput *input = gsg->_target._shader->get_input(id);
+      const float *dat;
+      if (input->get_nodepath().is_empty()) {
+        dat = LMatrix4f::ident_mat().get_data();
+      } else {
+        dat = input->get_nodepath().node()->get_transform()->get_mat().get_data();
+      }
       cgGLSetMatrixParameterfc(_cg_npbind[i].parameter, dat);
       cgGLSetMatrixParameterfc(_cg_npbind[i].parameter, dat);
     }
     }
     
     
     // Pass in trans,tpose,row,col,xvec,yvec,zvec,pos parameters
     // Pass in trans,tpose,row,col,xvec,yvec,zvec,pos parameters
     for (int i=0; i<(int)_cg_parameter_bind.size(); i++)
     for (int i=0; i<(int)_cg_parameter_bind.size(); i++)
-      bind_cg_transform(_cg_parameter_bind[i], m, gsg);
+      bind_cg_transform(_cg_parameter_bind[i], gsg);
 
 
     // Pass in trans,tpose,row,col,xvec,yvec,zvec,pos parameters
     // Pass in trans,tpose,row,col,xvec,yvec,zvec,pos parameters
     for (int i=0; i<(int)_cg_transform_bind.size(); i++)
     for (int i=0; i<(int)_cg_transform_bind.size(); i++)
-      bind_cg_transform(_cg_transform_bind[i], m, gsg);
+      bind_cg_transform(_cg_transform_bind[i], gsg);
   }
   }
 #endif
 #endif
 }
 }
@@ -213,11 +216,11 @@ issue_parameters(ShaderMode *m, GSG *gsg)
 //       Access: Public
 //       Access: Public
 //  Description: This function is to be called whenever
 //  Description: This function is to be called whenever
 //               the external_transform has changed, but the
 //               the external_transform has changed, but the
-//               Shader itself has not changed.  It loads the 
+//               ShaderExpansion itself has not changed.  It loads the 
 //               new transform into the already-bound shader.
 //               new transform into the already-bound shader.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 void CLP(ShaderContext)::
-issue_transform(ShaderMode *m, GSG *gsg)
+issue_transform(GSG *gsg)
 {
 {
 #ifdef HAVE_CGGL
 #ifdef HAVE_CGGL
   if (_cg_context != 0) {
   if (_cg_context != 0) {
@@ -229,7 +232,7 @@ issue_transform(ShaderMode *m, GSG *gsg)
     
     
     // Pass in trans,tpose,row,col,xvec,yvec,zvec,pos parameters
     // Pass in trans,tpose,row,col,xvec,yvec,zvec,pos parameters
     for (int i=0; i<(int)_cg_transform_bind.size(); i++)
     for (int i=0; i<(int)_cg_transform_bind.size(); i++)
-      bind_cg_transform(_cg_transform_bind[i], m, gsg);
+      bind_cg_transform(_cg_transform_bind[i], gsg);
   }
   }
 #endif
 #endif
 }
 }
@@ -284,8 +287,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
             gsg->_current_texture->get_on_stages();
             gsg->_current_texture->get_on_stages();
           if (texslot < (int)active_stages.size()) {
           if (texslot < (int)active_stages.size()) {
             TextureStage *stage = active_stages[texslot];
             TextureStage *stage = active_stages[texslot];
-            const InternalName *slotname = stage->get_texcoord_name();
-            name = name->append(slotname->get_name());
+            name = name->append(stage->get_texcoord_name()->get_name());
           }
           }
         }
         }
         if (gsg->_vertex_data->get_array_info(name,
         if (gsg->_vertex_data->get_array_info(name,
@@ -309,42 +311,43 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLShaderContext::bind_cg_transform
 //     Function: GLShaderContext::bind_cg_transform
 //       Access: Public
 //       Access: Public
-//  Description: Should deallocate all system resources (such as
-//               vertex program handles or Cg contexts).
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 void CLP(ShaderContext)::
-bind_cg_transform(const ShaderTransBind &stb, ShaderMode *m, GSG *gsg)
+bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
 {
 {
   CPT(TransformState) src;
   CPT(TransformState) src;
   CPT(TransformState) rel;
   CPT(TransformState) rel;
   
   
-  if (stb.src_argindex < 0) {
-    if (stb.src_argindex == SHADER_arg_camera)
-      src = TransformState::make_identity();
-    else if (stb.src_argindex == SHADER_arg_model)
-      src = gsg->get_transform();
-    else
-      src = gsg->get_scene()->get_world_transform();
+  if (stb.src_name == InternalName::get_camera()) {
+    src = TransformState::make_identity();
+  } else if (stb.src_name == InternalName::get_model()) {
+    src = gsg->get_transform();
+  } else if (stb.src_name == InternalName::get_world()) {
+    src = gsg->get_scene()->get_world_transform();
   } else {
   } else {
-    if ((int)m->_args.size() > stb.src_argindex) {
-      ShaderModeArg *arg = &(m->_args[stb.src_argindex]);
-      if (arg->_type == ShaderModeArg::SAT_NODEPATH)
-        src = gsg->get_scene()->get_world_transform()->compose(arg->_nvalue.get_net_transform());
+    const ShaderInput *input = gsg->_target._shader->get_input(stb.src_name);
+    if (input->get_nodepath().is_empty()) {
+      src = gsg->get_scene()->get_world_transform();
+    } else {
+      src = gsg->get_scene()->get_world_transform()->
+        compose(input->get_nodepath().get_net_transform());
     }
     }
   }
   }
 
 
-  if (stb.rel_argindex < 0) {
-    if (stb.rel_argindex == SHADER_arg_camera)
-      rel = TransformState::make_identity();
-    else if (stb.rel_argindex == SHADER_arg_model)
-      rel = gsg->get_transform();
-    else
-      rel = gsg->get_scene()->get_world_transform();
+  if (stb.rel_name == InternalName::get_camera()) {
+    rel = TransformState::make_identity();
+  } else if (stb.rel_name == InternalName::get_model()) {
+    rel = gsg->get_transform();
+  } else if (stb.rel_name == InternalName::get_world()) {
+    rel = gsg->get_scene()->get_world_transform();
   } else {
   } else {
-    if ((int)m->_args.size() > stb.rel_argindex) {
-      ShaderModeArg *arg = &(m->_args[stb.rel_argindex]);
-      if (arg->_type == ShaderModeArg::SAT_NODEPATH)
-        rel = gsg->get_scene()->get_world_transform()->compose(arg->_nvalue.get_net_transform());
+    const ShaderInput *input = gsg->_target._shader->get_input(stb.rel_name);
+    if (input->get_nodepath().is_empty()) {
+      rel = gsg->get_scene()->get_world_transform();
+    } else {
+      rel = gsg->get_scene()->get_world_transform()->
+        compose(input->get_nodepath().get_net_transform());
     }
     }
   }
   }
   
   
@@ -526,7 +529,7 @@ errchk_cg_output(CGparameter p, const string &msg)
   const char *ts = cgGetTypeString(cgGetParameterType(p));
   const char *ts = cgGetTypeString(cgGetParameterType(p));
   
   
   string err;
   string err;
-  string fn = _shader->_file;
+  string fn = _shader_expansion->get_name();
   err = fn + ": " + msg + " (" + vstr + dstr + ts + " " + cgGetParameterName(p) + ")\n";
   err = fn + ": " + msg + " (" + vstr + dstr + ts + " " + cgGetParameterName(p) + ")\n";
   cerr << err << "\n";
   cerr << err << "\n";
 }
 }
@@ -656,14 +659,8 @@ compile_cg_parameter(CGparameter p)
     else if (pieces[0]=="col2") bind.trans_piece = SHADER_data_col2;
     else if (pieces[0]=="col2") bind.trans_piece = SHADER_data_col2;
     else if (pieces[0]=="col3") bind.trans_piece = SHADER_data_col3;
     else if (pieces[0]=="col3") bind.trans_piece = SHADER_data_col3;
 
 
-    if      (pieces[1] == "world")  bind.src_argindex = SHADER_arg_world;
-    else if (pieces[1] == "camera") bind.src_argindex = SHADER_arg_camera;
-    else if (pieces[1] == "model")  bind.src_argindex = SHADER_arg_model;
-    else bind.src_argindex = _shader->arg_index(pieces[1]);
-    if      (pieces[3] == "world")  bind.rel_argindex = SHADER_arg_world;
-    else if (pieces[3] == "camera") bind.rel_argindex = SHADER_arg_camera;
-    else if (pieces[3] == "model")  bind.rel_argindex = SHADER_arg_model;
-    else bind.rel_argindex = _shader->arg_index(pieces[3]);
+    bind.src_name = InternalName::make(pieces[1]);
+    bind.rel_name = InternalName::make(pieces[3]);
 
 
     if ((bind.trans_piece == SHADER_data_matrix)||(bind.trans_piece == SHADER_data_transpose)) {
     if ((bind.trans_piece == SHADER_data_matrix)||(bind.trans_piece == SHADER_data_transpose)) {
       if (!errchk_cg_parameter_type(p, CG_FLOAT4x4)) return false;
       if (!errchk_cg_parameter_type(p, CG_FLOAT4x4)) return false;
@@ -672,8 +669,8 @@ compile_cg_parameter(CGparameter p)
     }
     }
 
 
     _cg_parameter_bind.push_back(bind);
     _cg_parameter_bind.push_back(bind);
-    if ((bind.src_argindex == SHADER_arg_model) ||
-        (bind.rel_argindex == SHADER_arg_model)) {
+    if ((bind.src_name == InternalName::get_model()) ||
+        (bind.rel_name == InternalName::get_model())) {
       _cg_transform_bind.push_back(bind);
       _cg_transform_bind.push_back(bind);
     }
     }
     return true;
     return true;
@@ -692,17 +689,14 @@ compile_cg_parameter(CGparameter p)
     ShaderTransBind bind;
     ShaderTransBind bind;
     bind.parameter = p;
     bind.parameter = p;
     
     
-    if      (pieces[0]=="wstrans") { bind.rel_argindex = SHADER_arg_world;  bind.trans_piece = SHADER_data_matrix; }
-    else if (pieces[0]=="cstrans") { bind.rel_argindex = SHADER_arg_camera; bind.trans_piece = SHADER_data_matrix; }
-    else if (pieces[0]=="mstrans") { bind.rel_argindex = SHADER_arg_model;  bind.trans_piece = SHADER_data_matrix; }
-    else if (pieces[0]=="wspos")   { bind.rel_argindex = SHADER_arg_world;  bind.trans_piece = SHADER_data_row3; }
-    else if (pieces[0]=="cspos")   { bind.rel_argindex = SHADER_arg_camera; bind.trans_piece = SHADER_data_row3; }
-    else if (pieces[0]=="mspos")   { bind.rel_argindex = SHADER_arg_model;  bind.trans_piece = SHADER_data_row3; }
-    
-    if      (pieces[1] == "world")  bind.src_argindex = SHADER_arg_world;
-    else if (pieces[1] == "camera") bind.src_argindex = SHADER_arg_camera;
-    else if (pieces[1] == "model")  bind.src_argindex = SHADER_arg_model;
-    else bind.src_argindex = _shader->arg_index(pieces[1]);
+    if      (pieces[0]=="wstrans") { bind.rel_name = InternalName::get_world();  bind.trans_piece = SHADER_data_matrix; }
+    else if (pieces[0]=="cstrans") { bind.rel_name = InternalName::get_camera(); bind.trans_piece = SHADER_data_matrix; }
+    else if (pieces[0]=="mstrans") { bind.rel_name = InternalName::get_model();  bind.trans_piece = SHADER_data_matrix; }
+    else if (pieces[0]=="wspos")   { bind.rel_name = InternalName::get_world();  bind.trans_piece = SHADER_data_row3; }
+    else if (pieces[0]=="cspos")   { bind.rel_name = InternalName::get_camera(); bind.trans_piece = SHADER_data_row3; }
+    else if (pieces[0]=="mspos")   { bind.rel_name = InternalName::get_model();  bind.trans_piece = SHADER_data_row3; }
+
+    bind.src_name = InternalName::make(pieces[1]);
     
     
     if ((bind.trans_piece == SHADER_data_matrix)||(bind.trans_piece == SHADER_data_transpose)) {
     if ((bind.trans_piece == SHADER_data_matrix)||(bind.trans_piece == SHADER_data_transpose)) {
       if (!errchk_cg_parameter_type(p, CG_FLOAT4x4)) return false;
       if (!errchk_cg_parameter_type(p, CG_FLOAT4x4)) return false;
@@ -710,9 +704,10 @@ compile_cg_parameter(CGparameter p)
       if (!errchk_cg_parameter_type(p, CG_FLOAT4)) return false;
       if (!errchk_cg_parameter_type(p, CG_FLOAT4)) return false;
     }
     }
     _cg_parameter_bind.push_back(bind);
     _cg_parameter_bind.push_back(bind);
-    if ((bind.src_argindex == SHADER_arg_model) ||
-        (bind.rel_argindex == SHADER_arg_model))
+    if ((bind.src_name == InternalName::get_model()) ||
+        (bind.rel_name == InternalName::get_model())) {
       _cg_transform_bind.push_back(bind);
       _cg_transform_bind.push_back(bind);
+    }
     return true;
     return true;
   }
   }
 
 
@@ -760,7 +755,7 @@ compile_cg_parameter(CGparameter p)
       return false;
       return false;
     ShaderArgBind bind;
     ShaderArgBind bind;
     bind.parameter = p;
     bind.parameter = p;
-    bind.argindex = _shader->arg_index(pieces[1]);
+    bind.name = InternalName::make(pieces[1]);
     switch (cgGetParameterType(p)) {
     switch (cgGetParameterType(p)) {
     case CG_FLOAT4:    _cg_fbind.push_back(bind); break;
     case CG_FLOAT4:    _cg_fbind.push_back(bind); break;
     case CG_SAMPLER2D: _cg_tbind2d.push_back(bind); break;
     case CG_SAMPLER2D: _cg_tbind2d.push_back(bind); break;
@@ -772,17 +767,17 @@ compile_cg_parameter(CGparameter p)
     }
     }
     return true;
     return true;
   }
   }
-
+  
   if (pieces[0] == "l") {
   if (pieces[0] == "l") {
     // IMPLEMENT THE ERROR CHECKING
     // IMPLEMENT THE ERROR CHECKING
     return true; // Cg handles this automatically.
     return true; // Cg handles this automatically.
   }
   }
-
+  
   if (pieces[0] == "o") {
   if (pieces[0] == "o") {
     // IMPLEMENT THE ERROR CHECKING
     // IMPLEMENT THE ERROR CHECKING
     return true; // Cg handles this automatically.
     return true; // Cg handles this automatically.
   }
   }
-
+  
   errchk_cg_output(p, "unrecognized parameter name");
   errchk_cg_output(p, "unrecognized parameter name");
   return false;
   return false;
 }
 }

+ 11 - 9
panda/src/glstuff/glShaderContext_src.h

@@ -17,11 +17,13 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "pandabase.h"
 #include "pandabase.h"
-#include "shaderContext.h"
 #ifdef HAVE_CGGL
 #ifdef HAVE_CGGL
 #include "Cg/cgGL.h"
 #include "Cg/cgGL.h"
 #endif
 #endif
 #include "string_utils.h"
 #include "string_utils.h"
+#include "internalName.h"
+#include "shaderExpansion.h"
+#include "shaderContext.h"
 
 
 class CLP(GraphicsStateGuardian);
 class CLP(GraphicsStateGuardian);
 
 
@@ -32,15 +34,15 @@ class CLP(GraphicsStateGuardian);
 
 
 class EXPCL_GL CLP(ShaderContext): public ShaderContext {
 class EXPCL_GL CLP(ShaderContext): public ShaderContext {
 public:
 public:
-  CLP(ShaderContext)(Shader *s);
+  CLP(ShaderContext)(ShaderExpansion *s);
   ~CLP(ShaderContext)();
   ~CLP(ShaderContext)();
   typedef CLP(GraphicsStateGuardian) GSG;
   typedef CLP(GraphicsStateGuardian) GSG;
 
 
   INLINE bool valid(void);
   INLINE bool valid(void);
-  void bind(ShaderMode *mode, GSG *gsg);
+  void bind(GSG *gsg);
   void unbind();
   void unbind();
-  void issue_parameters(ShaderMode *mode, GSG *gsg);
-  void issue_transform(ShaderMode *mode, GSG *gsg);
+  void issue_parameters(GSG *gsg);
+  void issue_transform(GSG *gsg);
   void disable_shader_vertex_arrays(GSG *gsg);
   void disable_shader_vertex_arrays(GSG *gsg);
   void update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg);
   void update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg);
 
 
@@ -54,12 +56,12 @@ private:
   };
   };
   struct ShaderArgBind {
   struct ShaderArgBind {
     CGparameter parameter;
     CGparameter parameter;
-    int argindex;
+    PT(InternalName) name;
   };
   };
   struct ShaderTransBind {
   struct ShaderTransBind {
     CGparameter parameter;
     CGparameter parameter;
-    int src_argindex;
-    int rel_argindex;
+    PT(InternalName) src_name;
+    PT(InternalName) rel_name;
     int trans_piece;
     int trans_piece;
   };
   };
   struct ShaderVarying {
   struct ShaderVarying {
@@ -82,7 +84,7 @@ private:
   vector <ShaderTransBind> _cg_parameter_bind;
   vector <ShaderTransBind> _cg_parameter_bind;
   vector <ShaderVarying> _cg_varying;
   vector <ShaderVarying> _cg_varying;
   
   
-  void bind_cg_transform(const ShaderTransBind &stb, ShaderMode *m,
+  void bind_cg_transform(const ShaderTransBind &stb,
                          CLP(GraphicsStateGuardian) *gsg);
                          CLP(GraphicsStateGuardian) *gsg);
   
   
   bool compile_cg_parameter(CGparameter p);
   bool compile_cg_parameter(CGparameter p);

+ 2 - 3
panda/src/gobj/config_gobj.cxx

@@ -42,7 +42,7 @@
 #include "texture.h"
 #include "texture.h"
 #include "textureStage.h"
 #include "textureStage.h"
 #include "textureContext.h"
 #include "textureContext.h"
-#include "shader.h"
+#include "shaderExpansion.h"
 #include "shaderContext.h"
 #include "shaderContext.h"
 #include "transformBlendTable.h"
 #include "transformBlendTable.h"
 #include "transformTable.h"
 #include "transformTable.h"
@@ -249,7 +249,7 @@ ConfigureFn(config_gobj) {
   Texture::init_type();
   Texture::init_type();
   dDrawable::init_type();
   dDrawable::init_type();
   TextureStage::init_type();
   TextureStage::init_type();
-  Shader::init_type();
+  ShaderExpansion::init_type();
   ShaderContext::init_type();
   ShaderContext::init_type();
   TransformBlendTable::init_type();
   TransformBlendTable::init_type();
   TransformTable::init_type();
   TransformTable::init_type();
@@ -278,7 +278,6 @@ ConfigureFn(config_gobj) {
   MatrixLens::register_with_read_factory();
   MatrixLens::register_with_read_factory();
   PerspectiveLens::register_with_read_factory();
   PerspectiveLens::register_with_read_factory();
   SliderTable::register_with_read_factory();
   SliderTable::register_with_read_factory();
-  Shader::register_with_read_factory();
   Texture::register_with_read_factory();
   Texture::register_with_read_factory();
   TextureStage::register_with_read_factory();
   TextureStage::register_with_read_factory();
   TransformBlendTable::register_with_read_factory();
   TransformBlendTable::register_with_read_factory();

+ 1 - 1
panda/src/gobj/gobj_composite2.cxx

@@ -16,7 +16,7 @@
 #include "textureContext.cxx"
 #include "textureContext.cxx"
 #include "texturePool.cxx"
 #include "texturePool.cxx"
 #include "textureStage.cxx"
 #include "textureStage.cxx"
-#include "shader.cxx"
+#include "shaderExpansion.cxx"
 #include "shaderContext.cxx"
 #include "shaderContext.cxx"
 #include "transformBlend.cxx"
 #include "transformBlend.cxx"
 #include "transformBlendTable.cxx"
 #include "transformBlendTable.cxx"

+ 47 - 0
panda/src/gobj/internalName.I

@@ -375,6 +375,53 @@ get_index() {
   return _index;
   return _index;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: InternalName::get_world
+//       Access: Published, Static
+//  Description: Returns the standard InternalName "world".  This is
+//               used as a keyword in the shader subsystem.
+////////////////////////////////////////////////////////////////////
+INLINE PT(InternalName) InternalName::
+get_world() {
+  if (_world == (InternalName *)NULL) {
+    _world = InternalName::make("world");
+  }
+  return _world;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InternalName::get_camera
+//       Access: Published, Static
+//  Description: Returns the standard InternalName "camera".  This is
+//               used as a keyword in the shader subsystem.
+////////////////////////////////////////////////////////////////////
+INLINE PT(InternalName) InternalName::
+get_camera() {
+  if (_camera == (InternalName *)NULL) {
+    _camera = InternalName::make("camera");
+  }
+  return _camera;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InternalName::get_model
+//       Access: Published, Static
+//  Description: Returns the standard InternalName "model".  This is
+//               used as a keyword in the shader subsystem.
+////////////////////////////////////////////////////////////////////
+INLINE PT(InternalName) InternalName::
+get_model() {
+  if (_model == (InternalName *)NULL) {
+    _model = InternalName::make("model");
+  }
+  return _model;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InternalName::output operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
 INLINE ostream &
 INLINE ostream &
 operator << (ostream &out, const InternalName &tcn) {
 operator << (ostream &out, const InternalName &tcn) {
   tcn.output(out);
   tcn.output(out);

+ 3 - 0
panda/src/gobj/internalName.cxx

@@ -39,6 +39,9 @@ PT(InternalName) InternalName::_transform_blend;
 PT(InternalName) InternalName::_transform_weight;
 PT(InternalName) InternalName::_transform_weight;
 PT(InternalName) InternalName::_transform_index;
 PT(InternalName) InternalName::_transform_index;
 PT(InternalName) InternalName::_index;
 PT(InternalName) InternalName::_index;
+PT(InternalName) InternalName::_world;
+PT(InternalName) InternalName::_camera;
+PT(InternalName) InternalName::_model;
 
 
 TypeHandle InternalName::_type_handle;
 TypeHandle InternalName::_type_handle;
 TypeHandle InternalName::_texcoord_type_handle;
 TypeHandle InternalName::_texcoord_type_handle;

+ 6 - 0
panda/src/gobj/internalName.h

@@ -81,6 +81,9 @@ PUBLISHED:
   INLINE static PT(InternalName) get_transform_index();
   INLINE static PT(InternalName) get_transform_index();
   INLINE static PT(InternalName) get_morph(InternalName *column, const string &slider);
   INLINE static PT(InternalName) get_morph(InternalName *column, const string &slider);
   INLINE static PT(InternalName) get_index();
   INLINE static PT(InternalName) get_index();
+  INLINE static PT(InternalName) get_world();
+  INLINE static PT(InternalName) get_camera();
+  INLINE static PT(InternalName) get_model();
 
 
 private:
 private:
   PT(InternalName) _parent;
   PT(InternalName) _parent;
@@ -105,6 +108,9 @@ private:
   static PT(InternalName) _transform_weight;
   static PT(InternalName) _transform_weight;
   static PT(InternalName) _transform_index;
   static PT(InternalName) _transform_index;
   static PT(InternalName) _index;
   static PT(InternalName) _index;
+  static PT(InternalName) _world;
+  static PT(InternalName) _camera;
+  static PT(InternalName) _model;
   
   
 public:
 public:
   // Datagram stuff
   // Datagram stuff

+ 13 - 13
panda/src/gobj/preparedGraphicsObjects.cxx

@@ -24,7 +24,7 @@
 #include "geom.h"
 #include "geom.h"
 #include "geomVertexArrayData.h"
 #include "geomVertexArrayData.h"
 #include "geomPrimitive.h"
 #include "geomPrimitive.h"
-#include "shader.h"
+#include "shaderExpansion.h"
 #include "mutexHolder.h"
 #include "mutexHolder.h"
 
 
 PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage");
 PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage");
@@ -83,7 +83,7 @@ PreparedGraphicsObjects::
        sci != _prepared_shaders.end();
        sci != _prepared_shaders.end();
        ++sci) {
        ++sci) {
     ShaderContext *sc = (*sci);
     ShaderContext *sc = (*sci);
-    sc->_shader->clear_prepared(this);
+    sc->_shader_expansion->clear_prepared(this);
   }
   }
 
 
   _prepared_shaders.clear();
   _prepared_shaders.clear();
@@ -410,10 +410,10 @@ prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg) {
 //               do this (presumably at the next frame).
 //               do this (presumably at the next frame).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PreparedGraphicsObjects::
 void PreparedGraphicsObjects::
-enqueue_shader(Shader *shader) {
+enqueue_shader(ShaderExpansion *se) {
   MutexHolder holder(_lock);
   MutexHolder holder(_lock);
 
 
-  _enqueued_shaders.insert(shader);
+  _enqueued_shaders.insert(se);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -431,10 +431,10 @@ enqueue_shader(Shader *shader) {
 //               queued.
 //               queued.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool PreparedGraphicsObjects::
 bool PreparedGraphicsObjects::
-dequeue_shader(Shader *shader) {
+dequeue_shader(ShaderExpansion *se) {
   MutexHolder holder(_lock);
   MutexHolder holder(_lock);
 
 
-  EnqueuedShaders::iterator qi = _enqueued_shaders.find(shader);
+  EnqueuedShaders::iterator qi = _enqueued_shaders.find(se);
   if (qi != _enqueued_shaders.end()) {
   if (qi != _enqueued_shaders.end()) {
     _enqueued_shaders.erase(qi);
     _enqueued_shaders.erase(qi);
     return true;
     return true;
@@ -459,12 +459,12 @@ void PreparedGraphicsObjects::
 release_shader(ShaderContext *sc) {
 release_shader(ShaderContext *sc) {
   MutexHolder holder(_lock);
   MutexHolder holder(_lock);
 
 
-  sc->_shader->clear_prepared(this);
+  sc->_shader_expansion->clear_prepared(this);
 
 
   // We have to set the Shader pointer to NULL at this point, since
   // We have to set the Shader pointer to NULL at this point, since
   // the Shader itself might destruct at any time after it has been
   // the Shader itself might destruct at any time after it has been
   // released.
   // released.
-  sc->_shader = (Shader *)NULL;
+  sc->_shader_expansion = (ShaderExpansion *)NULL;
 
 
   bool removed = (_prepared_shaders.erase(sc) != 0);
   bool removed = (_prepared_shaders.erase(sc) != 0);
   nassertv(removed);
   nassertv(removed);
@@ -491,8 +491,8 @@ release_all_shaders() {
        sci != _prepared_shaders.end();
        sci != _prepared_shaders.end();
        ++sci) {
        ++sci) {
     ShaderContext *sc = (*sci);
     ShaderContext *sc = (*sci);
-    sc->_shader->clear_prepared(this);
-    sc->_shader = (Shader *)NULL;
+    sc->_shader_expansion->clear_prepared(this);
+    sc->_shader_expansion = (ShaderExpansion *)NULL;
 
 
     _released_shaders.insert(sc);
     _released_shaders.insert(sc);
   }
   }
@@ -525,14 +525,14 @@ release_all_shaders() {
 //               ShaderContext will be deleted.
 //               ShaderContext will be deleted.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 ShaderContext *PreparedGraphicsObjects::
 ShaderContext *PreparedGraphicsObjects::
-prepare_shader_now(Shader *shader, GraphicsStateGuardianBase *gsg) {
+prepare_shader_now(ShaderExpansion *se, GraphicsStateGuardianBase *gsg) {
   MutexHolder holder(_lock);
   MutexHolder holder(_lock);
 
 
   // Ask the GSG to create a brand new ShaderContext.  There might
   // Ask the GSG to create a brand new ShaderContext.  There might
   // be several GSG's sharing the same set of shaders; if so, it
   // be several GSG's sharing the same set of shaders; if so, it
   // doesn't matter which of them creates the context (since they're
   // doesn't matter which of them creates the context (since they're
   // all shared anyway).
   // all shared anyway).
-  ShaderContext *sc = gsg->prepare_shader(shader);
+  ShaderContext *sc = gsg->prepare_shader(se);
 
 
   if (sc != (ShaderContext *)NULL) {
   if (sc != (ShaderContext *)NULL) {
     bool prepared = _prepared_shaders.insert(sc).second;
     bool prepared = _prepared_shaders.insert(sc).second;
@@ -930,7 +930,7 @@ update(GraphicsStateGuardianBase *gsg) {
   for (qsi = _enqueued_shaders.begin();
   for (qsi = _enqueued_shaders.begin();
        qsi != _enqueued_shaders.end();
        qsi != _enqueued_shaders.end();
        ++qsi) {
        ++qsi) {
-    Shader *shader = (*qsi);
+    ShaderExpansion *shader = (*qsi);
     shader->prepare_now(this, gsg);
     shader->prepare_now(this, gsg);
   }
   }
 
 

+ 5 - 5
panda/src/gobj/preparedGraphicsObjects.h

@@ -25,7 +25,7 @@
 #include "geom.h"
 #include "geom.h"
 #include "geomVertexArrayData.h"
 #include "geomVertexArrayData.h"
 #include "geomPrimitive.h"
 #include "geomPrimitive.h"
-#include "shader.h"
+#include "shaderExpansion.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "pStatCollector.h"
 #include "pStatCollector.h"
 #include "pset.h"
 #include "pset.h"
@@ -78,12 +78,12 @@ public:
 
 
   GeomContext *prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg);
   GeomContext *prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg);
 
 
-  void enqueue_shader(Shader *shader);
-  bool dequeue_shader(Shader *shader);
+  void enqueue_shader(ShaderExpansion *shader);
+  bool dequeue_shader(ShaderExpansion *shader);
   void release_shader(ShaderContext *sc);
   void release_shader(ShaderContext *sc);
   int release_all_shaders();
   int release_all_shaders();
 
 
-  ShaderContext *prepare_shader_now(Shader *shader, GraphicsStateGuardianBase *gsg);
+  ShaderContext *prepare_shader_now(ShaderExpansion *shader, GraphicsStateGuardianBase *gsg);
 
 
   void enqueue_vertex_buffer(GeomVertexArrayData *data);
   void enqueue_vertex_buffer(GeomVertexArrayData *data);
   bool dequeue_vertex_buffer(GeomVertexArrayData *data);
   bool dequeue_vertex_buffer(GeomVertexArrayData *data);
@@ -111,7 +111,7 @@ private:
   typedef phash_set<GeomContext *, pointer_hash> Geoms;
   typedef phash_set<GeomContext *, pointer_hash> Geoms;
   typedef phash_set< PT(Geom) > EnqueuedGeoms;
   typedef phash_set< PT(Geom) > EnqueuedGeoms;
   typedef phash_set<ShaderContext *, pointer_hash> Shaders;
   typedef phash_set<ShaderContext *, pointer_hash> Shaders;
-  typedef phash_set< PT(Shader) > EnqueuedShaders;
+  typedef phash_set< PT(ShaderExpansion) > EnqueuedShaders;
   typedef phash_set<VertexBufferContext *, pointer_hash> VertexBuffers;
   typedef phash_set<VertexBufferContext *, pointer_hash> VertexBuffers;
   typedef phash_set< PT(GeomVertexArrayData) > EnqueuedVertexBuffers;
   typedef phash_set< PT(GeomVertexArrayData) > EnqueuedVertexBuffers;
   typedef phash_set<IndexBufferContext *, pointer_hash> IndexBuffers;
   typedef phash_set<IndexBufferContext *, pointer_hash> IndexBuffers;

+ 2 - 2
panda/src/gobj/shaderContext.I

@@ -22,8 +22,8 @@
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE ShaderContext::
 INLINE ShaderContext::
-ShaderContext(Shader *s) :
-  _shader(s)
+ShaderContext(ShaderExpansion *se) :
+  _shader_expansion(se)
 {
 {
 }
 }
 
 

+ 3 - 8
panda/src/gobj/shaderContext.h

@@ -22,7 +22,7 @@
 #include "pandabase.h"
 #include "pandabase.h"
 #include "internalName.h"
 #include "internalName.h"
 #include "savedContext.h"
 #include "savedContext.h"
-#include "shader.h"
+#include "shaderExpansion.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : ShaderContext
 //       Class : ShaderContext
@@ -38,9 +38,9 @@
 
 
 class EXPCL_PANDA ShaderContext: public SavedContext {
 class EXPCL_PANDA ShaderContext: public SavedContext {
 public:
 public:
-  INLINE ShaderContext(Shader *shader);
+  INLINE ShaderContext(ShaderExpansion *se);
   
   
-  Shader *_shader;
+  ShaderExpansion *_shader_expansion;
   
   
 public:
 public:
   // The following declarations represent useful routines
   // The following declarations represent useful routines
@@ -51,11 +51,6 @@ public:
     SHADER_type_frag=1,
     SHADER_type_frag=1,
     SHADER_type_both=2,
     SHADER_type_both=2,
   };
   };
-  enum {
-    SHADER_arg_world = -1,
-    SHADER_arg_camera = -2,
-    SHADER_arg_model = -3,
-  };
   enum {
   enum {
     SHADER_data_matrix,
     SHADER_data_matrix,
     SHADER_data_transpose,
     SHADER_data_transpose,

+ 11 - 11
panda/src/gobj/shader.I → panda/src/gobj/shaderExpansion.I

@@ -1,4 +1,4 @@
-// Filename: shader.I
+// Filename: shaderExpansion.I
 // Heavily Modified:  jyelon (Sep05)
 // Heavily Modified:  jyelon (Sep05)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -17,22 +17,22 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//  Function: Shader::get_text
+//  Function: ShaderExpansion::get_name
 //  Access: Public
 //  Access: Public
-//  Description: Return the shader's text.
+//  Description: Return the ShaderExpansion's text.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE const string &Shader::
-get_text() {
-  return _text;
+INLINE const string &ShaderExpansion::
+get_name() const {
+  return _name;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//  Function: Shader::get_file
+//  Function: ShaderExpansion::get_text
 //  Access: Public
 //  Access: Public
-//  Description: Return the shader's filename, or null string.
+//  Description: Return the ShaderExpansion's text.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE const Filename &Shader::
-get_file() {
-  return _file;
+INLINE const string &ShaderExpansion::
+get_text() const {
+  return _text;
 }
 }
 
 

+ 62 - 65
panda/src/gobj/shader.cxx → panda/src/gobj/shaderExpansion.cxx

@@ -1,5 +1,5 @@
-// Filename: shader.cxx
-// Created by: jyelon (Sep05)
+// Filename: shaderExpansion.cxx
+// Created by: jyelon (01Sep05)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //
 //
@@ -17,55 +17,76 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "pandabase.h"
 #include "pandabase.h"
-#include "shader.h"
+#include "shaderExpansion.h"
 
 
-TypeHandle Shader::_type_handle;
+TypeHandle ShaderExpansion::_type_handle;
+ShaderExpansion::ExpansionCache ShaderExpansion::_expansion_cache;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//  Function: Shader::Constructor
-//  Access: Public
-//  Description: Construct a Shader.
+//  Function: ShaderExpansion::Constructor
+//  Access: Private
+//  Description: Construct a ShaderExpansion.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-Shader::
-Shader(const string &text, const string &file) {
-  _text = text;
-  _file = file;
+ShaderExpansion::
+ShaderExpansion() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Shader::Destructor
+//     Function: ShaderExpansion::Destructor
 //       Access: Public
 //       Access: Public
 //  Description: Delete the compiled code, if it exists.
 //  Description: Delete the compiled code, if it exists.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-Shader::
-~Shader() {
+ShaderExpansion::
+~ShaderExpansion() {
   release_all();
   release_all();
+  _expansion_cache.erase(ExpansionKey(_name,_text));
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Shader::parse_init
+//     Function: ShaderExpansion::make
+//       Access: Public, Static
+//  Description: Create a shader expansion (or reuse one from cache)
+////////////////////////////////////////////////////////////////////
+PT(ShaderExpansion) ShaderExpansion::
+make(const string &name, const string &text) {
+  ExpansionKey key(name, text);
+  ExpansionCache::const_iterator i = _expansion_cache.find(key);
+  if (i != _expansion_cache.end()) {
+    return i->second;
+  }
+  ShaderExpansion *result = new ShaderExpansion();
+  result->_name = name;
+  result->_text = text;
+  _expansion_cache.insert(ExpansionCache::value_type(key,result));
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderExpansion::parse_init
 //       Access: Public
 //       Access: Public
 //  Description: Set a 'parse pointer' to the beginning of the shader.
 //  Description: Set a 'parse pointer' to the beginning of the shader.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void Shader::
+void ShaderExpansion::
 parse_init() {
 parse_init() {
   _parse = 0;
   _parse = 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Shader::parse_line
+//     Function: ShaderExpansion::parse_line
 //       Access: Public
 //       Access: Public
 //  Description: Parse a line of text. If 'lt' is true, trim blanks
 //  Description: Parse a line of text. If 'lt' is true, trim blanks
 //               from the left end of the line. If 'rt' is true, trim
 //               from the left end of the line. If 'rt' is true, trim
 //               blanks from the right end (the newline is always
 //               blanks from the right end (the newline is always
 //               trimmed).
 //               trimmed).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void Shader::
+void ShaderExpansion::
 parse_line(string &result, bool lt, bool rt) {
 parse_line(string &result, bool lt, bool rt) {
   int len = _text.size();
   int len = _text.size();
   int head = _parse;
   int head = _parse;
   int tail = head;
   int tail = head;
-  while ((tail < len) && (_text[tail] != '\n')) tail++;
+  while ((tail < len) && (_text[tail] != '\n')) {
+    tail++;
+  }
   if (tail < len) {
   if (tail < len) {
     _parse = tail+1;
     _parse = tail+1;
   } else {
   } else {
@@ -79,19 +100,19 @@ parse_line(string &result, bool lt, bool rt) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Shader::parse_upto
+//     Function: ShaderExpansion::parse_upto
 //       Access: Public
 //       Access: Public
 //  Description: Parse lines until you read a line that matches the
 //  Description: Parse lines until you read a line that matches the
 //               specified pattern.  Returns all the preceding lines,
 //               specified pattern.  Returns all the preceding lines,
 //               and if the include flag is set, returns the final
 //               and if the include flag is set, returns the final
 //               line as well.
 //               line as well.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void Shader::
+void ShaderExpansion::
 parse_upto(string &result, string pattern, bool include) {
 parse_upto(string &result, string pattern, bool include) {
   GlobPattern endpat(pattern);
   GlobPattern endpat(pattern);
   int start = _parse;
   int start = _parse;
   int last = _parse;
   int last = _parse;
-  while (_parse < (int)_text.size()) {
+  while (_parse < (int)(_text.size())) {
     string t;
     string t;
     parse_line(t, true, true);
     parse_line(t, true, true);
     if (endpat.matches(t)) break;
     if (endpat.matches(t)) break;
@@ -105,57 +126,43 @@ parse_upto(string &result, string pattern, bool include) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Shader::parse_rest
+//     Function: ShaderExpansion::parse_rest
 //       Access: Public
 //       Access: Public
 //  Description: Returns the rest of the text from the current
 //  Description: Returns the rest of the text from the current
 //               parse location.
 //               parse location.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void Shader::
+void ShaderExpansion::
 parse_rest(string &result) {
 parse_rest(string &result) {
   result = _text.substr(_parse, _text.size() - _parse);
   result = _text.substr(_parse, _text.size() - _parse);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Shader::parse_lineno
+//     Function: ShaderExpansion::parse_lineno
 //       Access: Public
 //       Access: Public
 //  Description: Returns the line number of the current parse pointer.
 //  Description: Returns the line number of the current parse pointer.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-int Shader::
+int ShaderExpansion::
 parse_lineno() {
 parse_lineno() {
   int result = 1;
   int result = 1;
-  for (int i=0; i<_parse; i++)
+  for (int i=0; i<_parse; i++) {
     if (_text[i] == '\n') result += 1;
     if (_text[i] == '\n') result += 1;
+  }
   return result;
   return result;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Shader::parse_eof
+//     Function: ShaderExpansion::parse_eof
 //       Access: Public
 //       Access: Public
 //  Description: Returns true if the parse pointer is at the end of
 //  Description: Returns true if the parse pointer is at the end of
 //               the shader.
 //               the shader.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-bool Shader::
+bool ShaderExpansion::
 parse_eof() {
 parse_eof() {
   return (int)_text.size() == _parse;
   return (int)_text.size() == _parse;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//  Function: Shader::arg_index
-//  Access: Public
-//  Description: Allocates an integer index to the given
-//               shader parameter name.
-////////////////////////////////////////////////////////////////////
-int Shader::
-arg_index(const string &id) {
-  for (int i=0; i<(int)(_args.size()); i++)
-    if (_args[i] == id)
-      return i;
-  _args.push_back(id);
-  return _args.size() - 1;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Shader::prepare
+//     Function: ShaderExpansion::prepare
 //       Access: Published
 //       Access: Published
 //  Description: Indicates that the shader should be enqueued to be
 //  Description: Indicates that the shader should be enqueued to be
 //               prepared in the indicated prepared_objects at the
 //               prepared in the indicated prepared_objects at the
@@ -166,19 +173,19 @@ arg_index(const string &id) {
 //               Use this function instead of prepare_now() to preload
 //               Use this function instead of prepare_now() to preload
 //               textures from a user interface standpoint.
 //               textures from a user interface standpoint.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void Shader::
+void ShaderExpansion::
 prepare(PreparedGraphicsObjects *prepared_objects) {
 prepare(PreparedGraphicsObjects *prepared_objects) {
   prepared_objects->enqueue_shader(this);
   prepared_objects->enqueue_shader(this);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Shader::release
+//     Function: ShaderExpansion::release
 //       Access: Published
 //       Access: Published
 //  Description: Frees the texture context only on the indicated object,
 //  Description: Frees the texture context only on the indicated object,
 //               if it exists there.  Returns true if it was released,
 //               if it exists there.  Returns true if it was released,
 //               false if it had not been prepared.
 //               false if it had not been prepared.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-bool Shader::
+bool ShaderExpansion::
 release(PreparedGraphicsObjects *prepared_objects) {
 release(PreparedGraphicsObjects *prepared_objects) {
   Contexts::iterator ci;
   Contexts::iterator ci;
   ci = _contexts.find(prepared_objects);
   ci = _contexts.find(prepared_objects);
@@ -197,7 +204,7 @@ release(PreparedGraphicsObjects *prepared_objects) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Shader::prepare_now
+//     Function: ShaderExpansion::prepare_now
 //       Access: Public
 //       Access: Public
 //  Description: Creates a context for the texture on the particular
 //  Description: Creates a context for the texture on the particular
 //               GSG, if it does not already exist.  Returns the new
 //               GSG, if it does not already exist.  Returns the new
@@ -212,7 +219,7 @@ release(PreparedGraphicsObjects *prepared_objects) {
 //               explicitly prepared by the user before it may be
 //               explicitly prepared by the user before it may be
 //               rendered.
 //               rendered.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-ShaderContext *Shader::
+ShaderContext *ShaderExpansion::
 prepare_now(PreparedGraphicsObjects *prepared_objects, 
 prepare_now(PreparedGraphicsObjects *prepared_objects, 
             GraphicsStateGuardianBase *gsg) {
             GraphicsStateGuardianBase *gsg) {
   Contexts::const_iterator ci;
   Contexts::const_iterator ci;
@@ -228,15 +235,15 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Shader::clear_prepared
+//     Function: ShaderExpansion::clear_prepared
 //       Access: Private
 //       Access: Private
 //  Description: Removes the indicated PreparedGraphicsObjects table
 //  Description: Removes the indicated PreparedGraphicsObjects table
-//               from the Shader's table, without actually releasing
+//               from the ShaderExpansion's table, without actually releasing
 //               the texture.  This is intended to be called only from
 //               the texture.  This is intended to be called only from
 //               PreparedGraphicsObjects::release_texture(); it should
 //               PreparedGraphicsObjects::release_texture(); it should
 //               never be called by user code.
 //               never be called by user code.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void Shader::
+void ShaderExpansion::
 clear_prepared(PreparedGraphicsObjects *prepared_objects) {
 clear_prepared(PreparedGraphicsObjects *prepared_objects) {
   Contexts::iterator ci;
   Contexts::iterator ci;
   ci = _contexts.find(prepared_objects);
   ci = _contexts.find(prepared_objects);
@@ -250,13 +257,13 @@ clear_prepared(PreparedGraphicsObjects *prepared_objects) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: Shader::release_all
+//     Function: ShaderExpansion::release_all
 //       Access: Published
 //       Access: Published
 //  Description: Frees the context allocated on all objects for which
 //  Description: Frees the context allocated on all objects for which
 //               the texture has been declared.  Returns the number of
 //               the texture has been declared.  Returns the number of
 //               contexts which have been freed.
 //               contexts which have been freed.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-int Shader::
+int ShaderExpansion::
 release_all() {
 release_all() {
   // We have to traverse a copy of the _contexts list, because the
   // We have to traverse a copy of the _contexts list, because the
   // PreparedGraphicsObjects object will call clear_prepared() in response
   // PreparedGraphicsObjects object will call clear_prepared() in response
@@ -281,13 +288,3 @@ release_all() {
   return num_freed;
   return num_freed;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: Shader::register_with_read_factory
-//       Access: Public, Static
-//  Description: Factory method to generate a Shader object
-////////////////////////////////////////////////////////////////////
-void Shader::
-register_with_read_factory() {
-  // IMPLEMENT ME
-}
-

+ 30 - 46
panda/src/gobj/shader.h → panda/src/gobj/shaderExpansion.h

@@ -1,4 +1,4 @@
-// Filename: shader.h
+// Filename: shaderExpansion.h
 // Created by:  jyelon (01Sep05)
 // Created by:  jyelon (01Sep05)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -16,19 +16,8 @@
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
-////////////////////////////////////////////////////////////////////
-//
-// Current Loose Ends:
-//   - BAM reading/writing not implemented on most classes.
-//   - ShaderPool not implemented.
-//   - compilation of shaders for OpenGL not implemented.
-//   - compilation of shaders for DirectX8 not implemented.
-//   - compilation of shaders for DirectX9 not implemented.
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef SHADER_H
-#define SHADER_H
+#ifndef SHADEREXPANSION_H
+#define SHADEREXPANSION_H
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 #include "typedWritableReferenceCount.h"
 #include "typedWritableReferenceCount.h"
@@ -37,31 +26,27 @@
 #include "internalName.h"
 #include "internalName.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//       Class : Shader
-//      Summary: The Shader object contains the string which 
-//               is the shader's text, a filename that indicates
-//               where the shader came from (optional), and an
-//               argument-name to argument-index allocator.  The
-//               allocator is there so that all the Shader and
-//               ShaderContext objects associated with this Shader
-//               can refer to arguments by index instead of by name,
-//               which could make the bind process significantly
-//               faster.
+//       Class : ShaderExpansion
+//      Summary: A shader can contain context-sensitive macros.
+//               A ShaderExpansion is the output you get when you
+//               run the macro preprocessor on a shader.
+//               The ShaderExpansion contains the shader's 
+//               macroexpanded text, and a map of ShaderContext
+//               objects.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
-class EXPCL_PANDA Shader: public TypedWritableReferenceCount {
+class EXPCL_PANDA ShaderExpansion: public TypedReferenceCount {
 
 
 PUBLISHED:
 PUBLISHED:
-  Shader(const string &text, const string &file);
-  ~Shader();
-
-  INLINE const string   &get_text();
-  INLINE const Filename &get_file();
+  static PT(ShaderExpansion) make(const string &name, const string &body);
+  
+  INLINE const string &get_name() const;
+  INLINE const string &get_text() const;
   
   
   void prepare(PreparedGraphicsObjects *prepared_objects);
   void prepare(PreparedGraphicsObjects *prepared_objects);
   bool release(PreparedGraphicsObjects *prepared_objects);
   bool release(PreparedGraphicsObjects *prepared_objects);
   int release_all();
   int release_all();
-
+  
 PUBLISHED:
 PUBLISHED:
   // These routines help split the shader into sections,
   // These routines help split the shader into sections,
   // for those shader implementations that need to do so.
   // for those shader implementations that need to do so.
@@ -73,28 +58,27 @@ PUBLISHED:
   bool parse_eof();
   bool parse_eof();
   
   
 public:
 public:
+  ~ShaderExpansion();
 
 
-  INLINE int arg_count();
-  int        arg_index(const string &id);
-
+  string         _name;
   string         _text;
   string         _text;
-  Filename       _file;
   int            _parse;
   int            _parse;
-  vector<string> _args;
   
   
-  typedef pmap<PreparedGraphicsObjects *, ShaderContext *> Contexts;
-  Contexts _contexts;
-
-  static void register_with_read_factory();
+  typedef pair < string, string > ExpansionKey;
+  typedef pmap < ExpansionKey, ShaderExpansion * > ExpansionCache;
+  static ExpansionCache _expansion_cache;
 
 
   friend class ShaderContext;
   friend class ShaderContext;
   friend class PreparedGraphicsObjects;
   friend class PreparedGraphicsObjects;
 
 
+  typedef pmap <PreparedGraphicsObjects *, ShaderContext *> Contexts;
+  Contexts _contexts;
+  
   ShaderContext *prepare_now(PreparedGraphicsObjects *prepared_objects, 
   ShaderContext *prepare_now(PreparedGraphicsObjects *prepared_objects, 
                              GraphicsStateGuardianBase *gsg);
                              GraphicsStateGuardianBase *gsg);
-
+  
 private:  
 private:  
-  void parse();
+  ShaderExpansion();
   void clear_prepared(PreparedGraphicsObjects *prepared_objects);
   void clear_prepared(PreparedGraphicsObjects *prepared_objects);
 
 
 public:
 public:
@@ -102,9 +86,9 @@ public:
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedWritableReferenceCount::init_type();
-    register_type(_type_handle, "Shader",
-                  TypedWritableReferenceCount::get_class_type());
+    TypedReferenceCount::init_type();
+    register_type(_type_handle, "ShaderExpansion",
+                  TypedReferenceCount::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();
@@ -115,6 +99,6 @@ private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
 };
 };
 
 
-#include "shader.I"
+#include "shaderExpansion.I"
 
 
 #endif
 #endif

+ 2 - 4
panda/src/gsgbase/graphicsStateGuardianBase.h

@@ -61,9 +61,8 @@ class PreparedGraphicsObjects;
 class GraphicsOutput;
 class GraphicsOutput;
 class Texture;
 class Texture;
 class TextureContext;
 class TextureContext;
-class Shader;
 class ShaderContext;
 class ShaderContext;
-class ShaderMode;
+class ShaderExpansion;
 class RenderState;
 class RenderState;
 class TransformState;
 class TransformState;
 class Material;
 class Material;
@@ -90,7 +89,6 @@ class ShadeModelAttrib;
 class TransparencyAttrib;
 class TransparencyAttrib;
 class FogAttrib;
 class FogAttrib;
 class DepthOffsetAttrib;
 class DepthOffsetAttrib;
-class ShaderAttrib;
 
 
 class PointLight;
 class PointLight;
 class DirectionalLight;
 class DirectionalLight;
@@ -139,7 +137,7 @@ public:
   virtual GeomContext *prepare_geom(Geom *geom)=0;
   virtual GeomContext *prepare_geom(Geom *geom)=0;
   virtual void release_geom(GeomContext *gc)=0;
   virtual void release_geom(GeomContext *gc)=0;
 
 
-  virtual ShaderContext *prepare_shader(Shader *shader)=0;
+  virtual ShaderContext *prepare_shader(ShaderExpansion *shader)=0;
   virtual void release_shader(ShaderContext *sc)=0;
   virtual void release_shader(ShaderContext *sc)=0;
   
   
   virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data)=0;
   virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data)=0;

+ 2 - 3
panda/src/pgraph/alphaTestAttrib.cxx

@@ -97,9 +97,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AlphaTestAttrib::store_into_slot
 //     Function: AlphaTestAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AlphaTestAttrib::
 void AlphaTestAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/antialiasAttrib.cxx

@@ -209,9 +209,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AntialiasAttrib::store_into_slot
 //     Function: AntialiasAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AntialiasAttrib::
 void AntialiasAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/clipPlaneAttrib.cxx

@@ -885,9 +885,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ClipPlaneAttrib::store_into_slot
 //     Function: ClipPlaneAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ClipPlaneAttrib::
 void ClipPlaneAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/colorAttrib.cxx

@@ -135,9 +135,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorAttrib::store_into_slot
 //     Function: ColorAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ColorAttrib::
 void ColorAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/colorBlendAttrib.cxx

@@ -142,9 +142,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorBlendAttrib::store_into_slot
 //     Function: ColorBlendAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ColorBlendAttrib::
 void ColorBlendAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/colorScaleAttrib.cxx

@@ -260,9 +260,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorScaleAttrib::store_into_slot
 //     Function: ColorScaleAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ColorScaleAttrib::
 void ColorScaleAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/colorWriteAttrib.cxx

@@ -97,9 +97,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ColorWriteAttrib::store_into_slot
 //     Function: ColorWriteAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ColorWriteAttrib::
 void ColorWriteAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 6 - 3
panda/src/pgraph/config_pgraph.cxx

@@ -80,8 +80,9 @@
 #include "selectiveChildNode.h"
 #include "selectiveChildNode.h"
 #include "sequenceNode.h"
 #include "sequenceNode.h"
 #include "shadeModelAttrib.h"
 #include "shadeModelAttrib.h"
-#include "shaderMode.h"
+#include "shaderInput.h"
 #include "shaderAttrib.h"
 #include "shaderAttrib.h"
+#include "shader.h"
 #include "showBoundsEffect.h"
 #include "showBoundsEffect.h"
 #include "spotlight.h"
 #include "spotlight.h"
 #include "stateMunger.h"
 #include "stateMunger.h"
@@ -321,8 +322,9 @@ init_libpgraph() {
   SelectiveChildNode::init_type();
   SelectiveChildNode::init_type();
   SequenceNode::init_type();
   SequenceNode::init_type();
   ShadeModelAttrib::init_type();
   ShadeModelAttrib::init_type();
-  ShaderMode::init_type();
+  ShaderInput::init_type();
   ShaderAttrib::init_type();
   ShaderAttrib::init_type();
+  Shader::init_type();
   ShowBoundsEffect::init_type();
   ShowBoundsEffect::init_type();
   Spotlight::init_type();
   Spotlight::init_type();
   StateMunger::init_type();
   StateMunger::init_type();
@@ -379,8 +381,9 @@ init_libpgraph() {
   RenderState::register_with_read_factory();
   RenderState::register_with_read_factory();
   SequenceNode::register_with_read_factory();
   SequenceNode::register_with_read_factory();
   ShadeModelAttrib::register_with_read_factory();
   ShadeModelAttrib::register_with_read_factory();
-  ShaderMode::register_with_read_factory();
+  ShaderInput::register_with_read_factory();
   ShaderAttrib::register_with_read_factory();
   ShaderAttrib::register_with_read_factory();
+  Shader::register_with_read_factory();
   ShowBoundsEffect::register_with_read_factory();
   ShowBoundsEffect::register_with_read_factory();
   Spotlight::register_with_read_factory();
   Spotlight::register_with_read_factory();
   SwitchNode::register_with_read_factory();
   SwitchNode::register_with_read_factory();

+ 2 - 3
panda/src/pgraph/cullBinAttrib.cxx

@@ -103,9 +103,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CullBinAttrib::store_into_slot
 //     Function: CullBinAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CullBinAttrib::
 void CullBinAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/cullFaceAttrib.cxx

@@ -246,9 +246,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CullFaceAttrib::store_into_slot
 //     Function: CullFaceAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CullFaceAttrib::
 void CullFaceAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/depthOffsetAttrib.cxx

@@ -137,9 +137,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthOffsetAttrib::store_into_slot
 //     Function: DepthOffsetAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void DepthOffsetAttrib::
 void DepthOffsetAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/depthTestAttrib.cxx

@@ -90,9 +90,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthTestAttrib::store_into_slot
 //     Function: DepthTestAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void DepthTestAttrib::
 void DepthTestAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/depthWriteAttrib.cxx

@@ -97,9 +97,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DepthWriteAttrib::store_into_slot
 //     Function: DepthWriteAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void DepthWriteAttrib::
 void DepthWriteAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/fogAttrib.cxx

@@ -114,9 +114,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: FogAttrib::store_into_slot
 //     Function: FogAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void FogAttrib::
 void FogAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/lightAttrib.cxx

@@ -864,9 +864,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: LightAttrib::store_into_slot
 //     Function: LightAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void LightAttrib::
 void LightAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/materialAttrib.cxx

@@ -114,9 +114,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MaterialAttrib::store_into_slot
 //     Function: MaterialAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void MaterialAttrib::
 void MaterialAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 226 - 0
panda/src/pgraph/nodePath.cxx

@@ -37,6 +37,7 @@
 #include "alphaTestAttrib.h"
 #include "alphaTestAttrib.h"
 #include "depthTestAttrib.h"
 #include "depthTestAttrib.h"
 #include "depthWriteAttrib.h"
 #include "depthWriteAttrib.h"
+#include "shaderAttrib.h"
 #include "billboardEffect.h"
 #include "billboardEffect.h"
 #include "compassEffect.h"
 #include "compassEffect.h"
 #include "showBoundsEffect.h"
 #include "showBoundsEffect.h"
@@ -56,6 +57,8 @@
 #include "textureCollection.h"
 #include "textureCollection.h"
 #include "textureStageCollection.h"
 #include "textureStageCollection.h"
 #include "globPattern.h"
 #include "globPattern.h"
+#include "shader.h"
+#include "shaderInput.h"
 #include "config_gobj.h"
 #include "config_gobj.h"
 #include "bamFile.h"
 #include "bamFile.h"
 #include "preparedGraphicsObjects.h"
 #include "preparedGraphicsObjects.h"
@@ -3058,6 +3061,229 @@ get_texture(TextureStage *stage) const {
   return NULL;
   return NULL;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_shader
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_shader(Shader *sha, int priority) {
+  nassertv_always(!is_empty());
+
+  const RenderAttrib *attrib =
+    node()->get_attrib(ShaderAttrib::get_class_type());
+  if (attrib != (const RenderAttrib *)NULL) {
+    priority = max(priority,
+                   node()->get_state()->get_override(ShaderAttrib::get_class_type()));
+    const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
+    node()->set_attrib(sa->set_shader(sha, priority));
+  } else {
+    // Create a new ShaderAttrib for this node.
+    CPT(ShaderAttrib) sa = DCAST(ShaderAttrib, ShaderAttrib::make());
+    node()->set_attrib(sa->set_shader(sha, priority));
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_shader_off
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_shader_off(int priority) {
+  set_shader(NULL, priority);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::clear_shader
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+clear_shader() {
+  nassertv_always(!is_empty());
+
+  const RenderAttrib *attrib =
+    node()->get_attrib(ShaderAttrib::get_class_type());
+  if (attrib != (const RenderAttrib *)NULL) {
+    const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
+    node()->set_attrib(sa->clear_shader());
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::get_shader
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const Shader *NodePath::
+get_shader() const {
+  nassertr_always(!is_empty(), NULL);
+  const RenderAttrib *attrib =
+    node()->get_attrib(ShaderAttrib::get_class_type());
+  if (attrib != (const RenderAttrib *)NULL) {
+    const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
+    return sa->get_shader();
+  }
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_shader_input(const ShaderInput *inp) {
+  nassertv_always(!is_empty());
+
+  const RenderAttrib *attrib =
+    node()->get_attrib(ShaderAttrib::get_class_type());
+  if (attrib != (const RenderAttrib *)NULL) {
+    const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
+    node()->set_attrib(sa->add_input(inp));
+  } else {
+    // Create a new ShaderAttrib for this node.
+    CPT(ShaderAttrib) sa = DCAST(ShaderAttrib, ShaderAttrib::make());
+    node()->set_attrib(sa->add_input(inp));
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::get_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const ShaderInput *NodePath::
+get_shader_input(InternalName *id) const {
+  nassertr_always(!is_empty(), NULL);
+  
+  const RenderAttrib *attrib =
+    node()->get_attrib(ShaderAttrib::get_class_type());
+  if (attrib != (const RenderAttrib *)NULL) {
+    const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
+    return sa->get_input(id);
+  }
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::clear_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+clear_shader_input(InternalName *id) {
+  nassertv_always(!is_empty());
+
+  const RenderAttrib *attrib =
+    node()->get_attrib(ShaderAttrib::get_class_type());
+  if (attrib != (const RenderAttrib *)NULL) {
+    const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
+    node()->set_attrib(sa->clear_input(id));
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_shader_input(InternalName *id, Texture *tex, int priority) {
+  set_shader_input(new ShaderInput(id,tex,priority));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_shader_input(InternalName *id, const NodePath &np, int priority) {
+  set_shader_input(new ShaderInput(id,np,priority));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_shader_input(InternalName *id, const LVector4f &v, int priority) {
+  set_shader_input(new ShaderInput(id,v,priority));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_shader_input(InternalName *id, double n1, double n2, double n3, double n4, int priority) {
+  set_shader_input(new ShaderInput(id,LVector4f(n1,n2,n3,n4),priority));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_shader_input(const string &id, Texture *tex, int priority) {
+  set_shader_input(new ShaderInput(InternalName::make(id),tex,priority));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_shader_input(const string &id, const NodePath &np, int priority) {
+  set_shader_input(new ShaderInput(InternalName::make(id),np,priority));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_shader_input(const string &id, const LVector4f &v, int priority) {
+  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+set_shader_input(const string &id, double n1, double n2, double n3, double n4, int priority) {
+  set_shader_input(new ShaderInput(InternalName::make(id),LVector4f(n1,n2,n3,n4),priority));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::get_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+const ShaderInput *NodePath::
+get_shader_input(const string &id) const {
+  return get_shader_input(InternalName::make(id));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::clear_shader_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void NodePath::
+clear_shader_input(const string &id) {
+  clear_shader_input(InternalName::make(id));
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::set_tex_transform
 //     Function: NodePath::set_tex_transform
 //       Access: Published
 //       Access: Published

+ 20 - 1
panda/src/pgraph/nodePath.h

@@ -27,7 +27,6 @@
 #include "renderModeAttrib.h"
 #include "renderModeAttrib.h"
 #include "transparencyAttrib.h"
 #include "transparencyAttrib.h"
 #include "nodePathComponent.h"
 #include "nodePathComponent.h"
-
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "referenceCount.h"
 #include "referenceCount.h"
 #include "notify.h"
 #include "notify.h"
@@ -46,6 +45,8 @@ class Material;
 class Fog;
 class Fog;
 class GlobPattern;
 class GlobPattern;
 class PreparedGraphicsObjects;
 class PreparedGraphicsObjects;
+class Shader;
+class ShaderInput;
 
 
 //
 //
 // A NodePath is the fundamental unit of high-level interaction with
 // A NodePath is the fundamental unit of high-level interaction with
@@ -553,6 +554,24 @@ PUBLISHED:
   Texture *get_texture() const;
   Texture *get_texture() const;
   Texture *get_texture(TextureStage *stage) const;
   Texture *get_texture(TextureStage *stage) const;
 
 
+  void set_shader(Shader *sha, int priority = 0);
+  void set_shader_off(int priority = 0);
+  void clear_shader();
+  const Shader *get_shader() const;
+  void set_shader_input(const ShaderInput *inp);
+  const ShaderInput *get_shader_input(InternalName *id) const;
+  void clear_shader_input(InternalName *id);
+  void set_shader_input(InternalName *id, Texture *tex,       int priority=0);
+  void set_shader_input(InternalName *id, const NodePath &np, int priority=0);
+  void set_shader_input(InternalName *id, const LVector4f &v, int priority=0);
+  void set_shader_input(InternalName *id, double n1=0, double n2=0, double n3=0, double n4=1, int priority=0);
+  void set_shader_input(const string &id, Texture *tex,       int priority=0);
+  void set_shader_input(const string &id, const NodePath &np, int priority=0);
+  void set_shader_input(const string &id, const LVector4f &v, int priority=0);
+  void set_shader_input(const string &id, double n1=0, double n2=0, double n3=0, double n4=1, int priority=0);
+  const ShaderInput *get_shader_input(const string &id) const;
+  void clear_shader_input(const string &id);
+  
   void set_tex_transform(TextureStage *stage, const TransformState *transform);
   void set_tex_transform(TextureStage *stage, const TransformState *transform);
   void clear_tex_transform();
   void clear_tex_transform();
   void clear_tex_transform(TextureStage *stage);
   void clear_tex_transform(TextureStage *stage);

+ 2 - 1
panda/src/pgraph/pgraph_composite4.cxx

@@ -9,7 +9,8 @@
 #include "selectiveChildNode.cxx"
 #include "selectiveChildNode.cxx"
 #include "sequenceNode.cxx"
 #include "sequenceNode.cxx"
 #include "shadeModelAttrib.cxx"
 #include "shadeModelAttrib.cxx"
-#include "shaderMode.cxx"
+#include "shader.cxx"
+#include "shaderInput.cxx"
 #include "shaderAttrib.cxx"
 #include "shaderAttrib.cxx"
 #include "showBoundsEffect.cxx"
 #include "showBoundsEffect.cxx"
 #include "spotlight.cxx"
 #include "spotlight.cxx"

+ 2 - 3
panda/src/pgraph/renderModeAttrib.cxx

@@ -167,9 +167,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderModeAttrib::store_into_slot
 //     Function: RenderModeAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RenderModeAttrib::
 void RenderModeAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 20 - 0
panda/src/pgraph/renderState.I

@@ -560,6 +560,26 @@ compare_to(const Attribute &other) const {
   return _override - other._override;
   return _override - other._override;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::get_shader_expansion
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ShaderExpansion *RenderState::
+get_shader_expansion() const {
+  return _shader_expansion;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::set_shader_expansion
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void RenderState::
+set_shader_expansion(ShaderExpansion *exp) {
+  _shader_expansion = exp;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::CompositionCycleDescEntry::Constructor
 //     Function: RenderState::CompositionCycleDescEntry::Constructor
 //       Access: Public
 //       Access: Public

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

@@ -39,6 +39,7 @@
 RenderState::States *RenderState::_states = NULL;
 RenderState::States *RenderState::_states = NULL;
 CPT(RenderState) RenderState::_empty_state;
 CPT(RenderState) RenderState::_empty_state;
 UpdateSeq RenderState::_last_cycle_detect;
 UpdateSeq RenderState::_last_cycle_detect;
+
 PStatCollector RenderState::_cache_update_pcollector("*:State Cache:Update");
 PStatCollector RenderState::_cache_update_pcollector("*:State Cache:Update");
 PStatCollector RenderState::_state_compose_pcollector("*:State Cache:Compose State");
 PStatCollector RenderState::_state_compose_pcollector("*:State Cache:Compose State");
 PStatCollector RenderState::_state_invert_pcollector("*:State Cache:Invert State");
 PStatCollector RenderState::_state_invert_pcollector("*:State Cache:Invert State");
@@ -287,6 +288,7 @@ make(const AttribSlots *slots, int override) {
     }
     }
   }
   }
   state->_attributes.reserve(state->_attributes.size());
   state->_attributes.reserve(state->_attributes.size());
+  state->_attributes.sort();
   return return_new(state);
   return return_new(state);
 }
 }
 
 

+ 8 - 0
panda/src/pgraph/renderState.h

@@ -31,6 +31,7 @@
 #include "texMatrixAttrib.h"
 #include "texMatrixAttrib.h"
 #include "geomMunger.h"
 #include "geomMunger.h"
 #include "weakPointerTo.h"
 #include "weakPointerTo.h"
+#include "shaderExpansion.h"
 
 
 class GraphicsStateGuardianBase;
 class GraphicsStateGuardianBase;
 class FogAttrib;
 class FogAttrib;
@@ -148,6 +149,8 @@ public:
   void store_into_slots(AttribSlots *slots) const;
   void store_into_slots(AttribSlots *slots) const;
   
   
   static void bin_removed(int bin_index);
   static void bin_removed(int bin_index);
+  INLINE ShaderExpansion *get_shader_expansion() const;
+  INLINE void set_shader_expansion(ShaderExpansion *exp);
 
 
 private:
 private:
   class CompositionCycleDescEntry {
   class CompositionCycleDescEntry {
@@ -271,6 +274,11 @@ private:
   int _bin_index;
   int _bin_index;
   int _draw_order;
   int _draw_order;
 
 
+  // If this renderstate contains a Shader, then the macroexpansion
+  // of the shader needs to be cached (to avoid having to regenerate
+  // it each time this RenderState is applied).
+  PT(ShaderExpansion) _shader_expansion;
+  
   // We also cache the pointer to some critical attribs stored in the
   // We also cache the pointer to some critical attribs stored in the
   // state, if they exist.
   // state, if they exist.
   const FogAttrib *_fog;
   const FogAttrib *_fog;

+ 2 - 3
panda/src/pgraph/rescaleNormalAttrib.cxx

@@ -119,9 +119,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RescaleNormalAttrib::store_into_slot
 //     Function: RescaleNormalAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RescaleNormalAttrib::
 void RescaleNormalAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/shadeModelAttrib.cxx

@@ -126,9 +126,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ShadeModelAttrib::store_into_slot
 //     Function: ShadeModelAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ShadeModelAttrib::
 void ShadeModelAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 69 - 0
panda/src/pgraph/shader.I

@@ -0,0 +1,69 @@
+// Filename: shader.I
+// Created by: jyelon (01Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::get_file
+//       Access: Published
+//  Description: Returns null string if shader was not loaded from
+//               a source file.
+////////////////////////////////////////////////////////////////////
+INLINE const Filename &Shader::
+get_file() const {
+  return _file;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::get_body
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE const string &Shader::
+get_body() const {
+  return _body;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::get_name
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE const string &Shader::
+get_name() const {
+  return _name;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::get_loaded
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool Shader::
+get_loaded() const {
+  return _loaded;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::get_preprocessor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE int Shader::
+get_preprocessor() const {
+  return _preprocessor;
+}
+

+ 163 - 0
panda/src/pgraph/shader.cxx

@@ -0,0 +1,163 @@
+// Filename: shader.cxx
+// Created by: jyelon (01Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "shader.h"
+#include "virtualFileSystem.h"
+
+TypeHandle Shader::_type_handle;
+Shader::LoadTable Shader::_load_table;
+Shader::MakeTable Shader::_make_table;
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::Constructor
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+Shader::
+Shader() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::Destructor
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+Shader::
+~Shader() {
+  if (_loaded) {
+    LoadTableKey key(_file, _preprocessor);
+    _load_table.erase(key);
+  } else {
+    MakeTableKey key(_body, _preprocessor);
+    _make_table.erase(key);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::load
+//       Access: Published, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(Shader) Shader::
+load(const string &file, int preprocessor) {
+  return load(Filename(file), preprocessor);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::load
+//       Access: Published, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(Shader) Shader::
+load(const Filename &file, int preprocessor) {
+  LoadTableKey key(file, preprocessor);
+  LoadTable::const_iterator i = _load_table.find(key);
+  if (i != _load_table.end()) {
+    return i->second;
+  }
+  Shader *result = new Shader;
+  result->_name = file;
+  result->_file = file;
+  result->_loaded = true;
+  result->_preprocessor = preprocessor;
+  result->_fixed_expansion = 0;
+  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
+  if (!vfs->read_file(file, result->_body)) {
+    cerr << "Could not read shader file: " << file << "\n";
+    result->_body = "";
+  }
+  _load_table[key] = result;
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::make
+//       Access: Published, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(Shader) Shader::
+make(const string &body, int preprocessor) {
+  MakeTableKey key(body, preprocessor);
+  MakeTable::const_iterator i = _make_table.find(key);
+  if (i != _make_table.end()) {
+    return i->second;
+  }
+  Shader *result = new Shader;
+  result->_name = "generated shader";
+  result->_file = "";
+  result->_loaded = false;
+  result->_preprocessor = preprocessor;
+  result->_fixed_expansion = 0;
+  result->_body = body;
+  _make_table[key] = result;
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::macroexpand
+//       Access: Public
+//  Description: The eventual plan is that shaders will be run through
+//               a macro preprocessor in order to generate the actual
+//               shader text in Cg, GLSL, HLSL, or whatever.  The
+//               macro preprocessor will be able to query the RenderState
+//               and generate different shader code for different states.
+//               
+//               The macroexpansion of the shader is stored in an object
+//               of class ShaderExpansion.  This is somewhat expensive
+//               to generate, so the ShaderExpansion is cached inside the
+//               the RenderState itself.  The ShaderExpansion contains
+//               a map of ShaderContexts, each containing a compiled
+//               copy of the shader's macroexpansion.
+//
+//               Any given shader might not contain any ifdefs that
+//               depend on the RenderState.  If macroexpand determines
+//               that a given shader is not state-sensitive, it can cache
+//               the macroexpansion in the field "_fixed_expansion."
+//
+//               The preprocessing is usually done by a built-in macro
+//               preprocessing function.  However, the user can write
+//               his own preprocessor if he wishes to do so.  A user-
+//               supplied preprocessor can generate arbitrary code ---
+//               in fact, it doesn't need to look at the input string
+//               if it does not wish to do so.
+//
+//               Currently, macroexpand is just a stub that returns an
+//               expansion which is exactly equal to the input string.
+////////////////////////////////////////////////////////////////////
+PT(ShaderExpansion) Shader::
+macroexpand(const RenderState *context) const {
+  if (_fixed_expansion) {
+    return _fixed_expansion;
+  }
+  // I am casting away the 'const' so as to be able
+  // to write to this field.  This field is just a cache.
+  ((Shader*)this)->_fixed_expansion = ShaderExpansion::make(_name,_body);
+  return _fixed_expansion;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Shader::register_with_read_factory
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void Shader::
+register_with_read_factory() {
+  // IMPLEMENT ME
+}
+
+

+ 93 - 0
panda/src/pgraph/shader.h

@@ -0,0 +1,93 @@
+// Filename: shader.h
+// Created by: jyelon (01Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef SHADER_H
+#define SHADER_H
+
+#include "pandabase.h"
+#include "typedWritableReferenceCount.h"
+#include "pointerTo.h"
+#include "dcast.h"
+
+class ShaderExpansion;
+
+////////////////////////////////////////////////////////////////////
+//       Class : Shader
+// Description : 
+////////////////////////////////////////////////////////////////////
+
+class EXPCL_PANDA Shader: public TypedWritableReferenceCount {
+PUBLISHED:
+  static CPT(Shader) load(const Filename &file, int preprocessor=0);
+  static CPT(Shader) load(const string &file,   int preprocessor=0);
+  static CPT(Shader) make(const string &body,   int preprocessor=0);
+  
+  INLINE const string   &get_name() const;
+  INLINE const Filename &get_file() const;
+  INLINE const string   &get_body() const;
+  INLINE int             get_preprocessor() const;
+  INLINE bool            get_loaded() const;
+  
+  PT(ShaderExpansion) macroexpand(const RenderState *context) const;
+  
+public:
+  Shader();
+  ~Shader();
+  
+private:
+  string   _name;
+  Filename _file;
+  string   _body;
+  bool     _loaded;
+  int      _preprocessor;
+  
+  PT(ShaderExpansion) _fixed_expansion;
+  
+  typedef pair < Filename, int > LoadTableKey;
+  typedef pair < string,   int > MakeTableKey;
+
+  typedef pmap < LoadTableKey , Shader * > LoadTable;
+  typedef pmap < MakeTableKey , Shader * > MakeTable;
+  
+  static LoadTable _load_table;
+  static MakeTable _make_table;
+  
+public:
+  static void register_with_read_factory();
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    TypedWritableReferenceCount::init_type();
+    register_type(_type_handle, "Shader",
+                  TypedWritableReferenceCount::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "shader.I"
+
+#endif SHADER_H

+ 55 - 14
panda/src/pgraph/shaderAttrib.I

@@ -20,33 +20,74 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ShaderAttrib::Constructor
 //     Function: ShaderAttrib::Constructor
 //       Access: Private
 //       Access: Private
-//  Description: xyz
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE ShaderAttrib::
 INLINE ShaderAttrib::
 ShaderAttrib() {
 ShaderAttrib() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: ShaderAttrib::is_off
+//     Function: ShaderAttrib::Copy Constructor
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ShaderAttrib::
+ShaderAttrib(const ShaderAttrib &copy) :
+  _shader(copy._shader),
+  _shader_priority(copy._shader_priority),
+  _has_shader(copy._has_shader),
+  _inputs(copy._inputs)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderAttrib::get_shader
+//       Access: Published
+//  Description: Returns the shader object associated with the node.
+//               If get_override returns true, but get_shader 
+//               returns NULL, that means that this attribute should
+//               disable the shader.
+////////////////////////////////////////////////////////////////////
+INLINE const Shader *ShaderAttrib::
+get_shader() const {
+  return _shader;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderAttrib::has_shader
 //       Access: Published
 //       Access: Published
-//  Description: Returns true if the ShaderAttrib is an 'off'
-//               ShaderAttrib, indicating that it should disable
-//               the previous shader profiles
+//  Description: If true, the shader field of this attribute overrides
+//               the shader field of the parent attribute.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool ShaderAttrib::
 INLINE bool ShaderAttrib::
-is_off() const {
-  return _shader_mode == (ShaderMode *)NULL;
+has_shader() const {
+  return _has_shader;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderAttrib::get_shader_priority
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE int ShaderAttrib::
+get_shader_priority() const {
+  return _shader_priority;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: ShaderAttrib::get_shader_mode
+//     Function: ShaderAttrib::get_input
 //       Access: Published
 //       Access: Published
-//  Description: If the ShaderAttrib is not an 'off' ShaderAttrib,
-//               returns the ShaderMode that is associated.  Otherwise,
-//               return NULL.
+//  Description: Returns the ShaderInput of the given name.  If
+//               no such name is found, this function does not return
+//               NULL --- it returns the "blank" ShaderInput.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE ShaderMode *ShaderAttrib::
-get_shader_mode() const {
-  return _shader_mode;
+INLINE const ShaderInput *ShaderAttrib::
+get_input(const InternalName *id) const {
+  Inputs::const_iterator i = _inputs.find(id);
+  if (i == _inputs.end()) {
+    return ShaderInput::get_blank();
+  } else {
+    return (*i).second;
+  }
 }
 }
 
 

+ 166 - 24
panda/src/pgraph/shaderAttrib.cxx

@@ -28,28 +28,114 @@
 TypeHandle ShaderAttrib::_type_handle;
 TypeHandle ShaderAttrib::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: ShaderAttrib::make
+//     Function: ShaderAttrib::make_off
 //       Access: Published, Static
 //       Access: Published, Static
-//  Description: Constructs a new ShaderAttrib object suitable for
-//               process the indicated geometry with shaders
+//  Description: Constructs a new ShaderAttrib object that disables
+//               the use of shaders (it does not clear out all shader
+//               data, however.)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
+
 CPT(RenderAttrib) ShaderAttrib::
 CPT(RenderAttrib) ShaderAttrib::
-make(ShaderMode *shader_mode) {
-  ShaderAttrib *attrib = new ShaderAttrib;
-  attrib->_shader_mode = shader_mode;
-  return return_new(attrib);
+make_off() {
+  static CPT(RenderAttrib) _off_attrib;
+  if (_off_attrib == 0) {
+    ShaderAttrib *attrib = new ShaderAttrib;
+    attrib->_shader = (Shader*)NULL;
+    attrib->_shader_priority = 0;
+    attrib->_has_shader = true;
+    _off_attrib = return_new(attrib);
+  }
+  return _off_attrib;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: ShaderAttrib::make_off
+//     Function: ShaderAttrib::make
 //       Access: Published, Static
 //       Access: Published, Static
-//  Description: Constructs a new ShaderAttrib object suitable for
-//               rendering geometry with no shader interference
+//  Description: Constructs a new ShaderAttrib object with nothing
+//               set.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) ShaderAttrib::
 CPT(RenderAttrib) ShaderAttrib::
-make_off() {
-  ShaderAttrib *attrib = new ShaderAttrib;
-  return return_new(attrib);
+make() {
+  static CPT(RenderAttrib) _null_attrib;
+  if (_null_attrib == 0) {
+    ShaderAttrib *attrib = new ShaderAttrib;
+    attrib->_shader = (Shader*)NULL;
+    attrib->_shader_priority = 0;
+    attrib->_has_shader = false;
+    _null_attrib = return_new(attrib);
+  }
+  return _null_attrib;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderAttrib::set_shader
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ShaderAttrib::
+set_shader(const Shader *s, int priority) const {
+  ShaderAttrib *result = new ShaderAttrib(*this);
+  result->_shader = s;
+  result->_shader_priority = priority;
+  result->_has_shader = true;
+  return return_new(result);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderAttrib::set_shader_off
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ShaderAttrib::
+set_shader_off(int priority) const {
+  ShaderAttrib *result = new ShaderAttrib(*this);
+  result->_shader = NULL;
+  result->_shader_priority = priority;
+  result->_has_shader = true;
+  return return_new(result);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderAttrib::clear_shader
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ShaderAttrib::
+clear_shader() const {
+  ShaderAttrib *result = new ShaderAttrib(*this);
+  result->_shader = NULL;
+  result->_shader_priority = 0;
+  result->_has_shader = false;
+  return return_new(result);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderAttrib::add_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ShaderAttrib::
+add_input(const ShaderInput *input) const {
+  ShaderAttrib *result = new ShaderAttrib(*this);
+  Inputs::iterator i = result->_inputs.find(input->get_name());
+  if (i == result->_inputs.end()) {
+    result->_inputs.insert(Inputs::value_type(input->get_name(),input));
+  } else {
+    i->second = input;
+  }
+  return return_new(result);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderAttrib::clear_input
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ShaderAttrib::
+clear_input(const InternalName *id) const {
+  ShaderAttrib *result = new ShaderAttrib(*this);
+  result->_inputs.erase(id);
+  return return_new(result);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -57,7 +143,7 @@ make_off() {
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
 //  Description: Intended to be overridden by derived ShaderAttrib
 //  Description: Intended to be overridden by derived ShaderAttrib
 //               types to specify what the default property for a
 //               types to specify what the default property for a
-//               TexGenAttrib of this type should be.
+//               ShaderAttrib of this type should be.
 //
 //
 //               This should return a newly-allocated ShaderAttrib of
 //               This should return a newly-allocated ShaderAttrib of
 //               the same type that corresponds to whatever the
 //               the same type that corresponds to whatever the
@@ -71,9 +157,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ShaderAttrib::store_into_slot
 //     Function: ShaderAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ShaderAttrib::
 void ShaderAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {
@@ -97,18 +182,75 @@ store_into_slot(AttribSlots *slots) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int ShaderAttrib::
 int ShaderAttrib::
 compare_to_impl(const RenderAttrib *other) const {
 compare_to_impl(const RenderAttrib *other) const {
-  const ShaderAttrib *cgsa;
-  DCAST_INTO_R(cgsa, other, 0);
+  const ShaderAttrib *that;
+  DCAST_INTO_R(that, other, 0);
   
   
-  // Comparing pointers by subtraction is problematic.  Instead of
-  // doing this, we'll just depend on the built-in != and < operators
-  // for comparing pointers.
-  if (_shader_mode != cgsa->_shader_mode) {
-    return _shader_mode < cgsa->_shader_mode ? -1 : 1;
+  if (this->_shader != that->_shader) {
+    return (this->_shader < that->_shader) ? -1 : 1;
   }
   }
+  if (this->_shader_priority != that->_shader_priority) {
+    return (this->_shader_priority < that->_shader_priority) ? -1 : 1;
+  }
+  if (this->_has_shader != that->_has_shader) {
+    return (this->_has_shader < that->_has_shader) ? -1 : 1;
+  }
+  
+  Inputs::const_iterator i1 = this->_inputs.begin();
+  Inputs::const_iterator i2 = that->_inputs.begin();
+  while ((i1 != this->_inputs.end()) && (i2 != that->_inputs.end())) {
+    if (i1->second != i2->second) {
+      return (i1->second < i2->second) ? -1 : 1;
+    }
+    ++i1;
+    ++i2;
+  }
+  if (i1 != this->_inputs.end()) {
+    return 1;
+  }
+  if (i1 != that->_inputs.end()) {
+    return -1;
+  }
+  
   return 0;
   return 0;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderAttrib::compose_impl
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) ShaderAttrib::
+compose_impl(const RenderAttrib *other) const {
+  ShaderAttrib *attr = new ShaderAttrib(*this);
+  const ShaderAttrib *over;
+  DCAST_INTO_R(over, other, 0);
+  // Update the shader portion.
+  if (over->_has_shader) {
+    if ((attr->_has_shader == false) ||
+        (over->_shader_priority >= attr->_shader_priority)) {
+      attr->_shader = over->_shader;
+      attr->_shader_priority = over->_shader_priority;
+      attr->_has_shader = over->_has_shader;
+    }
+  }
+  // Update the shader-data portion.
+  Inputs::const_iterator iover;
+  for (iover=over->_inputs.begin(); iover!=over->_inputs.end(); ++iover) {
+    const InternalName *id = (*iover).first;
+    const ShaderInput *dover = (*iover).second;
+    Inputs::iterator iattr = attr->_inputs.find(id);
+    if (iattr == attr->_inputs.end()) {
+      attr->_inputs.insert(Inputs::value_type(id,dover));
+    } else {
+      const ShaderInput *dattr = (*iattr).second;
+      if (dattr->get_priority() <= dover->get_priority()) {
+        iattr->second = iover->second;
+      }
+    }
+  }
+  return return_new(attr);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ShaderAttrib::register_with_read_factory
 //     Function: ShaderAttrib::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 26 - 17
panda/src/pgraph/shaderAttrib.h

@@ -1,5 +1,5 @@
 // Filename: shaderAttrib.h
 // Filename: shaderAttrib.h
-// Created by:  sshodhan (10Jul04)
+// Created by: jyelon (01Sep05)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //
 //
@@ -20,45 +20,54 @@
 #define SHADERATTRIB_H
 #define SHADERATTRIB_H
 
 
 #include "pandabase.h"
 #include "pandabase.h"
-#include "luse.h"
-#include "pmap.h"
-#include "shader.h"
 #include "renderAttrib.h"
 #include "renderAttrib.h"
-#include "typedObject.h"
-#include "typedReferenceCount.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
-#include "factoryParam.h"
-#include "dcast.h"
-#include "shaderMode.h"
+#include "shaderInput.h"
+#include "shader.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : ShaderAttrib
 //       Class : ShaderAttrib
-// Description : fill me in
+// Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 class EXPCL_PANDA ShaderAttrib: public RenderAttrib {
 class EXPCL_PANDA ShaderAttrib: public RenderAttrib {
 
 
 private:
 private:
   INLINE ShaderAttrib();
   INLINE ShaderAttrib();
+  INLINE ShaderAttrib(const ShaderAttrib &copy);
 
 
 PUBLISHED:
 PUBLISHED:
-  static CPT(RenderAttrib) make(ShaderMode *sm);
+  static CPT(RenderAttrib) make();
   static CPT(RenderAttrib) make_off();
   static CPT(RenderAttrib) make_off();
 
 
-  INLINE bool is_off() const;
-  INLINE ShaderMode *get_shader_mode() const;
-
+  INLINE bool               has_shader() const;
+  INLINE int                get_shader_priority() const;
+  INLINE const Shader      *get_shader() const;
+  INLINE const ShaderInput *get_input(const InternalName *id) const;
+  
+  CPT(RenderAttrib)  clear_shader() const;
+  CPT(RenderAttrib)  set_shader(const Shader *s, int priority=0) const;
+  CPT(RenderAttrib)  set_shader_off(int priority=0) const;
+  
+  CPT(RenderAttrib)  add_input(const ShaderInput *input) const;
+  CPT(RenderAttrib)  clear_input(const InternalName *id) const;
+  
   static void register_with_read_factory();
   static void register_with_read_factory();
-
+  
 public:
 public:
   virtual void store_into_slot(AttribSlots *slots) const;
   virtual void store_into_slot(AttribSlots *slots) const;
 
 
 protected:
 protected:
   virtual RenderAttrib *make_default_impl() const;
   virtual RenderAttrib *make_default_impl() const;
   virtual int compare_to_impl(const RenderAttrib *other) const;
   virtual int compare_to_impl(const RenderAttrib *other) const;
-
+  virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
+  
 private:
 private:
-  PT(ShaderMode) _shader_mode;
+  CPT(Shader) _shader;
+  int         _shader_priority;
+  bool        _has_shader;
+  typedef pmap < CPT(InternalName), CPT(ShaderInput) > Inputs;
+  Inputs _inputs;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 152 - 0
panda/src/pgraph/shaderInput.I

@@ -0,0 +1,152 @@
+// Filename: shaderInput.I
+// Created by: jyelon (01Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ShaderInput::
+~ShaderInput()
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::Constructor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ShaderInput::
+ShaderInput(InternalName *name, int priority) :
+  _type(M_invalid),
+  _name(name),
+  _priority(priority),
+  _stored_texture(NULL),
+  _stored_nodepath(NodePath()),
+  _stored_vector(LVector4f(0,0,0,1))
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::Constructor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ShaderInput::
+ShaderInput(InternalName *name, Texture *tex, int priority) :
+  _type(M_texture),
+  _name(name),
+  _priority(priority),
+  _stored_texture(tex),
+  _stored_nodepath(NodePath()),
+  _stored_vector(LVector4f(0,0,0,1))
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::Constructor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ShaderInput::
+ShaderInput(InternalName *name, const NodePath &np, int priority) :
+  _type(M_nodepath),
+  _name(name),
+  _priority(priority),
+  _stored_texture(NULL),
+  _stored_nodepath(np),
+  _stored_vector(LVector4f(0,0,0,1))
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::Constructor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ShaderInput::
+ShaderInput(InternalName *name, const LVector4f &vec, int priority) :
+  _type(M_vector),
+  _name(name),
+  _priority(priority),
+  _stored_texture(NULL),
+  _stored_nodepath(NodePath()),
+  _stored_vector(vec)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::get_name
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE InternalName *ShaderInput::
+get_name() const {
+  return _name;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::get_value_type
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE int ShaderInput::
+get_value_type() const {
+  return _type;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::get_priority
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE int ShaderInput::
+get_priority() const {
+  return _priority;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::get_texture
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE Texture *ShaderInput::
+get_texture() const {
+  return _stored_texture;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::get_nodepath
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE const NodePath &ShaderInput::
+get_nodepath() const {
+  return _stored_nodepath;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::get_vector
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE const LVector4f &ShaderInput::
+get_vector() const {
+  return _stored_vector;
+}
+

+ 26 - 25
panda/src/pgraph/shaderMode.I → panda/src/pgraph/shaderInput.cxx

@@ -1,5 +1,5 @@
-// Filename: shaderMode.I
-// Heavily Modified:  jyelon (01Sep05)
+// Filename: shaderInput.cxx
+// Created by: jyelon (01Sep05)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //
 //
@@ -16,32 +16,33 @@
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
+#include "shaderInput.h"
+
+TypeHandle ShaderInput::_type_handle;
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//  Function: ShaderModeArg::Constructor
-//  Access: Public
-//  Description: initialize a shader arg storage structure.
-////////////////////////////////////////////////////////////////////
-INLINE ShaderModeArg::
-ShaderModeArg() {
-  _type = SAT_INVALID;
-}
-  
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderModeArg::Destructor
-//  Access: Public
-//  Description: delete a shader arg storage structure.
-////////////////////////////////////////////////////////////////////
-INLINE ShaderModeArg::
-~ShaderModeArg() {
+//     Function: ShaderInput::get_blank
+//       Access: Public, Static
+//  Description: Returns a static ShaderInput object with
+//               name NULL, priority zero, type INVALID, and
+//               all value-fields cleared.
+////////////////////////////////////////////////////////////////////
+const ShaderInput *ShaderInput::
+get_blank() {
+  static CPT(ShaderInput) blank;
+  if (blank == 0) {
+    blank = new ShaderInput(NULL, 0);
+  }
+  return blank;
 }
 }
- 
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::get_shader
-//  Access: Public
-//  Description: Return the Shader associated with this shader mode.
+//     Function: ShaderInput::register_with_read_factory
+//       Access: Public, Static
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE Shader *ShaderMode::
-get_shader() {
-  return _shader;
+void ShaderInput::
+register_with_read_factory() {
+  // IMPLEMENT ME
 }
 }
 
 

+ 93 - 0
panda/src/pgraph/shaderInput.h

@@ -0,0 +1,93 @@
+// Filename: shaderInput.h
+// Created by: jyelon (01Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef SHADERINPUT_H
+#define SHADERINPUT_H
+
+#include "pandabase.h"
+#include "typedWritableReferenceCount.h"
+#include "pointerTo.h"
+#include "nodePath.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : ShaderInput
+// Description : This is a small container class that can hold any
+//               one of the value types that can be passed as input
+//               to a shader.
+////////////////////////////////////////////////////////////////////
+
+class EXPCL_PANDA ShaderInput: public TypedWritableReferenceCount {
+public:
+  INLINE ~ShaderInput();
+
+PUBLISHED:
+  static const ShaderInput *get_blank();
+  INLINE ShaderInput(InternalName *id, int priority=0);
+  INLINE ShaderInput(InternalName *id, const NodePath &np, int priority=0);
+  INLINE ShaderInput(InternalName *id, const LVector4f &v, int priority=0);
+  INLINE ShaderInput(InternalName *id, Texture  *tex,      int priority=0);
+  
+  enum ShaderInputType {
+    M_invalid = 0,
+    M_texture,
+    M_nodepath,
+    M_vector
+  };
+  
+  INLINE InternalName *get_name() const;
+  
+  INLINE int               get_value_type() const;
+  INLINE int               get_priority() const;
+  INLINE Texture          *get_texture() const;
+  INLINE const NodePath   &get_nodepath() const;
+  INLINE const LVector4f  &get_vector() const;
+  
+public:
+  static void register_with_read_factory();
+
+private:
+  PT(InternalName) _name;
+  int _type;
+  int _priority;
+  PT(Texture) _stored_texture;
+  NodePath    _stored_nodepath;
+  LVector4f   _stored_vector;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    ReferenceCount::init_type();
+    register_type(_type_handle, "ShaderInput",
+                  ReferenceCount::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+
+#include "shaderInput.I"
+
+#endif  // SHADERINPUT_H
+

+ 0 - 237
panda/src/pgraph/shaderMode.cxx

@@ -1,237 +0,0 @@
-// Filename: shaderMode.cxx
-// Created by:  jyelon (01Sep05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#include "pandabase.h"
-#include "shader.h"
-#include "shaderMode.h"
-#include "virtualFileSystem.h"
-
-TypeHandle ShaderMode::_type_handle;
-
-////////////////////////////////////////////////////////////////////
-//     Function: ShaderMode::load
-//       Access: Published
-//  Description: Obtain the shader associated with the specified 
-//               file and construct a ShaderMode for that shader.
-////////////////////////////////////////////////////////////////////
-PT(ShaderMode) ShaderMode::
-load(const Filename &file)
-{
-  string text;
-  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
-  if (!vfs->read_file(file, text)) {
-    cerr << "Could not read " << file << "\n";
-    return new ShaderMode(new Shader("", file));
-  }
-  return new ShaderMode(new Shader(text, file));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ShaderMode::load
-//       Access: Published
-//  Description: Obtain the shader associated with the specified 
-//               file and construct a ShaderMode for that shader.
-////////////////////////////////////////////////////////////////////
-PT(ShaderMode) ShaderMode::
-load(const string &file)
-{
-  Filename fn(file);
-  return load(fn);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ShaderMode::make
-//       Access: Published
-//  Description: Obtain the shader associated with the specified
-//               text and construct a ShaderMode for that shader.
-////////////////////////////////////////////////////////////////////
-PT(ShaderMode) ShaderMode::
-make(const string &text)
-{
-  return new ShaderMode(new Shader(text, ""));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ShaderMode::Constructor
-//       Access: Published
-//  Description: Use to construct a new shader instance.
-////////////////////////////////////////////////////////////////////
-ShaderMode::
-ShaderMode(Shader *shader) {
-  _shader = shader;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ShaderMode::Destructor
-//       Access: Public
-//  Description: delete a shader
-////////////////////////////////////////////////////////////////////
-ShaderMode::
-~ShaderMode() {
-}
-
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::mod_param
-//  Access: Private
-//  Description: To set a parameter, you must first access it and
-//               then clear it.  This function accesses then clears
-//               the storage for a parameter, prior to setting it.
-////////////////////////////////////////////////////////////////////
-INLINE ShaderModeArg *ShaderMode::
-mod_param(const string &pname, int t) {
-  int index = _shader->arg_index(pname);
-  if (index >= (int)(_args.size()))
-    _args.resize(index+1);
-  ShaderModeArg *arg = &(_args[index]);
-  arg->_type = t;
-  arg->_nvalue = NodePath();
-  arg->_tvalue = (Texture*)NULL;
-  arg->_fvalue = LVector4d(0,0,0,0);
-  return arg;
-}
-
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::set_param texture
-//  Access: Public
-//  Description: Store texture in the map to associate with 
-//               param name
-////////////////////////////////////////////////////////////////////
-void ShaderMode::
-set_param(const string &pname, Texture *x) {
-  ShaderModeArg *arg = mod_param(pname, ShaderModeArg::SAT_TEXTURE);
-  arg->_tvalue = x;
-}
-
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::set_param nodepath
-//  Access: Public
-//  Description: Store nodepath in the map to associate with 
-//               param name
-////////////////////////////////////////////////////////////////////
-void ShaderMode::
-set_param(const string &pname, const NodePath &x) {
-  ShaderModeArg *arg = mod_param(pname, ShaderModeArg::SAT_NODEPATH);
-  arg->_nvalue = x;
-}
-
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::set_param 1f
-//  Access: Public
-//  Description: Store 1f in the map to associate with 
-//               param name
-////////////////////////////////////////////////////////////////////
-void ShaderMode::
-set_param(const string &pname, float x) {
-  ShaderModeArg *arg = mod_param(pname, ShaderModeArg::SAT_FLOAT);
-  arg->_fvalue = LVector4d(x,0,0,0);
-}
-
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::set_param 2f
-//  Access: Public
-//  Description: Store 2f in the map to associate with 
-//               param name
-////////////////////////////////////////////////////////////////////
-void ShaderMode::
-set_param(const string &pname, LVector2f x) {
-  ShaderModeArg *arg = mod_param(pname, ShaderModeArg::SAT_FLOAT);
-  arg->_fvalue = LVector4d(x[0],x[1],0,0);
-}
-
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::set_param 3f
-//  Access: Public
-//  Description: Store 3f in the map to associate with 
-//               param name
-////////////////////////////////////////////////////////////////////
-void ShaderMode::
-set_param(const string &pname, LVector3f x) {
-  ShaderModeArg *arg = mod_param(pname, ShaderModeArg::SAT_FLOAT);
-  arg->_fvalue = LVector4d(x[0],x[1],x[2],0);
-}
-
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::set_param 4f
-//  Access: Public
-//  Description: Store 4f in the map to associate with 
-//               param name
-////////////////////////////////////////////////////////////////////
-void ShaderMode::
-set_param(const string &pname, LVector4f x) {
-  ShaderModeArg *arg = mod_param(pname, ShaderModeArg::SAT_FLOAT);
-  arg->_fvalue = LVector4d(x[0],x[1],x[2],x[3]);
-}
-
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::set_param 1d
-//  Access: Public
-//  Description: Store 1d in the map to associate with 
-//               param name
-////////////////////////////////////////////////////////////////////
-void ShaderMode::
-set_param(const string &pname, double x) {
-  ShaderModeArg *arg = mod_param(pname, ShaderModeArg::SAT_FLOAT);
-  arg->_fvalue = LVector4d(x,0,0,0);
-}
-
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::set_param 2d
-//  Access: Public
-//  Description: Store 2d in the map to associate with 
-//               param name
-////////////////////////////////////////////////////////////////////
-void ShaderMode::
-set_param(const string &pname, LVector2d x) {
-  ShaderModeArg *arg = mod_param(pname, ShaderModeArg::SAT_FLOAT);
-  arg->_fvalue = LVector4d(x[0],x[1],0,0);
-}
-
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::set_param 3d
-//  Access: Public
-//  Description: Store 3d in the map to associate with 
-//               param name
-////////////////////////////////////////////////////////////////////
-void ShaderMode::
-set_param(const string &pname, LVector3d x) {
-  ShaderModeArg *arg = mod_param(pname, ShaderModeArg::SAT_FLOAT);
-  arg->_fvalue = LVector4d(x[0],x[1],x[2],0);
-}
-
-////////////////////////////////////////////////////////////////////
-//  Function: ShaderMode::set_param 4d
-//  Access: Public
-//  Description: Store 4d in the map to associate with 
-//               param name
-////////////////////////////////////////////////////////////////////
-void ShaderMode::
-set_param(const string &pname, LVector4d x) {
-  ShaderModeArg *arg = mod_param(pname, ShaderModeArg::SAT_FLOAT);
-  arg->_fvalue = x;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ShaderMode::register_with_read_factory
-//       Access: Public, Static
-//  Description: Factory method to generate a ShaderMode object
-////////////////////////////////////////////////////////////////////
-void ShaderMode::
-register_with_read_factory() {
-  // IMPLEMENT ME
-}
-

+ 0 - 117
panda/src/pgraph/shaderMode.h

@@ -1,117 +0,0 @@
-// Filename: shaderMode.h
-// Created by:  jyelon (01Sep05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef SHADERMODE_H
-#define SHADERMODE_H
-
-#include "pandabase.h"
-#include "nodePath.h"
-
-////////////////////////////////////////////////////////////////////
-//       Class : ShaderModeArg
-// Description : The ShaderModeArg is a small structure designed to hold
-//               any of the various kinds of values that can be
-//               passed to a shader.  Basically, it is a temporary
-//               storage repository for shader input parameters.
-////////////////////////////////////////////////////////////////////
-
-class ShaderModeArg
-{
-public:
-  enum ShaderModeArgType
-  {
-    SAT_INVALID,
-    SAT_FLOAT,
-    SAT_TEXTURE,
-    SAT_NODEPATH,
-  };
-
-  INLINE ShaderModeArg();
-  INLINE ~ShaderModeArg();
-  
-  int         _type;
-  NodePath    _nvalue;
-  PT(Texture) _tvalue;
-  LVector4d   _fvalue;
-};
-
-////////////////////////////////////////////////////////////////////
-//       Class : ShaderMode
-//      Summary: The ShaderMode object contains a Shader and a
-//               list of input data to pass into the shader when
-//               it is executing.
-////////////////////////////////////////////////////////////////////
-
-class EXPCL_PANDA ShaderMode: public TypedWritableReferenceCount {
-
-public:
-  PT(Shader)            _shader;
-  vector<ShaderModeArg> _args;
-
-PUBLISHED:
-  ShaderMode(Shader *body);
-
-  static PT(ShaderMode) load(const string   &file);
-  static PT(ShaderMode) load(const Filename &file);
-  static PT(ShaderMode) make(const string   &text);
-  
-  ~ShaderMode();
-  
-  INLINE Shader *get_shader();
-  
-  // Overloaded set_param to be used based on your param type
-  void set_param(const string &pname, Texture *t);
-  void set_param(const string &pname, const NodePath  &np);
-  void set_param(const string &pname, float     p1f);
-  void set_param(const string &pname, LVector2f p2f);
-  void set_param(const string &pname, LVector3f p3f);
-  void set_param(const string &pname, LVector4f p4f);
-  void set_param(const string &pname, double    p1d);
-  void set_param(const string &pname, LVector2d p2d);
-  void set_param(const string &pname, LVector3d p3d);
-  void set_param(const string &pname, LVector4d p4d);
-
-  static void register_with_read_factory();
-
-private:
-  ShaderModeArg *mod_param(const string &pname, int kind);
-  
-public:
-  static TypeHandle get_class_type() {
-    return _type_handle;
-  }
-  static void init_type() {
-    TypedWritableReferenceCount::init_type();
-    register_type(_type_handle, "ShaderMode",
-                  TypedWritableReferenceCount::get_class_type());
-  }
-  virtual TypeHandle get_type() const {
-    return get_class_type();
-  }
-  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
-
-private:
-  static TypeHandle _type_handle;
-};
-
-
-#include "shaderMode.I"
-
-#endif
-
-

+ 2 - 3
panda/src/pgraph/texGenAttrib.cxx

@@ -540,9 +540,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TexGenAttrib::store_into_slot
 //     Function: TexGenAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TexGenAttrib::
 void TexGenAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/texMatrixAttrib.cxx

@@ -429,9 +429,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TexMatrixAttrib::store_into_slot
 //     Function: TexMatrixAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TexMatrixAttrib::
 void TexMatrixAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/textureAttrib.cxx

@@ -688,9 +688,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TextureAttrib::store_into_slot
 //     Function: TextureAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TextureAttrib::
 void TextureAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

+ 2 - 3
panda/src/pgraph/transparencyAttrib.cxx

@@ -117,9 +117,8 @@ make_default_impl() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TransparencyAttrib::store_into_slot
 //     Function: TransparencyAttrib::store_into_slot
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: When attribs are stored in a slot-based attrib array,
-//               this returns the index of the appropriate slot
-//               for this attrib type.
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TransparencyAttrib::
 void TransparencyAttrib::
 store_into_slot(AttribSlots *slots) const {
 store_into_slot(AttribSlots *slots) const {

Some files were not shown because too many files changed in this diff