Quellcode durchsuchen

Support .ktx textures, ETC1/ETC2/EAC compression

rdb vor 9 Jahren
Ursprung
Commit
400bc2cc26

+ 3 - 9
panda/src/framework/windowFramework.cxx

@@ -602,16 +602,10 @@ load_model(const NodePath &parent, Filename filename) {
     if (model_type == (LoaderFileType *)NULL) {
       // The extension isn't a known model file type; is it a known image file
       // extension?
-      if (extension == "txo" || downcase(extension) == "dds") {
-        // A texture object.  Not exactly an image, but certainly a texture.
+      TexturePool *texture_pool = TexturePool::get_global_ptr();
+      if (texture_pool->get_texture_type(extension) != NULL) {
+        // It is a known image file extension.
         is_image = true;
-
-      } else {
-        TexturePool *texture_pool = TexturePool::get_global_ptr();
-        if (texture_pool->get_texture_type(extension) != NULL) {
-          // It is a known image file extension.
-          is_image = true;
-        }
       }
     }
   }

+ 10 - 0
panda/src/gles2gsg/gles2gsg.h

@@ -231,6 +231,16 @@ typedef char GLchar;
 #define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
 #define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
 #define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
 
 #undef SUPPORT_IMMEDIATE_MODE
 #define APIENTRY

+ 11 - 0
panda/src/glesgsg/glesgsg.h

@@ -132,6 +132,17 @@
 #define GL_DEBUG_SEVERITY_LOW 0x9148
 #define GL_DEBUG_OUTPUT 0x92E0
 
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+
 #undef SUPPORT_IMMEDIATE_MODE
 #define APIENTRY
 #define APIENTRYP *

+ 152 - 8
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1053,6 +1053,24 @@ reset() {
         break;
 #endif
 
+      case GL_COMPRESSED_R11_EAC:
+      case GL_COMPRESSED_RG11_EAC:
+        _compressed_texture_formats.set_bit(Texture::CM_eac);
+        break;
+
+      case GL_COMPRESSED_RGB8_ETC2:
+      case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+      case GL_COMPRESSED_RGBA8_ETC2_EAC:
+        _compressed_texture_formats.set_bit(Texture::CM_etc1);
+        _compressed_texture_formats.set_bit(Texture::CM_etc2);
+        break;
+
+#ifdef OPENGLES
+      case GL_ETC1_RGB8_OES:
+        _compressed_texture_formats.set_bit(Texture::CM_etc1);
+        break;
+#endif
+
       default:
         break;
       }
@@ -8066,6 +8084,12 @@ get_texture_target(Texture::TextureType texture_type) const {
     return GL_TEXTURE_1D;
 #endif
 
+  case Texture::TT_1d_texture_array:
+    // There are no 1D array textures in OpenGL ES.  Fall back to 2D textures.
+#ifndef OPENGLES
+    return GL_TEXTURE_1D_ARRAY;
+#endif
+
   case Texture::TT_2d_texture:
     return GL_TEXTURE_2D;
 
@@ -8282,6 +8306,11 @@ get_component_type(Texture::ComponentType component_type) {
     return GL_HALF_FLOAT;
 #endif
 
+#ifndef OPENGLES_1
+  case Texture::T_unsigned_int:
+    return GL_UNSIGNED_INT;
+#endif
+
   default:
     GLCAT.error() << "Invalid Texture::Type value!\n";
     return GL_UNSIGNED_BYTE;
@@ -8444,9 +8473,9 @@ get_external_image_format(Texture *tex) const {
 
     case Texture::CM_rgtc:
 #ifndef OPENGLES
-      if (tex->get_format() == Texture::F_luminance) {
+      if (format == Texture::F_luminance) {
         return GL_COMPRESSED_LUMINANCE_LATC1_EXT;
-      } else if (tex->get_format() == Texture::F_luminance_alpha) {
+      } else if (format == Texture::F_luminance_alpha) {
         return GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
       } else if (tex->get_num_components() == 1) {
         return GL_COMPRESSED_RED_RGTC1;
@@ -8456,6 +8485,41 @@ get_external_image_format(Texture *tex) const {
 #endif
       break;
 
+    case Texture::CM_etc1:
+#ifdef OPENGLES
+      return GL_ETC1_RGB8_OES;
+#endif
+      // Fall through - ETC2 is backward compatible
+    case Texture::CM_etc2:
+      if (format == Texture::F_rgbm) {
+        return GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
+      } else if (format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
+      } else if (format == Texture::F_srgb) {
+        return GL_COMPRESSED_SRGB8_ETC2;
+      } else if (Texture::has_alpha(format)) {
+        return GL_COMPRESSED_RGBA8_ETC2_EAC;
+      } else {
+        return GL_COMPRESSED_RGB8_ETC2;
+      }
+      break;
+
+    case Texture::CM_eac:
+      if (Texture::is_unsigned(tex->get_component_type())) {
+        if (tex->get_num_components() == 1) {
+          return GL_COMPRESSED_R11_EAC;
+        } else {
+          return GL_COMPRESSED_RG11_EAC;
+        }
+      } else {
+        if (tex->get_num_components() == 1) {
+          return GL_COMPRESSED_SIGNED_R11_EAC;
+        } else {
+          return GL_COMPRESSED_SIGNED_RG11_EAC;
+        }
+      }
+      break;
+
     case Texture::CM_default:
     case Texture::CM_off:
     case Texture::CM_dxt2:
@@ -8565,7 +8629,7 @@ get_external_image_format(Texture *tex) const {
   }
   GLCAT.error()
     << "Invalid Texture::Format value in get_external_image_format(): "
-    << tex->get_format() << "\n";
+    << format << "\n";
   return GL_RGB;
 }
 
@@ -8615,10 +8679,14 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
         break;
 
       case Texture::F_rgbm:
+      case Texture::F_rgba5:
       case Texture::F_rgb10_a2:
         if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) {
           return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
         }
+        if (get_supports_compressed_texture_format(Texture::CM_etc2) && !is_3d) {
+          return GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
+        }
 #ifndef OPENGLES
         if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) {
           return GL_COMPRESSED_RGBA_FXT1_3DFX;
@@ -8633,6 +8701,9 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
           return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
         }
 #endif
+        if (get_supports_compressed_texture_format(Texture::CM_etc2) && !is_3d) {
+          return GL_COMPRESSED_RGBA8_ETC2_EAC;
+        }
 #ifndef OPENGLES
         if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) {
           return GL_COMPRESSED_RGBA_FXT1_3DFX;
@@ -8651,6 +8722,9 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
           return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
         }
 #endif
+        if (get_supports_compressed_texture_format(Texture::CM_etc2) && !is_3d) {
+          return GL_COMPRESSED_RGBA8_ETC2_EAC;
+        }
 #ifndef OPENGLES
         if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) {
           return GL_COMPRESSED_RGBA_FXT1_3DFX;
@@ -8661,7 +8735,6 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
 
       case Texture::F_rgb:
       case Texture::F_rgb5:
-      case Texture::F_rgba5:
       case Texture::F_rgb8:
       case Texture::F_rgb12:
       case Texture::F_rgb332:
@@ -8670,7 +8743,14 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
         if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) {
           return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
         }
-#ifndef OPENGLES
+        if (get_supports_compressed_texture_format(Texture::CM_etc2) && !is_3d) {
+          return GL_COMPRESSED_RGB8_ETC2;
+        }
+#ifdef OPENGLES
+        if (get_supports_compressed_texture_format(Texture::CM_etc1) && !is_3d) {
+          return GL_ETC1_RGB8_OES;
+        }
+#else
         if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) {
           return GL_COMPRESSED_RGB_FXT1_3DFX;
         }
@@ -8702,6 +8782,13 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
           return GL_COMPRESSED_RED_RGTC1;
         }
 #endif
