Browse Source

Added texture handling in shader code

Josh Yelon 20 years ago
parent
commit
0c7e721e79

+ 2 - 2
doc/makepanda/makepanda71.vcproj

@@ -17,8 +17,8 @@
 			ConfigurationType="0">
 			ConfigurationType="0">
 			<Tool
 			<Tool
 				Name="VCNMakeTool"
 				Name="VCNMakeTool"
-				BuildCommandLine="cd .. &amp; makepanda\makepanda --everything --installer"
-				Output="..\built\bin\flt2egg.exe"/>
+				BuildCommandLine="cd .. &amp; makepanda\makepanda --everything"
+				Output="..\built\python\python.exe"/>
 		</Configuration>
 		</Configuration>
 	</Configurations>
 	</Configurations>
 	<References>
 	<References>

+ 413 - 365
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -757,6 +757,8 @@ reset() {
   _current_shader_context = (CLP(ShaderContext) *)NULL;
   _current_shader_context = (CLP(ShaderContext) *)NULL;
   _vertex_array_shader_expansion = (ShaderExpansion *)NULL;
   _vertex_array_shader_expansion = (ShaderExpansion *)NULL;
   _vertex_array_shader_context = (CLP(ShaderContext) *)NULL;
   _vertex_array_shader_context = (CLP(ShaderContext) *)NULL;
+  _texture_binding_shader_expansion = (ShaderExpansion *)NULL;
+  _texture_binding_shader_context = (CLP(ShaderContext) *)NULL;
   
   
   // Count the max number of lights
   // Count the max number of lights
   GLint max_lights;
   GLint max_lights;
@@ -840,20 +842,20 @@ do_clear(const RenderBuffer &buffer) {
   int buffer_type = buffer._buffer_type;
   int buffer_type = buffer._buffer_type;
   GLbitfield mask = 0;
   GLbitfield mask = 0;
 
 
+  set_state_and_transform(RenderState::make_empty(), _external_transform);
+
   if (buffer_type & RenderBuffer::T_color) {
   if (buffer_type & RenderBuffer::T_color) {
     GLP(ClearColor)(_color_clear_value[0],
     GLP(ClearColor)(_color_clear_value[0],
                     _color_clear_value[1],
                     _color_clear_value[1],
                     _color_clear_value[2],
                     _color_clear_value[2],
                     _color_clear_value[3]);
                     _color_clear_value[3]);
     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;
-    _target._depth_write = AttribSlots::get_defaults()._depth_write;
   }
   }
 
 
   if (buffer_type & RenderBuffer::T_stencil) {
   if (buffer_type & RenderBuffer::T_stencil) {
@@ -886,20 +888,6 @@ do_clear(const RenderBuffer &buffer) {
     GLCAT.spam(false) << ")" << endl;
     GLCAT.spam(false) << ")" << endl;
   }
   }
   
   
-  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();
 }
 }
@@ -1598,15 +1586,15 @@ draw_triangles(const GeomTriangles *primitive) {
       const unsigned char *client_pointer = setup_primitive(primitive);
       const unsigned char *client_pointer = setup_primitive(primitive);
       
       
       _glDrawRangeElements(GL_TRIANGLES, 
       _glDrawRangeElements(GL_TRIANGLES, 
-			   primitive->get_min_vertex(),
-			   primitive->get_max_vertex(),
-			   primitive->get_num_vertices(),
-			   get_numeric_type(primitive->get_index_type()), 
-			   client_pointer);
+                           primitive->get_min_vertex(),
+                           primitive->get_max_vertex(),
+                           primitive->get_num_vertices(),
+                           get_numeric_type(primitive->get_index_type()), 
+                           client_pointer);
     } else {
     } else {
       GLP(DrawArrays)(GL_TRIANGLES,
       GLP(DrawArrays)(GL_TRIANGLES,
-		      primitive->get_first_vertex(),
-		      primitive->get_num_vertices());
+                      primitive->get_first_vertex(),
+                      primitive->get_num_vertices());
     }
     }
   }
   }
   
   
@@ -1642,17 +1630,17 @@ draw_tristrips(const GeomTristrips *primitive) {
       _vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
       _vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
       _primitive_batches_tristrip_pcollector.add_level(1);
       _primitive_batches_tristrip_pcollector.add_level(1);
       if (primitive->is_indexed()) {
       if (primitive->is_indexed()) {
-	const unsigned char *client_pointer = setup_primitive(primitive);
-	_glDrawRangeElements(GL_TRIANGLE_STRIP, 
-			     primitive->get_min_vertex(),
-			     primitive->get_max_vertex(),
-			     primitive->get_num_vertices(),
-			     get_numeric_type(primitive->get_index_type()), 
-			     client_pointer);
+        const unsigned char *client_pointer = setup_primitive(primitive);
+        _glDrawRangeElements(GL_TRIANGLE_STRIP, 
+                             primitive->get_min_vertex(),
+                             primitive->get_max_vertex(),
+                             primitive->get_num_vertices(),
+                             get_numeric_type(primitive->get_index_type()), 
+                             client_pointer);
       } else {
       } else {
-	GLP(DrawArrays)(GL_TRIANGLE_STRIP,
-			primitive->get_first_vertex(),
-			primitive->get_num_vertices());
+        GLP(DrawArrays)(GL_TRIANGLE_STRIP,
+                        primitive->get_first_vertex(),
+                        primitive->get_num_vertices());
       }
       }
       
       
     } else {
     } else {
@@ -1662,32 +1650,32 @@ draw_tristrips(const GeomTristrips *primitive) {
       
       
       _primitive_batches_tristrip_pcollector.add_level(ends.size());
       _primitive_batches_tristrip_pcollector.add_level(ends.size());
       if (primitive->is_indexed()) {
       if (primitive->is_indexed()) {
-	const unsigned char *client_pointer = setup_primitive(primitive);
-	int index_stride = primitive->get_index_stride();
-	GeomVertexReader mins(primitive->get_mins(), 0);
-	GeomVertexReader maxs(primitive->get_maxs(), 0);
-	nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && 
-		 primitive->get_maxs()->get_num_rows() == (int)ends.size());
-	
-	unsigned int start = 0;
-	for (size_t i = 0; i < ends.size(); i++) {
-	  _vertices_tristrip_pcollector.add_level(ends[i] - start);
-	  _glDrawRangeElements(GL_TRIANGLE_STRIP, 
-			       mins.get_data1i(), maxs.get_data1i(), 
-			       ends[i] - start,
-			       get_numeric_type(primitive->get_index_type()), 
-			       client_pointer + start * index_stride);
-	  start = ends[i] + 2;
-	}
+        const unsigned char *client_pointer = setup_primitive(primitive);
+        int index_stride = primitive->get_index_stride();
+        GeomVertexReader mins(primitive->get_mins(), 0);
+        GeomVertexReader maxs(primitive->get_maxs(), 0);
+        nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && 
+                 primitive->get_maxs()->get_num_rows() == (int)ends.size());
+        
+        unsigned int start = 0;
+        for (size_t i = 0; i < ends.size(); i++) {
+          _vertices_tristrip_pcollector.add_level(ends[i] - start);
+          _glDrawRangeElements(GL_TRIANGLE_STRIP, 
+                               mins.get_data1i(), maxs.get_data1i(), 
+                               ends[i] - start,
+                               get_numeric_type(primitive->get_index_type()), 
+                               client_pointer + start * index_stride);
+          start = ends[i] + 2;
+        }
       } else {
       } else {
-	unsigned int start = 0;
-	int first_vertex = primitive->get_first_vertex();
-	for (size_t i = 0; i < ends.size(); i++) {
-	  _vertices_tristrip_pcollector.add_level(ends[i] - start);
-	  GLP(DrawArrays)(GL_TRIANGLE_STRIP, first_vertex + start, 
-			  ends[i] - start);
-	  start = ends[i] + 2;
-	}
+        unsigned int start = 0;
+        int first_vertex = primitive->get_first_vertex();
+        for (size_t i = 0; i < ends.size(); i++) {
+          _vertices_tristrip_pcollector.add_level(ends[i] - start);
+          GLP(DrawArrays)(GL_TRIANGLE_STRIP, first_vertex + start, 
+                          ends[i] - start);
+          start = ends[i] + 2;
+        }
       }
       }
     }
     }
   }
   }
