Browse Source

Fix mipmapping with sampler state

rdb 11 years ago
parent
commit
89031b4e48

+ 25 - 11
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -4268,14 +4268,15 @@ update_texture(TextureContext *tc, bool force) {
 
     // If the texture image was modified, reload the texture.
     apply_texture(tc);
+
+    Texture *tex = tc->get_texture();
     if (gtc->was_properties_modified()) {
-      Texture *tex = tc->get_texture();
       specify_texture(gtc, tex->get_default_sampler());
     }
-    bool okflag = upload_texture(gtc, force);
+    bool okflag = upload_texture(gtc, force, tex->uses_mipmaps());
     if (!okflag) {
       GLCAT.error()
-        << "Could not load " << *gtc->get_texture() << "\n";
+        << "Could not load " << *tex << "\n";
       return false;
     }
 
@@ -4290,7 +4291,7 @@ update_texture(TextureContext *tc, bool force) {
     if (specify_texture(gtc, tex->get_default_sampler())) {
       // Actually, looks like the texture *does* need to be reloaded.
       gtc->mark_needs_reload();
-      bool okflag = upload_texture(gtc, force);
+      bool okflag = upload_texture(gtc, force, tex->uses_mipmaps());
       if (!okflag) {
         GLCAT.error()
           << "Could not load " << *tex << "\n";
@@ -4398,7 +4399,7 @@ prepare_sampler(const SamplerState &sampler) {
 
   SamplerState::FilterType minfilter = sampler.get_effective_minfilter();
   SamplerState::FilterType magfilter = sampler.get_effective_magfilter();
-  bool uses_mipmaps = Texture::is_mipmap(minfilter) && !gl_ignore_mipmaps;
+  bool uses_mipmaps = SamplerState::is_mipmap(minfilter) && !gl_ignore_mipmaps;
 
 #ifndef NDEBUG
   if (gl_force_mipmaps) {
@@ -9837,7 +9838,7 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) {
 
   SamplerState::FilterType minfilter = sampler.get_effective_minfilter();
   SamplerState::FilterType magfilter = sampler.get_effective_magfilter();
-  bool uses_mipmaps = Texture::is_mipmap(minfilter) && !gl_ignore_mipmaps;
+  bool uses_mipmaps = SamplerState::is_mipmap(minfilter) && !gl_ignore_mipmaps;
 
 #ifndef NDEBUG
   if (gl_force_mipmaps) {
@@ -9948,6 +9949,8 @@ apply_texture(TextureContext *tc) {
 ////////////////////////////////////////////////////////////////////
 bool CLP(GraphicsStateGuardian)::
 apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) {
+  CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
+
   if (_supports_sampler_objects) {
     // We support sampler objects.  Prepare the sampler object and
     // bind it to the indicated texture unit.
@@ -9965,8 +9968,6 @@ apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) {
     }
 
   } else {
-    CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
-
     // We don't support sampler objects.  We'll have to bind the
     // texture and change the texture parameters if they don't match.
     if (gtc->_active_sampler != sampler) {
@@ -9976,6 +9977,19 @@ apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) {
     }
   }
 
+  if (sampler.uses_mipmaps() && !gtc->_uses_mipmaps) {
+    // The texture wasn't created with mipmaps, but we are trying
+    // to sample it with mipmaps.  We will need to reload it.
+    apply_texture(tc);
+    gtc->mark_needs_reload();
+    bool okflag = upload_texture(gtc, false, true);
+    if (!okflag) {
+      GLCAT.error()
+        << "Could not load " << *gtc->get_texture() << "\n";
+      return false;
+    }
+  }
+
   report_my_gl_errors();
   return true;
 }
@@ -9990,7 +10004,7 @@ apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) {
 //               the texture has no image.
 ////////////////////////////////////////////////////////////////////
 bool CLP(GraphicsStateGuardian)::
-upload_texture(CLP(TextureContext) *gtc, bool force) {
+upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
   PStatGPUTimer timer(this, _load_texture_pcollector);
 
   Texture *tex = gtc->get_texture();
@@ -10161,7 +10175,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force) {
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
   GLenum target = get_texture_target(tex->get_texture_type());
-  bool uses_mipmaps = (tex->uses_mipmaps() && !gl_ignore_mipmaps) || gl_force_mipmaps;
+  uses_mipmaps = (uses_mipmaps && !gl_ignore_mipmaps) || gl_force_mipmaps;
   bool needs_reload = false;
   if (!gtc->_has_storage ||
       gtc->_uses_mipmaps != uses_mipmaps ||
@@ -11453,7 +11467,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
 
   tex->set_ram_image(image, compression, page_size);
 
-  if (tex->uses_mipmaps()) {
+  if (gtc->_uses_mipmaps) {
     // Also get the mipmap levels.
     GLint num_expected_levels = tex->get_expected_num_mipmap_levels();
     GLint highest_level = num_expected_levels;

+ 1 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -490,7 +490,7 @@ protected:
   bool specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler);
   bool apply_texture(TextureContext *tc);
   bool apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc);
-  bool upload_texture(CLP(TextureContext) *gtc, bool force);
+  bool upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps);
   bool upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
                             bool uses_mipmaps, int mipmap_bias,
                             GLenum texture_target, GLenum page_target,

+ 32 - 0
panda/src/gobj/samplerState.I

@@ -307,6 +307,38 @@ get_lod_bias() const {
   return _lod_bias;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: SamplerState::uses_mipmaps
+//       Access: Public
+//  Description: Returns true if the minfilter settings on this
+//               sampler indicate the use of mipmapping, false
+//               otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool SamplerState::
+uses_mipmaps() const {
+  return is_mipmap(get_effective_minfilter());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SamplerState::is_mipmap
+//       Access: Published, Static
+//  Description: Returns true if the indicated filter type requires
+//               the use of mipmaps, or false if it does not.
+////////////////////////////////////////////////////////////////////
+INLINE bool SamplerState::
+is_mipmap(FilterType filter_type) {
+  switch (filter_type) {
+  case SamplerState::FT_nearest_mipmap_nearest:
+  case SamplerState::FT_linear_mipmap_nearest:
+  case SamplerState::FT_nearest_mipmap_linear:
+  case SamplerState::FT_linear_mipmap_linear:
+    return true;
+
+  default:
+    return false;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SamplerState::operator ==
 //       Access: Published

+ 3 - 0
panda/src/gobj/samplerState.h

@@ -110,6 +110,9 @@ PUBLISHED:
   INLINE PN_stdfloat get_max_lod() const;
   INLINE PN_stdfloat get_lod_bias() const;
 
+  INLINE bool uses_mipmaps() const;
+  INLINE static bool is_mipmap(FilterType type);
+
   static string format_filter_type(FilterType ft);
   static FilterType string_filter_type(const string &str);
 

+ 1 - 1
panda/src/gobj/texture.I

@@ -1223,7 +1223,7 @@ get_render_to_texture() const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool Texture::
 uses_mipmaps() const {
-  return is_mipmap(get_effective_minfilter());
+  return SamplerState::is_mipmap(get_effective_minfilter());
 }
 
 ////////////////////////////////////////////////////////////////////

+ 0 - 20
panda/src/gobj/texture.cxx

@@ -1804,26 +1804,6 @@ set_orig_file_size(int x, int y, int z) {
   nassertv(z == cdata->_z_size);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: Texture::is_mipmap
-//       Access: Published, Static
-//  Description: Returns true if the indicated filter type requires
-//               the use of mipmaps, or false if it does not.
-////////////////////////////////////////////////////////////////////
-bool Texture::
-is_mipmap(FilterType filter_type) {
-  switch (filter_type) {
-  case SamplerState::FT_nearest_mipmap_nearest:
-  case SamplerState::FT_linear_mipmap_nearest:
-  case SamplerState::FT_nearest_mipmap_linear:
-  case SamplerState::FT_linear_mipmap_linear:
-    return true;
-
-  default:
-    return false;
-  }
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::prepare_now
 //       Access: Published

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

@@ -458,8 +458,6 @@ PUBLISHED:
   INLINE void set_loaded_from_txo();
   INLINE bool get_loaded_from_txo() const;
 
-  static bool is_mipmap(FilterType type);
-
   INLINE bool get_match_framebuffer_format() const;
   INLINE void set_match_framebuffer_format(bool flag);