Browse Source

Add render to texture option.

aignacio_sf 20 years ago
parent
commit
578aefebc4
3 changed files with 103 additions and 73 deletions
  1. 13 0
      panda/src/gobj/texture.I
  2. 79 65
      panda/src/gobj/texture.cxx
  3. 11 8
      panda/src/gobj/texture.h

+ 13 - 0
panda/src/gobj/texture.I

@@ -398,6 +398,19 @@ get_border_color() const {
   return _border_color;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::get_render_to_texture
+//       Access: Published
+//  Description: Returns the solid color of the texture's border.
+//               Some OpenGL implementations use a border for tiling
+//               textures; in Panda, it is only used for specifying
+//               the clamp color.
+////////////////////////////////////////////////////////////////////
+INLINE bool Texture::
+get_render_to_texture() const {
+  return _render_to_texture;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::uses_mipmaps
 //       Access: Public

+ 79 - 65
panda/src/gobj/texture.cxx

@@ -58,6 +58,7 @@ Texture(const string &name) :
   _keep_ram_image = true;
   _all_dirty_flags = 0;
   _border_color.set(0.0f, 0.0f, 0.0f, 1.0f);
+  _render_to_texture = false;
   _match_framebuffer_format = false;
 
   _texture_type = TT_2d_texture;
@@ -126,7 +127,7 @@ Texture::
 //               as a separate texture from the original, so it will
 //               be duplicated in texture memory (and may be
 //               independently modified if desired).
-//               
+//
 //               If the Texture is an AviTexture, the resulting
 //               duplicate may be animated independently of the
 //               original.
@@ -145,8 +146,8 @@ make_copy() {
 //               modify_ram_image().
 ////////////////////////////////////////////////////////////////////
 void Texture::
-setup_texture(Texture::TextureType texture_type, int x_size, int y_size, 
-              int z_size, Texture::ComponentType component_type, 
+setup_texture(Texture::TextureType texture_type, int x_size, int y_size,
+              int z_size, Texture::ComponentType component_type,
               Texture::Format format) {
   if (texture_type == TT_cube_map) {
     // Cube maps must always consist of six square images.
@@ -291,11 +292,11 @@ read(const Filename &fullpath, int z, int primary_file_num_channels) {
   if (textures_header_only) {
     if (!image.read_header(fullpath)) {
       gobj_cat.error()
-	<< "Texture::read() - couldn't read: " << fullpath << endl;
+  << "Texture::read() - couldn't read: " << fullpath << endl;
       return false;
     }
     image = PNMImage(1, 1, image.get_num_channels(), image.get_maxval(),
-		     image.get_type());
+         image.get_type());
     image.fill(0.2, 0.3, 1.0);
     if (image.has_alpha()) {
       image.alpha_fill(1.0);
@@ -304,7 +305,7 @@ read(const Filename &fullpath, int z, int primary_file_num_channels) {
   } else {
     if (!image.read(fullpath, NULL, false)) {
       gobj_cat.error()
-	<< "Texture::read() - couldn't read: " << fullpath << endl;
+  << "Texture::read() - couldn't read: " << fullpath << endl;
       return false;
     }
   }
@@ -345,11 +346,11 @@ read(const Filename &fullpath, const Filename &alpha_fullpath,
   if (textures_header_only) {
     if (!image.read_header(fullpath)) {
       gobj_cat.error()
-	<< "Texture::read() - couldn't read: " << fullpath << endl;
+  << "Texture::read() - couldn't read: " << fullpath << endl;
       return false;
     }
     image = PNMImage(1, 1, image.get_num_channels(), image.get_maxval(),
-		     image.get_type());
+         image.get_type());
     image.fill(0.2, 0.3, 1.0);
     if (image.has_alpha()) {
       image.alpha_fill(1.0);
@@ -358,7 +359,7 @@ read(const Filename &fullpath, const Filename &alpha_fullpath,
   } else {
     if (!image.read(fullpath, NULL, false)) {
       gobj_cat.error()
-	<< "Texture::read() - couldn't read: " << fullpath << endl;
+  << "Texture::read() - couldn't read: " << fullpath << endl;
       return false;
     }
   }
@@ -367,12 +368,12 @@ read(const Filename &fullpath, const Filename &alpha_fullpath,
   if (textures_header_only) {
     if (!alpha_image.read_header(alpha_fullpath)) {
       gobj_cat.error()
-	<< "Texture::read() - couldn't read: " << alpha_fullpath << endl;
+  << "Texture::read() - couldn't read: " << alpha_fullpath << endl;
       return false;
     }
-    alpha_image = PNMImage(1, 1, alpha_image.get_num_channels(), 
-			   alpha_image.get_maxval(),
-			   alpha_image.get_type());
+    alpha_image = PNMImage(1, 1, alpha_image.get_num_channels(),
+         alpha_image.get_maxval(),
+         alpha_image.get_type());
     alpha_image.fill(1.0);
     if (alpha_image.has_alpha()) {
       alpha_image.alpha_fill(1.0);
@@ -381,11 +382,11 @@ read(const Filename &fullpath, const Filename &alpha_fullpath,
   } else {
     if (!alpha_image.read(alpha_fullpath, NULL, true)) {
       gobj_cat.error()
-	<< "Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
+  << "Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
       return false;
     }
   }
-    
+
   if (!has_name()) {
     set_name(fullpath.get_basename_wo_extension());
   }
@@ -405,7 +406,7 @@ read(const Filename &fullpath, const Filename &alpha_fullpath,
       image.get_y_size() != alpha_image.get_y_size()) {
     gobj_cat.info()
       << "Automatically rescaling " << alpha_fullpath.get_basename()
-      << " from " << alpha_image.get_x_size() << " by " 
+      << " from " << alpha_image.get_x_size() << " by "
       << alpha_image.get_y_size() << " to " << image.get_x_size()
       << " by " << image.get_y_size() << "\n";
 
@@ -424,7 +425,7 @@ read(const Filename &fullpath, const Filename &alpha_fullpath,
   // grayscale value from the second image.
   image.add_alpha();
 
-  if (alpha_file_channel == 4 || 
+  if (alpha_file_channel == 4 ||
       (alpha_file_channel == 2 && alpha_image.get_num_channels() == 2)) {
     // Use the alpha channel.
     for (int x = 0; x < image.get_x_size(); x++) {
@@ -614,8 +615,8 @@ load(const PNMImage &pnmimage, int z) {
   }
 
   if (!reconsider_image_properties(pnmimage.get_x_size(), pnmimage.get_y_size(),
-				   pnmimage.get_num_channels(), component_type,
-				   z)) {
+           pnmimage.get_num_channels(), component_type,
+           z)) {
     return false;
   }
 
@@ -627,12 +628,12 @@ load(const PNMImage &pnmimage, int z) {
   // _image component.
   bool has_alpha = pnmimage.has_alpha();
   bool is_grayscale = pnmimage.is_grayscale();
-    
+
   if (maxval == 255) {
     // Most common case: one byte per pixel, and the source image
     // shows a maxval of 255.  No scaling is necessary.
     int idx = get_expected_ram_page_size() * z;
-    
+
     for (int j = _y_size-1; j >= 0; j--) {
       for (int i = 0; i < _x_size; i++) {
         if (is_grayscale) {
@@ -649,12 +650,12 @@ load(const PNMImage &pnmimage, int z) {
     }
 
     nassertr((size_t)idx == get_expected_ram_page_size() * (z + 1), false);
-    
+
   } else if (maxval == 65535) {
     // Another possible case: two bytes per pixel, and the source
     // image shows a maxval of 65535.  Again, no scaling is necessary.
     int idx = get_expected_ram_page_size() * z;
-    
+
     for (int j = _y_size-1; j >= 0; j--) {
       for (int i = 0; i < _x_size; i++) {
         if (is_grayscale) {
@@ -671,14 +672,14 @@ load(const PNMImage &pnmimage, int z) {
     }
 
     nassertr((size_t)idx == get_expected_ram_page_size() * (z + 1), false);
-    
+
   } else if (maxval <= 255) {
     // A less common case: one byte per pixel, but the maxval is
     // something other than 255.  In this case, we should scale the
     // pixel values up to the appropriate amount.
     int idx = get_expected_ram_page_size() * z;
     double scale = 255.0 / (double)maxval;
-    
+
     for (int j = _y_size-1; j >= 0; j--) {
       for (int i = 0; i < _x_size; i++) {
         if (is_grayscale) {
@@ -695,14 +696,14 @@ load(const PNMImage &pnmimage, int z) {
     }
 
     nassertr((size_t)idx == get_expected_ram_page_size() * (z + 1), false);
-    
+
   } else {
     // Another uncommon case: two bytes per pixel, and the maxval is
     // something other than 65535.  Again, we must scale the pixel
     // values.
     int idx = get_expected_ram_page_size() * z;
     double scale = 65535.0 / (double)maxval;
-    
+
     for (int j = _y_size-1; j >= 0; j--) {
       for (int i = 0; i < _x_size; i++) {
         if (is_grayscale) {
@@ -815,14 +816,14 @@ load_related(const PT(InternalName) &suffix) const {
     return (Texture*)NULL;
   }
   Filename main = get_fullpath();
-  main.set_basename_wo_extension(main.get_basename_wo_extension() + 
+  main.set_basename_wo_extension(main.get_basename_wo_extension() +
                                  suffix->get_name());
   Texture *res;
   if (has_alpha_fullpath()) {
     Filename alph = get_alpha_fullpath();
     alph.set_basename_wo_extension(alph.get_basename_wo_extension() +
                                    suffix->get_name());
-    res = TexturePool::load_texture(main, alph, 
+    res = TexturePool::load_texture(main, alph,
                                     _primary_file_num_channels,
                                     _alpha_file_channel);
   } else {
@@ -856,7 +857,7 @@ set_wrap_u(Texture::WrapMode wrap) {
 void Texture::
 set_wrap_v(Texture::WrapMode wrap) {
   if (_wrap_v != wrap) {
-    mark_dirty(DF_wrap); 
+    mark_dirty(DF_wrap);
     _wrap_v = wrap;
   }
 }
@@ -869,7 +870,7 @@ set_wrap_v(Texture::WrapMode wrap) {
 void Texture::
 set_wrap_w(Texture::WrapMode wrap) {
   if (_wrap_w != wrap) {
-    mark_dirty(DF_wrap); 
+    mark_dirty(DF_wrap);
     _wrap_w = wrap;
   }
 }
@@ -937,6 +938,19 @@ set_border_color(const Colorf &color) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::set_render_to_texture
+//       Access: Published
+//  Description: Specifies the solid color of the texture's border.
+//               Some OpenGL implementations use a border for tiling
+//               textures; in Panda, it is only used for specifying
+//               the clamp color.
+////////////////////////////////////////////////////////////////////
+void Texture::
+set_render_to_texture(bool render_to_texture) {
+    _render_to_texture = render_to_texture;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::has_ram_image
 //       Access: Published, Virtual
@@ -1243,7 +1257,7 @@ is_mipmap(FilterType filter_type) {
   case FT_nearest_mipmap_linear:
   case FT_linear_mipmap_linear:
     return true;
-    
+
   default:
     return false;
   }
@@ -1266,7 +1280,7 @@ is_mipmap(FilterType filter_type) {
 //               rendered.
 ////////////////////////////////////////////////////////////////////
 TextureContext *Texture::
-prepare_now(PreparedGraphicsObjects *prepared_objects, 
+prepare_now(PreparedGraphicsObjects *prepared_objects,
             GraphicsStateGuardianBase *gsg) {
   Contexts::const_iterator ci;
   ci = _contexts.find(prepared_objects);
@@ -1454,7 +1468,7 @@ reload_ram_image() {
   if (_texture_type == TT_1d_texture || _texture_type == TT_2d_texture) {
     gobj_cat.info()
       << "Reloading texture " << get_name() << "\n";
-    
+
     make_ram_image();
     if (has_alpha_fullpath()) {
       read(get_fullpath(), get_alpha_fullpath(),
@@ -1534,7 +1548,7 @@ reconsider_z_size(int z) {
 ////////////////////////////////////////////////////////////////////
 bool Texture::
 reconsider_image_properties(int x_size, int y_size, int num_components,
-			    Texture::ComponentType component_type, int z) {
+          Texture::ComponentType component_type, int z) {
   if (!_loaded_from_disk || num_components != _num_components) {
     // Come up with a default format based on the number of channels.
     // But only do this the first time the file is loaded, or if the
@@ -1544,19 +1558,19 @@ reconsider_image_properties(int x_size, int y_size, int num_components,
     case 1:
       _format = F_luminance;
       break;
-      
+
     case 2:
       _format = F_luminance_alpha;
       break;
-      
+
     case 3:
       _format = F_rgb;
       break;
-      
+
     case 4:
       _format = F_rgba;
       break;
-      
+
     default:
       // Eh?
       nassertr(false, false);
@@ -1751,33 +1765,33 @@ make_from_bam(const FactoryParams &params) {
       // This texture does have a filename, so try to load it from disk.
       VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
       if (!manager->get_filename().empty()) {
-	// If texture filename was given relative to the bam filename,
-	// expand it now.
-	Filename bam_dir = manager->get_filename().get_dirname();
+  // If texture filename was given relative to the bam filename,
+  // expand it now.
+  Filename bam_dir = manager->get_filename().get_dirname();
         vfs->resolve_filename(filename, bam_dir);
-	if (!alpha_filename.empty()) {
-	  vfs->resolve_filename(alpha_filename, bam_dir);
-	}
+  if (!alpha_filename.empty()) {
+    vfs->resolve_filename(alpha_filename, bam_dir);
+  }
       }
 
       switch (texture_type) {
       case TT_1d_texture:
       case TT_2d_texture:
-	if (alpha_filename.empty()) {
-	  me = TexturePool::load_texture(filename, primary_file_num_channels);
-	} else {
-	  me = TexturePool::load_texture(filename, alpha_filename, 
-					 primary_file_num_channels, alpha_file_channel);
-	}
-	break;
+  if (alpha_filename.empty()) {
+    me = TexturePool::load_texture(filename, primary_file_num_channels);
+  } else {
+    me = TexturePool::load_texture(filename, alpha_filename,
+           primary_file_num_channels, alpha_file_channel);
+  }
+  break;
 
       case TT_3d_texture:
-	me = TexturePool::load_3d_texture(filename);
-	break;
+  me = TexturePool::load_3d_texture(filename);
+  break;
 
       case TT_cube_map:
-	me = TexturePool::load_cube_map(filename);
-	break;
+  me = TexturePool::load_cube_map(filename);
+  break;
       }
     }
   }
@@ -1824,7 +1838,7 @@ fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) {
     // written.
     set_format(format);
   }
-  
+
   if (has_rawdata) {
     // In the rawdata case, we must always set the format.
     _format = format;
@@ -1835,9 +1849,9 @@ fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) {
     _component_type = (ComponentType)scan.get_uint8();
     _component_width = scan.get_uint8();
     _loaded_from_disk = false;
-    
+
     PN_uint32 u_size = scan.get_uint32();
-    
+
     // fill the _image buffer with image data
     string temp_buff = scan.extract_bytes(u_size);
     _image = PTA_uchar::empty_array((int) u_size);
@@ -1868,7 +1882,7 @@ write_datagram(BamWriter *manager, Datagram &me) {
   // Otherwise, we just write out the filename, and assume whoever
   // loads the bam file later will have access to the image file on
   // disk.
-  bool has_rawdata = 
+  bool has_rawdata =
     (bam_texture_mode == BTM_rawdata || (has_ram_image() && filename.empty()));
 
   switch (bam_texture_mode) {
@@ -1886,23 +1900,23 @@ write_datagram(BamWriter *manager, Datagram &me) {
     alpha_filename = get_alpha_fullpath();
     if (!has_bam_dir || filename.find_on_searchpath(bam_dir) == -1) {
       if (filename.find_on_searchpath(get_texture_path()) == -1) {
-	filename.find_on_searchpath(get_model_path());
+  filename.find_on_searchpath(get_model_path());
       }
     }
     if (gobj_cat.is_debug()) {
       gobj_cat.debug()
         << "Texture file " << get_filename()
-	<< " found as " << filename << "\n";
+  << " found as " << filename << "\n";
     }
     if (!has_bam_dir || alpha_filename.find_on_searchpath(bam_dir) == -1) {
       if (alpha_filename.find_on_searchpath(get_texture_path()) == -1) {
-	alpha_filename.find_on_searchpath(get_model_path());
+  alpha_filename.find_on_searchpath(get_model_path());
       }
     }
     if (gobj_cat.is_debug()) {
       gobj_cat.debug()
         << "Alpha image " << get_alpha_filename()
-	<< " found as " << alpha_filename << "\n";
+  << " found as " << alpha_filename << "\n";
     }
     break;
 
@@ -1972,7 +1986,7 @@ operator << (ostream &out, Texture::FilterType ft) {
 
   case Texture::FT_shadow:
     return out << "shadow";
-  
+
   case Texture::FT_invalid:
     return out << "invalid";
   }

+ 11 - 8
panda/src/gobj/texture.h

@@ -129,7 +129,7 @@ PUBLISHED:
 
     // The OpenGL ARB_shadow extension can be thought of as a kind of filtering.
     FT_shadow,
-    
+
     // Returned by string_filter_type() for an invalid match.
     FT_invalid
   };
@@ -173,10 +173,10 @@ PUBLISHED:
   void generate_normalization_cube_map(int size);
 
   virtual bool read(const Filename &fullpath, int z = 0,
-		    int primary_file_num_channels = 0);
-  virtual bool read(const Filename &fullpath, const Filename &alpha_fullpath, 
-		    int z = 0,
-		    int primary_file_num_channels = 0, int alpha_file_channel = 0);
+        int primary_file_num_channels = 0);
+  virtual bool read(const Filename &fullpath, const Filename &alpha_fullpath,
+        int z = 0,
+        int primary_file_num_channels = 0, int alpha_file_channel = 0);
   bool write(const Filename &fullpath, int z = 0) const;
 
   bool read_pages(Filename fullpath_pattern, int z_size = 0);
@@ -186,7 +186,7 @@ PUBLISHED:
   bool store(PNMImage &pnmimage, int z = 0) const;
 
   Texture *load_related(const PT(InternalName) &suffix) const;
-  
+
   INLINE bool has_filename() const;
   INLINE const Filename &get_filename() const;
   INLINE bool has_alpha_filename() const;
@@ -213,6 +213,7 @@ PUBLISHED:
   void set_magfilter(FilterType filter);
   void set_anisotropic_degree(int anisotropic_degree);
   void set_border_color(const Colorf &color);
+  void set_render_to_texture(bool render_to_texture);
 
   INLINE WrapMode get_wrap_u() const;
   INLINE WrapMode get_wrap_v() const;
@@ -221,6 +222,7 @@ PUBLISHED:
   INLINE FilterType get_magfilter() const;
   INLINE int get_anisotropic_degree() const;
   INLINE Colorf get_border_color() const;
+  INLINE bool get_render_to_texture() const;
   INLINE bool uses_mipmaps() const;
 
   virtual bool has_ram_image() const;
@@ -268,7 +270,7 @@ public:
 
   static bool is_mipmap(FilterType type);
 
-  TextureContext *prepare_now(PreparedGraphicsObjects *prepared_objects, 
+  TextureContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
                               GraphicsStateGuardianBase *gsg);
 
   // These bits are used as parameters to Texture::mark_dirty() and
@@ -302,7 +304,7 @@ protected:
 
   bool reconsider_z_size(int z);
   bool reconsider_image_properties(int x_size, int y_size, int num_components,
-				   ComponentType component_type, int z);
+           ComponentType component_type, int z);
 
 private:
   void clear_prepared(PreparedGraphicsObjects *prepared_objects);
@@ -351,6 +353,7 @@ protected:
   int _anisotropic_degree;
   bool _keep_ram_image;
   Colorf _border_color;
+  bool _render_to_texture;
   bool _match_framebuffer_format;
 
   // A Texture keeps a list (actually, a map) of all the