@@ -2453,12 +2441,7 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
   // for GLP(ReadPixels)() to work
   // for GLP(ReadPixels)() to work
   // 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;
-  if (_target._texture != _state._texture) {
-    do_issue_texture();
-    _state._texture = _target._texture;
-  }
-  _state_rs = 0;
+  set_state_and_transform(RenderState::make_empty(), _external_transform);
   
   
   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);
@@ -3086,7 +3069,7 @@ do_issue_blending() {
   } else {
   } else {
     if (_target._color_write != _state._color_write) {
     if (_target._color_write != _state._color_write) {
       if (CLP(color_mask)) {
       if (CLP(color_mask)) {
-	unsigned int channels = _target._color_write->get_channels();
+        unsigned int channels = _target._color_write->get_channels();
         GLP(ColorMask)((channels & ColorWriteAttrib::C_red) != 0,
         GLP(ColorMask)((channels & ColorWriteAttrib::C_red) != 0,
                        (channels & ColorWriteAttrib::C_green) != 0,
                        (channels & ColorWriteAttrib::C_green) != 0,
                        (channels & ColorWriteAttrib::C_blue) != 0,
                        (channels & ColorWriteAttrib::C_blue) != 0,
@@ -3576,7 +3559,7 @@ is_at_least_version(int major_version, int minor_version,
       return false;
       return false;
     } else if (_gl_version_minor == minor_version) {
     } else if (_gl_version_minor == minor_version) {
       if (_gl_version_release < release_version) {
       if (_gl_version_release < release_version) {
-	return false;
+        return false;
       }
       }
     }
     }
   }
   }
@@ -4592,9 +4575,6 @@ set_state_and_transform(const RenderState *target,
   // attributes we issue.  Impose them now.
   // attributes we issue.  Impose them now.
   _target._texture = _target._texture->filter_to_max(_max_texture_stages);
   _target._texture = _target._texture->filter_to_max(_max_texture_stages);
 
 
-  bool needs_tex_gen = false;
-  bool needs_tex_mat = false;
-
   if (_target._alpha_test != _state._alpha_test) {
   if (_target._alpha_test != _state._alpha_test) {
     do_issue_alpha_test();
     do_issue_alpha_test();
     _state._alpha_test = _target._alpha_test;
     _state._alpha_test = _target._alpha_test;
@@ -4660,22 +4640,6 @@ set_state_and_transform(const RenderState *target,
     _state._shade_model = _target._shade_model;
     _state._shade_model = _target._shade_model;
   }
   }
   
   
-  if (_target._shader != _state._shader) {
-    do_issue_shader();
-    _state._shader = _target._shader;
-  }
-  
-  if (_target._tex_gen != _state._tex_gen) {
-    _state._tex_gen = _target._tex_gen;
-    needs_tex_gen = true;
-    _state._tex_gen = _target._tex_gen;
-  }
-  
-  if (_target._tex_matrix != _state._tex_matrix) {
-    needs_tex_mat = true;
-    _state._tex_matrix = _target._tex_matrix;
-  }
-  
   if ((_target._transparency != _state._transparency)||
   if ((_target._transparency != _state._transparency)||
       (_target._color_write != _state._color_write)||
       (_target._color_write != _state._color_write)||
       (_target._color_blend != _state._color_blend)) {
       (_target._color_blend != _state._color_blend)) {
@@ -4685,16 +4649,19 @@ set_state_and_transform(const RenderState *target,
     _state._color_blend = _target._color_blend;
     _state._color_blend = _target._color_blend;
   }
   }
   
   
+  if (_target._shader != _state._shader) {
+    do_issue_shader();
+    _state._shader = _target._shader;
+    _state._texture = 0;
+  }
+  
   if (_target._texture != _state._texture) {
   if (_target._texture != _state._texture) {
     do_issue_texture();
     do_issue_texture();
     _state._texture = _target._texture;
     _state._texture = _target._texture;
-
-    // Changing the set of texture stages will require us to reissue the
-    // texgen and texmat attribs.
-    needs_tex_gen = true;
-    needs_tex_mat = true;
+    _state._tex_gen = 0;
+    _state._tex_matrix = 0;
   }
   }
-
+  
   if (_target._material != _state._material) {
   if (_target._material != _state._material) {
     do_issue_material();
     do_issue_material();
     _state._material = _target._material;
     _state._material = _target._material;
@@ -4708,278 +4675,24 @@ set_state_and_transform(const RenderState *target,
   // If one of the previously-loaded TexGen modes modified the texture
   // If one of the previously-loaded TexGen modes modified the texture
   // matrix, then if either state changed, we have to change both of
   // matrix, then if either state changed, we have to change both of
   // them now.
   // them now.
-  if (_tex_gen_modifies_mat && (needs_tex_mat || needs_tex_gen)) {
-    needs_tex_mat = true;
-    needs_tex_gen = true;
-  }
-
-  // Apply the texture matrix, if needed.
-  if (needs_tex_mat) {
-    int num_stages = _state._texture->get_num_on_stages();
-    nassertv(num_stages <= _max_texture_stages);
-    
-    for (int i = 0; i < num_stages; i++) {
-      TextureStage *stage = _state._texture->get_on_stage(i);
-      _glActiveTexture(GL_TEXTURE0 + i);
-      
-      GLP(MatrixMode)(GL_TEXTURE);
-      if (_state._tex_matrix->has_stage(stage)) {
-        GLP(LoadMatrixf)(_state._tex_matrix->get_mat(stage).get_data());
-      } else {
-        GLP(LoadIdentity)();
-
-        // For some reason, the glLoadIdentity() call doesn't work on
-        // my Dell laptop's IBM OpenGL driver, when used in
-        // conjunction with glTexGen(), below.  But explicitly loading
-        // an identity matrix does work.  But this buggy-driver
-        // workaround might have other performance implications, so I
-        // leave it out.
-        //GLP(LoadMatrixf)(LMatrix4f::ident_mat().get_data());
-      }
+  if (_tex_gen_modifies_mat) {
+    if ((_target._tex_gen != _state._tex_gen) ||
+        (_target._tex_matrix != _state._tex_matrix)) {
+      _state._tex_matrix = 0;
+      _state._tex_gen = 0;
     }
     }
-    report_my_gl_errors();
   }
   }
-
-  if (needs_tex_gen) {
-    bool force_normal = false;
-
-    int num_stages = _state._texture->get_num_on_stages();
-    nassertv(num_stages <= _max_texture_stages);
-    
-    // These are passed in for the four OBJECT_PLANE or EYE_PLANE
-    // values; they effectively define an identity matrix that maps
-    // the spatial coordinates one-for-one to UV's.  If you want a
-    // mapping other than identity, use a TexMatrixAttrib (or a
-    // TexProjectorEffect).
-    static const float s_data[4] = { 1, 0, 0, 0 };
-    static const float t_data[4] = { 0, 1, 0, 0 };
-    static const float r_data[4] = { 0, 0, 1, 0 };
-    static const float q_data[4] = { 0, 0, 0, 1 };
-
-    _tex_gen_modifies_mat = false;
-
-    bool got_point_sprites = false;
-    
-    for (int i = 0; i < num_stages; i++) {
-      TextureStage *stage = _state._texture->get_on_stage(i);
-      _glActiveTexture(GL_TEXTURE0 + i);
-      GLP(Disable)(GL_TEXTURE_GEN_S);
-      GLP(Disable)(GL_TEXTURE_GEN_T);
-      GLP(Disable)(GL_TEXTURE_GEN_R);
-      GLP(Disable)(GL_TEXTURE_GEN_Q);
-      if (_supports_point_sprite) {
-        GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE);
-      }
-
-      TexGenAttrib::Mode mode = _state._tex_gen->get_mode(stage);
-      switch (mode) {
-      case TexGenAttrib::M_off:
-      case TexGenAttrib::M_light_vector:
-        break;
-        
-      case TexGenAttrib::M_eye_sphere_map:
-        GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
-        GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
-        GLP(Enable)(GL_TEXTURE_GEN_S);
-        GLP(Enable)(GL_TEXTURE_GEN_T);
-        force_normal = true;
-        break;
-        
-      case TexGenAttrib::M_eye_cube_map:
-        if (_supports_cube_map) {
-          // We need to rotate the normals out of GL's coordinate
-          // system and into the user's coordinate system.  We do this
-          // by composing a transform onto the texture matrix.
-          LMatrix4f mat = _inv_cs_transform->get_mat();
-          mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f));
-          GLP(MatrixMode)(GL_TEXTURE);
-          GLP(MultMatrixf)(mat.get_data());
-          
-          // Now we need to reset the texture matrix next time
-          // around to undo this.
-          _tex_gen_modifies_mat = true;
-
-          GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
-          GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
-          GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
-          GLP(Enable)(GL_TEXTURE_GEN_S);
-          GLP(Enable)(GL_TEXTURE_GEN_T);
-          GLP(Enable)(GL_TEXTURE_GEN_R);
-          force_normal = true;
-        }
-        break;
-
-      case TexGenAttrib::M_world_cube_map:
-        if (_supports_cube_map) {
-          // We dynamically transform normals from eye space to world
-          // space by applying the appropriate rotation transform to
-          // the current texture matrix.  Unlike M_world_position, we
-          // can't achieve this effect by monkeying with the modelview
-          // transform, since the current modelview doesn't affect
-          // GL_REFLECTION_MAP.
-          CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
-
-          LMatrix4f mat = camera_transform->get_mat();
-          mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f));
-          GLP(MatrixMode)(GL_TEXTURE);
-          GLP(MultMatrixf)(mat.get_data());
-          
-          // Now we need to reset the texture matrix next time
-          // around to undo this.
-          _tex_gen_modifies_mat = true;
-
-          GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
-          GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
-          GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
-          GLP(Enable)(GL_TEXTURE_GEN_S);
-          GLP(Enable)(GL_TEXTURE_GEN_T);
-          GLP(Enable)(GL_TEXTURE_GEN_R);
-          force_normal = true;
-        }
-        break;
-        
-      case TexGenAttrib::M_eye_normal:
-        if (_supports_cube_map) {
-          // We need to rotate the normals out of GL's coordinate
-          // system and into the user's coordinate system.  We do this
-          // by composing a transform onto the texture matrix.
-          LMatrix4f mat = _inv_cs_transform->get_mat();
-          mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f));
-          GLP(MatrixMode)(GL_TEXTURE);
-          GLP(MultMatrixf)(mat.get_data());
-          
-          // Now we need to reset the texture matrix next time
-          // around to undo this.
-          _tex_gen_modifies_mat = true;
-
-          GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
-          GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
-          GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
-          GLP(Enable)(GL_TEXTURE_GEN_S);
-          GLP(Enable)(GL_TEXTURE_GEN_T);
-          GLP(Enable)(GL_TEXTURE_GEN_R);
-          force_normal = true;
-        }
-        break;
-
-      case TexGenAttrib::M_world_normal:
-        if (_supports_cube_map) {
-          // We dynamically transform normals from eye space to world
-          // space by applying the appropriate rotation transform to
-          // the current texture matrix.  Unlike M_world_position, we
-          // can't achieve this effect by monkeying with the modelview
-          // transform, since the current modelview doesn't affect
-          // GL_NORMAL_MAP.
-          CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
-
-          LMatrix4f mat = camera_transform->get_mat();
-          mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f));
-          GLP(MatrixMode)(GL_TEXTURE);
-          GLP(MultMatrixf)(mat.get_data());
-          
-          // Now we need to reset the texture matrix next time
-          // around to undo this.
-          _tex_gen_modifies_mat = true;
-
-          GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
-          GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
-          GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
-          GLP(Enable)(GL_TEXTURE_GEN_S);
-          GLP(Enable)(GL_TEXTURE_GEN_T);
-          GLP(Enable)(GL_TEXTURE_GEN_R);
-          force_normal = true;
-        }
-        break;
-
-      case TexGenAttrib::M_eye_position:
-        // To represent eye position correctly, we need to temporarily
-        // load the coordinate-system transform.
-        GLP(MatrixMode)(GL_MODELVIEW);
-        GLP(PushMatrix)();
-        GLP(LoadMatrixf)(_cs_transform->get_mat().get_data());
-
-        GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-        GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-        GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-        GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-        
-        GLP(TexGenfv)(GL_S, GL_EYE_PLANE, s_data);
-        GLP(TexGenfv)(GL_T, GL_EYE_PLANE, t_data);
-        GLP(TexGenfv)(GL_R, GL_EYE_PLANE, r_data);
-        GLP(TexGenfv)(GL_Q, GL_EYE_PLANE, q_data);
-        
-        GLP(Enable)(GL_TEXTURE_GEN_S);
-        GLP(Enable)(GL_TEXTURE_GEN_T);
-        GLP(Enable)(GL_TEXTURE_GEN_R);
-        GLP(Enable)(GL_TEXTURE_GEN_Q);
-
-        GLP(MatrixMode)(GL_MODELVIEW);
-        GLP(PopMatrix)();
-        break;
-
-      case TexGenAttrib::M_world_position:
-        // We achieve world position coordinates by using the eye
-        // position mode, and loading the transform of the root
-        // node--thus putting the "eye" at the root.
-        {
-          GLP(MatrixMode)(GL_MODELVIEW);
-          GLP(PushMatrix)();
-          CPT(TransformState) root_transform = _cs_transform->compose(_scene_setup->get_world_transform());
-          GLP(LoadMatrixf)(root_transform->get_mat().get_data());
-          GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-          GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-          GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-          GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-        
-          GLP(TexGenfv)(GL_S, GL_EYE_PLANE, s_data);
-          GLP(TexGenfv)(GL_T, GL_EYE_PLANE, t_data);
-          GLP(TexGenfv)(GL_R, GL_EYE_PLANE, r_data);
-          GLP(TexGenfv)(GL_Q, GL_EYE_PLANE, q_data);
-          
-          GLP(Enable)(GL_TEXTURE_GEN_S);
-          GLP(Enable)(GL_TEXTURE_GEN_T);
-          GLP(Enable)(GL_TEXTURE_GEN_R);
-          GLP(Enable)(GL_TEXTURE_GEN_Q);
-          
-          GLP(MatrixMode)(GL_MODELVIEW);
-          GLP(PopMatrix)();
-        }
-        break;
-
-      case TexGenAttrib::M_point_sprite:
-        nassertv(_supports_point_sprite);
-        GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
-        got_point_sprites = true;
-        break;
-
-      case TexGenAttrib::M_unused:
-        break;
-      }
-    }
-
-    if (got_point_sprites != _tex_gen_point_sprite) {
-      _tex_gen_point_sprite = got_point_sprites;
-      if (_tex_gen_point_sprite) {
-        GLP(Enable)(GL_POINT_SPRITE_ARB);
-      } else {
-        GLP(Disable)(GL_POINT_SPRITE_ARB);
-      }
-    }
-
-    // Certain texgen modes (sphere_map, cube_map) require forcing the
-    // normal to be sent to the GL while the texgen mode is in effect.
-    if (force_normal != _texgen_forced_normal) {
-      if (force_normal) {
-        force_normals();
-      } else  {
-        undo_force_normals();
-      }
-      _texgen_forced_normal = force_normal;
-    }
-
-    report_my_gl_errors();
+  
+  if (_target._tex_matrix != _state._tex_matrix) {
+    do_issue_tex_matrix();
+    _state._tex_matrix = _target._tex_matrix;
   }
   }
-
+  
+  if (_target._tex_gen != _state._tex_gen) {
+    do_issue_tex_gen();
+    _state._tex_gen = _target._tex_gen;
+  }
+  
   _state_rs = _target_rs;
   _state_rs = _target_rs;
 }
 }
 
 