+        if (get_supports_compressed_texture_format(Texture::CM_eac) && !is_3d) {
+          if (Texture::is_unsigned(tex->get_component_type())) {
+            return GL_COMPRESSED_R11_EAC;
+          } else {
+            return GL_COMPRESSED_SIGNED_R11_EAC;
+          }
+        }
         if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) {
           return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
         }
@@ -8721,6 +8808,13 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
           return GL_COMPRESSED_RG_RGTC2;
         }
 #endif
+        if (get_supports_compressed_texture_format(Texture::CM_eac) && !is_3d) {
+          if (Texture::is_unsigned(tex->get_component_type())) {
+            return GL_COMPRESSED_RG11_EAC;
+          } else {
+            return GL_COMPRESSED_SIGNED_RG11_EAC;
+          }
+        }
         if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) {
           return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
         }
@@ -8764,12 +8858,18 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
         if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) {
           return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
         }
+        if (get_supports_compressed_texture_format(Texture::CM_etc2) && !is_3d) {
+          return GL_COMPRESSED_SRGB8_ETC2;
+        }
         return GL_COMPRESSED_SRGB;
 
       case Texture::F_srgb_alpha:
         if (get_supports_compressed_texture_format(Texture::CM_dxt5) && !is_3d) {
           return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
         }
+        if (get_supports_compressed_texture_format(Texture::CM_etc2) && !is_3d) {
+          return GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
+        }
         return GL_COMPRESSED_SRGB_ALPHA;
 
       case Texture::F_sluminance:
@@ -8855,9 +8955,9 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
 
     case Texture::CM_rgtc:
 #ifndef OPENGLES