@@ -5030,19 +4743,47 @@ do_auto_rescale_normal() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::do_issue_texture
 //     Function: GLGraphicsStateGuardian::do_issue_texture
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
-//  Description: This is called by finish_modify_state() when the
-//               texture state has changed.
+//  Description: This is called by set_state_and_transform() when
+//               the texture state has changed.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 void CLP(GraphicsStateGuardian)::
 do_issue_texture() {
 do_issue_texture() {
   DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
   DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
+  
+  if (_texture_binding_shader_context==0) {
+    if (_current_shader_context==0) {
+      update_standard_texture_bindings();
+    } else {
+      disable_standard_texture_bindings();
+      _current_shader_context->update_shader_texture_bindings(NULL,this);
+    }
+  } else {
+    if (_current_shader_context==0) {
+      _texture_binding_shader_context->disable_shader_texture_bindings(this);
+      update_standard_texture_bindings();
+    } else {
+      _current_shader_context->
+        update_shader_texture_bindings(_texture_binding_shader_context,this);
+    }
+  }
+  _texture_binding_shader_expansion = _current_shader_expansion;
+  _texture_binding_shader_context = _current_shader_context;
+}
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::update_standard_texture_bindings
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+update_standard_texture_bindings()
+{
   int num_stages = _target._texture->get_num_on_stages();
   int num_stages = _target._texture->get_num_on_stages();
   int num_old_stages = _max_texture_stages;
   int num_old_stages = _max_texture_stages;
   if (_state._texture != (TextureAttrib *)NULL) {
   if (_state._texture != (TextureAttrib *)NULL) {
     num_old_stages = _state._texture->get_num_on_stages();
     num_old_stages = _state._texture->get_num_on_stages();
   }
   }
-
+  
   nassertv(num_stages <= _max_texture_stages && 
   nassertv(num_stages <= _max_texture_stages && 
            num_old_stages <= _max_texture_stages);
            num_old_stages <= _max_texture_stages);
 
 
@@ -5057,7 +4798,7 @@ do_issue_texture() {
     nassertv(texture != (Texture *)NULL);
     nassertv(texture != (Texture *)NULL);
     
     
     if (i >= num_old_stages ||
     if (i >= num_old_stages ||
-	_state._texture == (TextureAttrib *)NULL ||
+        _state._texture == (TextureAttrib *)NULL ||
         stage != _state._texture->get_on_stage(i) ||
         stage != _state._texture->get_on_stage(i) ||
         texture != _state._texture->get_on_texture(stage) ||
         texture != _state._texture->get_on_texture(stage) ||
         stage->involves_color_scale()) {
         stage->involves_color_scale()) {
@@ -5202,7 +4943,7 @@ do_issue_texture() {
       }
       }
 
 
       GLP(MatrixMode)(GL_TEXTURE);
       GLP(MatrixMode)(GL_TEXTURE);
-      if (_state._tex_matrix->has_stage(stage)) {
+      if (_target._tex_matrix->has_stage(stage)) {
         GLP(LoadMatrixf)(_state._tex_matrix->get_mat(stage).get_data());
         GLP(LoadMatrixf)(_state._tex_matrix->get_mat(stage).get_data());
       } else {
       } else {
         GLP(LoadIdentity)();
         GLP(LoadIdentity)();
@@ -5236,6 +4977,313 @@ do_issue_texture() {
   report_my_gl_errors();
   report_my_gl_errors();
 }
 }
 
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::disable_standard_texture_bindings
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+disable_standard_texture_bindings() {
+  int num_old_stages = _max_texture_stages;
+  if (_state._texture != (TextureAttrib *)NULL) {
+    num_old_stages = _state._texture->get_num_on_stages();
+  }
+
+  // Disable the texture stages that are no longer used.
+  for (int i = 0; i < num_old_stages; i++) {
+    _glActiveTexture(GL_TEXTURE0 + i);
+    GLP(Disable)(GL_TEXTURE_1D);
+    GLP(Disable)(GL_TEXTURE_2D);
+    if (_supports_3d_texture) {
+      GLP(Disable)(GL_TEXTURE_3D);
+    }
+    if (_supports_cube_map) {
+      GLP(Disable)(GL_TEXTURE_CUBE_MAP);
+    }
+  }
+  
+  report_my_gl_errors();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::do_issue_tex_matrix
+//       Access: Protected
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+do_issue_tex_matrix() {
+  int num_stages = _target._texture->get_num_on_stages();
+  nassertv(num_stages <= _max_texture_stages);
+  
+  for (int i = 0; i < num_stages; i++) {
+    TextureStage *stage = _target._texture->get_on_stage(i);
+    _glActiveTexture(GL_TEXTURE0 + i);
+    
+    GLP(MatrixMode)(GL_TEXTURE);
+    if (_target._tex_matrix->has_stage(stage)) {
+      GLP(LoadMatrixf)(_target._tex_matrix->get_mat(stage).get_data());
+    } else {
+      GLP(LoadIdentity)();
+      
+      // For some reason, the glLoadIdentity() call doesn't work on
+      // my Dell laptop's IBM OpenGL driver, when used in
+      // conjunction with glTexGen(), below.  But explicitly loading
+      // an identity matrix does work.  But this buggy-driver
+      // workaround might have other performance implications, so I
+      // leave it out.
+      //GLP(LoadMatrixf)(LMatrix4f::ident_mat().get_data());
+    }
+  }
+  report_my_gl_errors();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::do_issue_tex_gen
+//       Access: Protected
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+do_issue_tex_gen() {
+  bool force_normal = false;
+
+  int num_stages = _target._texture->get_num_on_stages();
+  nassertv(num_stages <= _max_texture_stages);
+  
+  // These are passed in for the four OBJECT_PLANE or EYE_PLANE
+  // values; they effectively define an identity matrix that maps
+  // the spatial coordinates one-for-one to UV's.  If you want a
+  // mapping other than identity, use a TexMatrixAttrib (or a
+  // TexProjectorEffect).
+  static const float s_data[4] = { 1, 0, 0, 0 };
+  static const float t_data[4] = { 0, 1, 0, 0 };
+  static const float r_data[4] = { 0, 0, 1, 0 };
+  static const float q_data[4] = { 0, 0, 0, 1 };
+  
+  _tex_gen_modifies_mat = false;
+  
+  bool got_point_sprites = false;
+  
+  for (int i = 0; i < num_stages; i++) {
+    TextureStage *stage = _target._texture->get_on_stage(i);
+    _glActiveTexture(GL_TEXTURE0 + i);
+    GLP(Disable)(GL_TEXTURE_GEN_S);
+    GLP(Disable)(GL_TEXTURE_GEN_T);
+    GLP(Disable)(GL_TEXTURE_GEN_R);
+    GLP(Disable)(GL_TEXTURE_GEN_Q);
+    if (_supports_point_sprite) {
+      GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE);
+    }
+    
+    TexGenAttrib::Mode mode = _target._tex_gen->get_mode(stage);
+    switch (mode) {
+    case TexGenAttrib::M_off:
+    case TexGenAttrib::M_light_vector:
+      break;
+      
+    case TexGenAttrib::M_eye_sphere_map:
+      GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+      GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+      GLP(Enable)(GL_TEXTURE_GEN_S);
+      GLP(Enable)(GL_TEXTURE_GEN_T);
+      force_normal = true;
+      break;
+      
+    case TexGenAttrib::M_eye_cube_map:
+      if (_supports_cube_map) {
+        // We need to rotate the normals out of GL's coordinate
+        // system and into the user's coordinate system.  We do this
+        // by composing a transform onto the texture matrix.
+        LMatrix4f mat = _inv_cs_transform->get_mat();
+        mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f));
+        GLP(MatrixMode)(GL_TEXTURE);
+        GLP(MultMatrixf)(mat.get_data());
+        
+        // Now we need to reset the texture matrix next time
+        // around to undo this.
+        _tex_gen_modifies_mat = true;
+        
+        GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+        GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+        GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+        GLP(Enable)(GL_TEXTURE_GEN_S);
+        GLP(Enable)(GL_TEXTURE_GEN_T);
+        GLP(Enable)(GL_TEXTURE_GEN_R);
+        force_normal = true;
+      }
+      break;
+      
+    case TexGenAttrib::M_world_cube_map:
+      if (_supports_cube_map) {
+        // We dynamically transform normals from eye space to world
+        // space by applying the appropriate rotation transform to
+        // the current texture matrix.  Unlike M_world_position, we
+        // can't achieve this effect by monkeying with the modelview
+        // transform, since the current modelview doesn't affect
+        // GL_REFLECTION_MAP.
+        CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
+        
+        LMatrix4f mat = camera_transform->get_mat();
+        mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f));
+        GLP(MatrixMode)(GL_TEXTURE);
+        GLP(MultMatrixf)(mat.get_data());
+        
+        // Now we need to reset the texture matrix next time
+        // around to undo this.
+        _tex_gen_modifies_mat = true;
+        
+        GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+        GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+        GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+        GLP(Enable)(GL_TEXTURE_GEN_S);
+        GLP(Enable)(GL_TEXTURE_GEN_T);
+        GLP(Enable)(GL_TEXTURE_GEN_R);
+        force_normal = true;
+      }
+      break;
+      
+    case TexGenAttrib::M_eye_normal:
+      if (_supports_cube_map) {
+        // We need to rotate the normals out of GL's coordinate
+        // system and into the user's coordinate system.  We do this
+        // by composing a transform onto the texture matrix.
+        LMatrix4f mat = _inv_cs_transform->get_mat();
+        mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f));
+        GLP(MatrixMode)(GL_TEXTURE);
+        GLP(MultMatrixf)(mat.get_data());
+        
+        // Now we need to reset the texture matrix next time
+        // around to undo this.
+        _tex_gen_modifies_mat = true;
+        
+        GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
+        GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
+        GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
+        GLP(Enable)(GL_TEXTURE_GEN_S);
+        GLP(Enable)(GL_TEXTURE_GEN_T);
+        GLP(Enable)(GL_TEXTURE_GEN_R);
+        force_normal = true;
+      }
+      break;
+      
+    case TexGenAttrib::M_world_normal:
+      if (_supports_cube_map) {
+        // We dynamically transform normals from eye space to world
+        // space by applying the appropriate rotation transform to
+        // the current texture matrix.  Unlike M_world_position, we
+        // can't achieve this effect by monkeying with the modelview
+        // transform, since the current modelview doesn't affect
+        // GL_NORMAL_MAP.
+        CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform);
+        
+        LMatrix4f mat = camera_transform->get_mat();
+        mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f));
+        GLP(MatrixMode)(GL_TEXTURE);
+        GLP(MultMatrixf)(mat.get_data());
+        
+        // Now we need to reset the texture matrix next time
+        // around to undo this.
+        _tex_gen_modifies_mat = true;
+        
+        GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
+        GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
+        GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
+        GLP(Enable)(GL_TEXTURE_GEN_S);
+        GLP(Enable)(GL_TEXTURE_GEN_T);
+        GLP(Enable)(GL_TEXTURE_GEN_R);
+        force_normal = true;
+      }
+      break;
+      
+    case TexGenAttrib::M_eye_position:
+      // To represent eye position correctly, we need to temporarily
+      // load the coordinate-system transform.
+      GLP(MatrixMode)(GL_MODELVIEW);
+      GLP(PushMatrix)();
+      GLP(LoadMatrixf)(_cs_transform->get_mat().get_data());
+      
+      GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+      GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+      GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+      GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+      
+      GLP(TexGenfv)(GL_S, GL_EYE_PLANE, s_data);
+      GLP(TexGenfv)(GL_T, GL_EYE_PLANE, t_data);
+      GLP(TexGenfv)(GL_R, GL_EYE_PLANE, r_data);
+      GLP(TexGenfv)(GL_Q, GL_EYE_PLANE, q_data);
+      
+      GLP(Enable)(GL_TEXTURE_GEN_S);
+      GLP(Enable)(GL_TEXTURE_GEN_T);
+      GLP(Enable)(GL_TEXTURE_GEN_R);
+      GLP(Enable)(GL_TEXTURE_GEN_Q);
+      
+      GLP(MatrixMode)(GL_MODELVIEW);
+      GLP(PopMatrix)();
+      break;
+      
+    case TexGenAttrib::M_world_position:
+      // We achieve world position coordinates by using the eye
+      // position mode, and loading the transform of the root
+      // node--thus putting the "eye" at the root.
+      {
+        GLP(MatrixMode)(GL_MODELVIEW);
+        GLP(PushMatrix)();
+        CPT(TransformState) root_transform = _cs_transform->compose(_scene_setup->get_world_transform());
+        GLP(LoadMatrixf)(root_transform->get_mat().get_data());
+        GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+        GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+        GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+        GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+        
+        GLP(TexGenfv)(GL_S, GL_EYE_PLANE, s_data);
+        GLP(TexGenfv)(GL_T, GL_EYE_PLANE, t_data);
+        GLP(TexGenfv)(GL_R, GL_EYE_PLANE, r_data);
+        GLP(TexGenfv)(GL_Q, GL_EYE_PLANE, q_data);
+        
+        GLP(Enable)(GL_TEXTURE_GEN_S);
+        GLP(Enable)(GL_TEXTURE_GEN_T);
+        GLP(Enable)(GL_TEXTURE_GEN_R);
+        GLP(Enable)(GL_TEXTURE_GEN_Q);
+        
+        GLP(MatrixMode)(GL_MODELVIEW);
+        GLP(PopMatrix)();
+      }
+      break;
+      
+    case TexGenAttrib::M_point_sprite:
+      nassertv(_supports_point_sprite);
+      GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
+      got_point_sprites = true;
+      break;
+      
+    case TexGenAttrib::M_unused:
+      break;
+    }
+  }
+  
+  if (got_point_sprites != _tex_gen_point_sprite) {
+    _tex_gen_point_sprite = got_point_sprites;
+    if (_tex_gen_point_sprite) {
+      GLP(Enable)(GL_POINT_SPRITE_ARB);
+    } else {
+      GLP(Disable)(GL_POINT_SPRITE_ARB);
+    }
+  }
+  
+  // Certain texgen modes (sphere_map, cube_map) require forcing the
+  // normal to be sent to the GL while the texgen mode is in effect.
+  if (force_normal != _texgen_forced_normal) {
+    if (force_normal) {
+      force_normals();
+    } else  {
+      undo_force_normals();
+    }
+    _texgen_forced_normal = force_normal;
+  }
+  
+  report_my_gl_errors();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::specify_texture
 //     Function: GLGraphicsStateGuardian::specify_texture
 //       Access: Protected
 //       Access: Protected

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

@@ -177,6 +177,8 @@ protected:
   void do_issue_material();
   void do_issue_material();
   void do_issue_texture();
   void do_issue_texture();
   void do_issue_blending();
   void do_issue_blending();
+  void do_issue_tex_gen();
+  void do_issue_tex_matrix();
 
 
   static bool report_errors_loop(int line, const char *source_file, 
   static bool report_errors_loop(int line, const char *source_file, 
                                  GLenum error_code, int &error_count);
                                  GLenum error_code, int &error_count);
@@ -249,6 +251,8 @@ protected:
 
 
   void disable_standard_vertex_arrays();
   void disable_standard_vertex_arrays();
   void update_standard_vertex_arrays();
   void update_standard_vertex_arrays();
+  void disable_standard_texture_bindings();
+  void update_standard_texture_bindings();
 
 
   void do_auto_rescale_normal();
   void do_auto_rescale_normal();
   void specify_texture(Texture *tex);
   void specify_texture(Texture *tex);
@@ -310,6 +314,8 @@ protected:
   CLP(ShaderContext)  *_current_shader_context;
   CLP(ShaderContext)  *_current_shader_context;
   PT(ShaderExpansion)  _vertex_array_shader_expansion;
   PT(ShaderExpansion)  _vertex_array_shader_expansion;
   CLP(ShaderContext)  *_vertex_array_shader_context;
   CLP(ShaderContext)  *_vertex_array_shader_context;