-      if (tex->get_format() == Texture::F_luminance) {
+      if (format == Texture::F_luminance) {
         return GL_COMPRESSED_LUMINANCE_LATC1_EXT;
-      } else if (tex->get_format() == Texture::F_luminance_alpha) {
+      } else if (format == Texture::F_luminance_alpha) {
         return GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
       } else if (tex->get_num_components() == 1) {
         return GL_COMPRESSED_RED_RGTC1;
@@ -8867,6 +8967,41 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
 #endif
       break;
 
+    case Texture::CM_etc1:
+#ifdef OPENGLES
+      return GL_ETC1_RGB8_OES;
+#endif
+      // Fall through - ETC2 is backward compatible
+    case Texture::CM_etc2:
+      if (format == Texture::F_rgbm) {
+        return GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
+      } else if (format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
+      } else if (format == Texture::F_srgb) {
+        return GL_COMPRESSED_SRGB8_ETC2;
+      } else if (Texture::has_alpha(format)) {
+        return GL_COMPRESSED_RGBA8_ETC2_EAC;
+      } else {
+        return GL_COMPRESSED_RGB8_ETC2;
+      }
+      break;
+
+    case Texture::CM_eac:
+      if (Texture::is_unsigned(tex->get_component_type())) {
+        if (tex->get_num_components() == 1) {
+          return GL_COMPRESSED_R11_EAC;
+        } else {
+          return GL_COMPRESSED_RG11_EAC;
+        }
+      } else {
+        if (tex->get_num_components() == 1) {
+          return GL_COMPRESSED_SIGNED_R11_EAC;
+        } else {
+          return GL_COMPRESSED_SIGNED_RG11_EAC;
+        }
+      }
+      break;
+
     case Texture::CM_default:
     case Texture::CM_off:
     case Texture::CM_dxt2:
@@ -9197,7 +9332,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
   default:
     GLCAT.error()
       << "Invalid image format in get_internal_image_format(): "
-      << (int)tex->get_format() << "\n";
+      << (int)format << "\n";
     return force_sized ? GL_RGB8 : GL_RGB;
   }
 }
@@ -11661,6 +11796,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
         break;
       case Texture::TT_2d_texture:
       case Texture::TT_cube_map:
+      case Texture::TT_1d_texture_array:
         _glTexStorage2D(target, num_levels, internal_format, width, height);
         break;
       case Texture::TT_3d_texture:
@@ -12119,6 +12255,14 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
             // fill it in with the correct clear color, which we can then
             // upload.
             ptimage = tex->make_ram_mipmap_image(n);
+
+          } else if (image_compression != Texture::CM_off) {
+            // We can't upload a NULL compressed texture.
+            if (_supports_texture_max_level) {
+              // Tell the GL we have no more mipmaps for it to use.
+              glTexParameteri(texture_target, GL_TEXTURE_MAX_LEVEL, n - mipmap_bias);
+            }
+            break;
           }
         }
         image_ptr = ptimage;

+ 9 - 0
panda/src/glstuff/glShaderContext_src.cxx

@@ -1296,12 +1296,15 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
       case GL_SAMPLER_2D_ARRAY_SHADOW:
 #ifndef OPENGLES
       case GL_INT_SAMPLER_1D:
+      case GL_INT_SAMPLER_1D_ARRAY:
       case GL_INT_SAMPLER_BUFFER:
       case GL_INT_SAMPLER_CUBE_MAP_ARRAY:
       case GL_UNSIGNED_INT_SAMPLER_1D:
+      case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
       case GL_UNSIGNED_INT_SAMPLER_BUFFER:
       case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY:
       case GL_SAMPLER_1D:
+      case GL_SAMPLER_1D_ARRAY:
       case GL_SAMPLER_1D_SHADOW:
       case GL_SAMPLER_BUFFER:
       case GL_SAMPLER_CUBE_MAP_ARRAY:
@@ -1597,6 +1600,12 @@ get_sampler_texture_type(int &out, GLenum param_type) {
   case GL_SAMPLER_1D:
     out = Texture::TT_1d_texture;
     return true;
+
+  case GL_INT_SAMPLER_1D_ARRAY:
+  case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
+  case GL_SAMPLER_1D_ARRAY:
+    out = Texture::TT_1d_texture_array;
+    return true;
 #endif
 
   case GL_INT_SAMPLER_2D:

+ 19 - 4
panda/src/gobj/texture.I

@@ -2318,8 +2318,8 @@ get_unsigned_short(const unsigned char *&p) {
 }
 
 /**
- * Returns true if the indicated filename ends in .txo or .txo.pz, false
- * otherwise.
+ * Returns true if the indicated filename ends in .txo or .txo.pz or .txo.gz,
+ * false otherwise.
  */
 INLINE bool Texture::
 is_txo_filename(const Filename &fullpath) {
@@ -2333,8 +2333,8 @@ is_txo_filename(const Filename &fullpath) {
 }
 
 /**
- * Returns true if the indicated filename ends in .dds or .dds.pz, false
- * otherwise.
+ * Returns true if the indicated filename ends in .dds or .dds.pz or .dds.gz,
+ * false otherwise.
  */
 INLINE bool Texture::
 is_dds_filename(const Filename &fullpath) {
@@ -2347,6 +2347,21 @@ is_dds_filename(const Filename &fullpath) {
   return (downcase(extension) == "dds");
 }
 
+/**
+ * Returns true if the indicated filename ends in .ktx or .ktx.pz or .ktx.gz,
+ * false otherwise.
+ */
+INLINE bool Texture::
+is_ktx_filename(const Filename &fullpath) {
+  string extension = fullpath.get_extension();
+#ifdef HAVE_ZLIB
+  if (extension == "pz" || extension == "gz") {
+    extension = Filename(fullpath.get_basename_wo_extension()).get_extension();
+  }
+#endif  // HAVE_ZLIB
+  return (downcase(extension) == "ktx");
+}
+
 /**
  *
  */

Datei-Diff unterdrückt, da er zu groß ist
+ 1033 - 2
panda/src/gobj/texture.cxx


+ 9 - 0
panda/src/gobj/texture.h

@@ -79,6 +79,7 @@ PUBLISHED:
     TT_cube_map,
     TT_buffer_texture,
     TT_cube_map_array,
+    TT_1d_texture_array,
   };
 
   enum ComponentType {
@@ -90,6 +91,7 @@ PUBLISHED:
     T_byte,
     T_short,
     T_half_float,
+    T_unsigned_int,
   };
 
   enum Format {
@@ -206,6 +208,9 @@ PUBLISHED:
     CM_pvr1_2bpp,
     CM_pvr1_4bpp,
     CM_rgtc, // BC4/BC5: 1 or 2 channels, individually compressed.
+    CM_etc1,
+    CM_etc2,
+    CM_eac, // EAC: 1 or 2 channels.
   };
 
   enum QualityLevel {
@@ -284,6 +289,7 @@ PUBLISHED:
   BLOCKING static PT(Texture) make_from_txo(istream &in, const string &filename = "");
   BLOCKING bool write_txo(ostream &out, const string &filename = "") const;
   BLOCKING bool read_dds(istream &in, const string &filename = "", bool header_only = false);
+  BLOCKING bool read_ktx(istream &in, const string &filename = "", bool header_only = false);
 
   BLOCKING INLINE bool load(const PNMImage &pnmimage, const LoaderOptions &options = LoaderOptions());
   BLOCKING INLINE bool load(const PNMImage &pnmimage, int z, int n, const LoaderOptions &options = LoaderOptions());
@@ -657,6 +663,8 @@ protected:
   bool do_read_txo(CData *cdata, istream &in, const string &filename);
   bool do_read_dds_file(CData *cdata, const Filename &fullpath, bool header_only);
   bool do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only);
+  bool do_read_ktx_file(CData *cdata, const Filename &fullpath, bool header_only);
+  bool do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only);
 
   bool do_write(CData *cdata, const Filename &fullpath, int z, int n,
                 bool write_pages, bool write_mipmaps);
@@ -840,6 +848,7 @@ private:
 
   INLINE static bool is_txo_filename(const Filename &fullpath);
   INLINE static bool is_dds_filename(const Filename &fullpath);
+  INLINE static bool is_ktx_filename(const Filename &fullpath);
 
   void do_filter_2d_mipmap_pages(const CData *cdata,
                                  RamImage &to, const RamImage &from,

+ 6 - 1
panda/src/gobj/texturePool.cxx

@@ -90,7 +90,7 @@ get_texture_type(const string &extension) const {
   // Check the PNM type registry.
   PNMFileTypeRegistry *pnm_reg = PNMFileTypeRegistry::get_global_ptr();
   PNMFileType *type = pnm_reg->get_type_from_extension(c);
-  if (type != (PNMFileType *)NULL) {
+  if (type != (PNMFileType *)NULL || c == "txo" || c == "dds" || c == "ktx") {
     // This is a known image type; create an ordinary Texture.
     ((TexturePool *)this)->_type_registry[c] = Texture::make_texture;
     return Texture::make_texture;
@@ -109,6 +109,11 @@ void TexturePool::
 write_texture_types(ostream &out, int indent_level) const {
   MutexHolder holder(_lock);
 
+  // These are supported out of the box.
+  indent(out, indent_level) << "Texture Object                  .txo\n";
+  indent(out, indent_level) << "DirectDraw Surface              .dds\n";
+  indent(out, indent_level) << "Khronos Texture                 .ktx\n";
+
   PNMFileTypeRegistry *pnm_reg = PNMFileTypeRegistry::get_global_ptr();
   pnm_reg->write(out, indent_level);
 

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.