+  PT(ShaderExpansion)  _texture_binding_shader_expansion;
+  CLP(ShaderContext)  *_texture_binding_shader_context;
   
   
   CPT(DisplayRegion) _actual_display_region;
   CPT(DisplayRegion) _actual_display_region;
 
 

+ 147 - 10
panda/src/glstuff/glShaderContext_src.cxx

@@ -307,6 +307,84 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
 #endif // HAVE_CGGL
 #endif // HAVE_CGGL
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLShaderContext::disable_shader_texture_bindings
+//       Access: Public
+//  Description: Disable all the texture bindings used by this shader.
+////////////////////////////////////////////////////////////////////
+void CLP(ShaderContext)::
+disable_shader_texture_bindings(GSG *gsg)
+{
+#ifdef HAVE_CGGL
+  if (_cg_context) {
+    for (int i=0; i<(int)_cg_texbind.size(); i++) {
+      int texunit = cgGetParameterResourceIndex(_cg_texbind[i].parameter);
+      gsg->_glActiveTexture(GL_TEXTURE0 + texunit);
+      GLP(Disable)(GL_TEXTURE_1D);
+      GLP(Disable)(GL_TEXTURE_2D);
+      if (gsg->_supports_3d_texture) {
+        GLP(Disable)(GL_TEXTURE_3D);
+      }
+      if (gsg->_supports_cube_map) {
+        GLP(Disable)(GL_TEXTURE_CUBE_MAP);
+      }
+      // This is probably faster - but maybe not as safe?
+      // cgGLDisableTextureParameter(_cg_texbind[i].parameter);
+    }
+  }
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLShaderContext::update_shader_texture_bindings
+//       Access: Public
+//  Description: Disables all texture bindings used by the previous
+//               shader, then enables all the texture bindings needed
+//               by this shader.  Extracts the relevant vertex array
+//               data from the gsg.
+//               The current implementation is inefficient, because
+//               it may unnecessarily disable textures then immediately
+//               reenable them.  We may optimize this someday.
+////////////////////////////////////////////////////////////////////
+void CLP(ShaderContext)::
+update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg)
+{
+  if (prev) prev->disable_shader_texture_bindings(gsg);
+#ifdef HAVE_CGGL
+  if (_cg_context) {
+    for (int i=0; i<(int)_cg_texbind.size(); i++) {
+      Texture *tex = 0;
+      InternalName *id = _cg_texbind[i].name;
+      if (id != 0) {
+        const ShaderInput *input = gsg->_target._shader->get_input(id);
+        tex = input->get_texture();
+      } else {
+        TextureStage *stage = gsg->_target._texture->get_on_stage(_cg_texbind[i].stage);
+        tex = gsg->_target._texture->get_on_texture(stage);
+      }
+      if ((tex == 0) || (tex->get_texture_type() != _cg_texbind[i].desiredtype)) {
+        continue;
+      }
+      TextureContext *tc = tex->prepare_now(gsg->_prepared_objects, gsg);
+      if (tc == (TextureContext*)NULL) {
+        continue;
+      }
+      int texunit = cgGetParameterResourceIndex(_cg_texbind[i].parameter);
+      gsg->_glActiveTexture(GL_TEXTURE0 + texunit);
+
+      GLenum target = gsg->get_texture_target(tex->get_texture_type());
+      if (target == GL_NONE) {
+        // Unsupported texture mode.
+        continue;
+      }
+      GLP(Enable)(target);
+      
+      gsg->apply_texture(tc);
+    }
+  }
+#endif
+}
+
 #ifdef HAVE_CGGL
 #ifdef HAVE_CGGL
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLShaderContext::bind_cg_transform
 //     Function: GLShaderContext::bind_cg_transform
@@ -321,6 +399,8 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
   
   
   if (stb.src_name == InternalName::get_camera()) {
   if (stb.src_name == InternalName::get_camera()) {
     src = TransformState::make_identity();
     src = TransformState::make_identity();
+  } else if (stb.src_name == InternalName::get_view()) {
+    src = gsg->_cs_transform;
   } else if (stb.src_name == InternalName::get_model()) {
   } else if (stb.src_name == InternalName::get_model()) {
     src = gsg->get_transform();
     src = gsg->get_transform();
   } else if (stb.src_name == InternalName::get_world()) {
   } else if (stb.src_name == InternalName::get_world()) {
@@ -337,6 +417,8 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
 
 
   if (stb.rel_name == InternalName::get_camera()) {
   if (stb.rel_name == InternalName::get_camera()) {
     rel = TransformState::make_identity();
     rel = TransformState::make_identity();
+  } else if (stb.src_name == InternalName::get_view()) {
+    rel = gsg->_cs_transform;
   } else if (stb.rel_name == InternalName::get_model()) {
   } else if (stb.rel_name == InternalName::get_model()) {
     rel = gsg->get_transform();
     rel = gsg->get_transform();
   } else if (stb.rel_name == InternalName::get_world()) {
   } else if (stb.rel_name == InternalName::get_world()) {
@@ -498,7 +580,10 @@ bool CLP(ShaderContext)::
 errchk_cg_parameter_sampler(CGparameter p)
 errchk_cg_parameter_sampler(CGparameter p)
 {
 {
   CGtype t = cgGetParameterType(p);
   CGtype t = cgGetParameterType(p);
-  if (t != CG_SAMPLER2D) {
+  if ((t!=CG_SAMPLER1D)&&
+      (t!=CG_SAMPLER2D)&&
+      (t!=CG_SAMPLER3D)&&
+      (t!=CG_SAMPLERCUBE)) {
     errchk_cg_output(p, "parameter should have a 'sampler' type");
     errchk_cg_output(p, "parameter should have a 'sampler' type");
     return false;
     return false;
   }
   }
@@ -744,8 +829,21 @@ compile_cg_parameter(CGparameter p)
         (!errchk_cg_parameter_variance(p, CG_UNIFORM)) ||
         (!errchk_cg_parameter_variance(p, CG_UNIFORM)) ||
         (!errchk_cg_parameter_sampler(p)))
         (!errchk_cg_parameter_sampler(p)))
       return false;
       return false;
-    // IMPLEMENT ME
-    return true; // Cg handles this automatically.
+    ShaderTexBind bind;
+    bind.parameter = p;
+    bind.name = 0;
+    bind.stage = atoi(pieces[1].c_str());
+    switch (cgGetParameterType(p)) {
+    case CG_SAMPLER1D:   bind.desiredtype = Texture::TT_1d_texture; break;
+    case CG_SAMPLER2D:   bind.desiredtype = Texture::TT_2d_texture; break;
+    case CG_SAMPLER3D:   bind.desiredtype = Texture::TT_3d_texture; break;
+    case CG_SAMPLERCUBE: bind.desiredtype = Texture::TT_cube_map; break;
+    default:
+      errchk_cg_output(p, "Invalid type for a tex-parameter");
+      return false;
+    }
+    _cg_texbind.push_back(bind);
+    return true;
   }
   }
 
 
   if (pieces[0] == "k") {
   if (pieces[0] == "k") {
@@ -753,14 +851,53 @@ compile_cg_parameter(CGparameter p)
         (!errchk_cg_parameter_direction(p, CG_IN)) ||
         (!errchk_cg_parameter_direction(p, CG_IN)) ||
         (!errchk_cg_parameter_variance(p, CG_UNIFORM)))
         (!errchk_cg_parameter_variance(p, CG_UNIFORM)))
       return false;
       return false;
-    ShaderArgBind bind;
-    bind.parameter = p;
-    bind.name = InternalName::make(pieces[1]);
     switch (cgGetParameterType(p)) {
     switch (cgGetParameterType(p)) {
-    case CG_FLOAT4:    _cg_fbind.push_back(bind); break;
-    case CG_SAMPLER2D: _cg_tbind2d.push_back(bind); break;
-    case CG_SAMPLER3D: _cg_tbind3d.push_back(bind); break;
-    case CG_FLOAT4x4:  _cg_npbind.push_back(bind); break;
+    case CG_FLOAT4: {
+      ShaderArgBind bind;
+      bind.parameter = p;
+      bind.name = InternalName::make(pieces[1]);
+      _cg_fbind.push_back(bind);
+      break;
+    }
+    case CG_FLOAT4x4: {
+      ShaderArgBind bind;
+      bind.parameter = p;
+      bind.name = InternalName::make(pieces[1]);
+      _cg_npbind.push_back(bind);
+      break;
+    }
+    case CG_SAMPLER1D: { 
+      ShaderTexBind bind;
+      bind.parameter = p;
+      bind.name = InternalName::make(pieces[1]);
+      bind.desiredtype=Texture::TT_1d_texture;
+      _cg_texbind.push_back(bind);
+      break;
+    }      
+    case CG_SAMPLER2D: {
+      ShaderTexBind bind;
+      bind.parameter = p;
+      bind.name = InternalName::make(pieces[1]);
+      bind.desiredtype=Texture::TT_2d_texture;
+      _cg_texbind.push_back(bind);
+      break;
+    }
+    case CG_SAMPLER3D: {
+      ShaderTexBind bind;
+      bind.parameter = p;
+      bind.name = InternalName::make(pieces[1]);
+      bind.desiredtype=Texture::TT_3d_texture;
+      _cg_texbind.push_back(bind);
+      break;
+    }
+    case CG_SAMPLERCUBE: {
+      ShaderTexBind bind;
+      bind.parameter = p;
+      bind.name = InternalName::make(pieces[1]);
+      bind.desiredtype = Texture::TT_cube_map;
+      _cg_texbind.push_back(bind);
+      break;
+    }
     default:
     default:
       errchk_cg_output(p, "Invalid type for a k-parameter");
       errchk_cg_output(p, "Invalid type for a k-parameter");
       return false;
       return false;

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

@@ -45,6 +45,8 @@ public:
   void issue_transform(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);
+  void disable_shader_texture_bindings(GSG *gsg);
+  void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg);
 
 
 private:
 private:
 
 
@@ -58,6 +60,12 @@ private:
     CGparameter parameter;
     CGparameter parameter;
     PT(InternalName) name;
     PT(InternalName) name;
   };
   };
+  struct ShaderTexBind {
+    CGparameter parameter;
+    PT(InternalName) name;
+    int stage;
+    int desiredtype;
+  };
   struct ShaderTransBind {
   struct ShaderTransBind {
     CGparameter parameter;
     CGparameter parameter;
     PT(InternalName) src_name;
     PT(InternalName) src_name;
@@ -76,10 +84,9 @@ private:
   // These arrays contain lists of "bindings." They
   // These arrays contain lists of "bindings." They
   // tell us how to fill the shader's input parameters.
   // tell us how to fill the shader's input parameters.
   vector <ShaderAutoBind> _cg_autobind;
   vector <ShaderAutoBind> _cg_autobind;
-  vector <ShaderArgBind> _cg_tbind2d;
-  vector <ShaderArgBind> _cg_tbind3d;
   vector <ShaderArgBind> _cg_fbind;
   vector <ShaderArgBind> _cg_fbind;
   vector <ShaderArgBind> _cg_npbind;
   vector <ShaderArgBind> _cg_npbind;
+  vector <ShaderTexBind> _cg_texbind;
   vector <ShaderTransBind> _cg_transform_bind;
   vector <ShaderTransBind> _cg_transform_bind;
   vector <ShaderTransBind> _cg_parameter_bind;
   vector <ShaderTransBind> _cg_parameter_bind;
   vector <ShaderVarying> _cg_varying;
   vector <ShaderVarying> _cg_varying;

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

@@ -417,6 +417,20 @@ get_model() {
   return _model;
   return _model;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: InternalName::get_view
+//       Access: Published, Static
+//  Description: Returns the standard InternalName "view".  This is
+//               used as a keyword in the shader subsystem.
+////////////////////////////////////////////////////////////////////
+INLINE PT(InternalName) InternalName::
+get_view() {
+  if (_view == (InternalName *)NULL) {
+    _view = InternalName::make("view");
+  }
+  return _view;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: InternalName::output operator
 //     Function: InternalName::output operator
 //       Access: Public
 //       Access: Public

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

@@ -42,6 +42,7 @@ PT(InternalName) InternalName::_index;
 PT(InternalName) InternalName::_world;
 PT(InternalName) InternalName::_world;
 PT(InternalName) InternalName::_camera;
 PT(InternalName) InternalName::_camera;
 PT(InternalName) InternalName::_model;
 PT(InternalName) InternalName::_model;
+PT(InternalName) InternalName::_view;
 
 
 TypeHandle InternalName::_type_handle;
 TypeHandle InternalName::_type_handle;
 TypeHandle InternalName::_texcoord_type_handle;
 TypeHandle InternalName::_texcoord_type_handle;

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

@@ -84,6 +84,7 @@ PUBLISHED:
   INLINE static PT(InternalName) get_world();
   INLINE static PT(InternalName) get_world();
   INLINE static PT(InternalName) get_camera();
   INLINE static PT(InternalName) get_camera();
   INLINE static PT(InternalName) get_model();
   INLINE static PT(InternalName) get_model();
+  INLINE static PT(InternalName) get_view();
 
 
 private:
 private:
   PT(InternalName) _parent;
   PT(InternalName) _parent;
@@ -111,6 +112,7 @@ private:
   static PT(InternalName) _world;
   static PT(InternalName) _world;
   static PT(InternalName) _camera;
   static PT(InternalName) _camera;
   static PT(InternalName) _model;
   static PT(InternalName) _model;
+  static PT(InternalName) _view;
   
   
 public:
 public:
   // Datagram stuff
   // Datagram stuff