Patch for TextureState (problem with DDS textures as cubemap's faces)

If someone is interested, here is patch that fixes problem with using compressed textures with pregenerated mipmaps (like in DDS format) as cubemap faces:



### Eclipse Workspace Patch 1.0
#P JME2
Index: src/com/jme/scene/state/lwjgl/LWJGLTextureState.java
===================================================================
--- src/com/jme/scene/state/lwjgl/LWJGLTextureState.java   (revision 4009)
+++ src/com/jme/scene/state/lwjgl/LWJGLTextureState.java   (working copy)
@@ -611,8 +611,7 @@
                                 }
                             }
                         } else {
-                            logger
-                                    .warning("This card does not support Cubemaps.");
+                            logger.warning("This card does not support Cubemaps.");
                             return;
                         }
                         break;
@@ -624,157 +623,182 @@
                 // Get mipmap data sizes and amount of mipmaps to send to
                 // opengl. Then loop through all mipmaps and send them.
                 int[] mipSizes = image.getMipMapSizes();
-                ByteBuffer data = image.getData(0);
-                if (type == Type.ThreeDimensional) {
-                    if (supportsTexture3D) {
-                        // concat data into single buffer:
-                        int dSize = 0;
-                        int count = 0;
-                        for (int x = 0; x < image.getData().size(); x++) {
-                            if (image.getData(x) != null) {
-                                data = image.getData(x);
-                                dSize += data.limit();
-                                count++;
-                            }
-                        }
-                        // reuse buffer if we can.
-                        if (count != 1) {
-                            data = BufferUtils.createByteBuffer(dSize);
-                            for (int x = 0; x < image.getData().size(); x++) {
-                                if (image.getData(x) != null) {
-                                    data.put(image.getData(x));
-                                }
-                            }
-                            // ensure the buffer is ready for reading
-                            data.flip();
-                        }
-                    } else {
-                        logger.warning("This card does not support Texture3D.");
-                        return;
+                ByteBuffer data = null;
+               
+                if (type == Type.CubeMap) {
+                   if (supportsTextureCubeMap) {
+                      for (TextureCubeMap.Face face : TextureCubeMap.Face.values()) {
+                         data = image.getData(face.ordinal());
+                         int pos = 0;
+                         int max = 1;
+
+                         if (mipSizes == null) {
+                            mipSizes = new int[] { data.capacity() };
+                         } else if (texture.getMinificationFilter().usesMipMapLevels()) {
+                            max = mipSizes.length;
+                         }
+
+                         for (int m = 0; m < max; m++) {
+                            int width = Math.max(1, image.getWidth() >> m);
+                            int height = type != Type.OneDimensional ? Math.max(1, image.getHeight() >> m) : 0;
+
+                               data.position(pos);
+                               data.limit(pos + mipSizes[m]);
+
+                               if (TextureStateRecord.isCompressedType(image.getFormat())) {
+                                  ARBTextureCompression.glCompressedTexImage2DARB(
+                                        getGLCubeMapFace(face),
+                                        m,
+                                        TextureStateRecord
+                                        .getGLDataFormat(image
+                                              .getFormat()),
+                                              width, height,
+                                              hasBorder ? 1 : 0, data);
+                               } else {
+                                  GL11.glTexImage2D(
+                                        getGLCubeMapFace(face),
+                                        m,
+                                        TextureStateRecord
+                                        .getGLDataFormat(image
+                                              .getFormat()),
+                                              width, height,
+                                              hasBorder ? 1 : 0,
+                                              TextureStateRecord.getGLPixelFormat(image.getFormat()),
+                                              GL11.GL_UNSIGNED_BYTE, data);
+                               }
+                               pos += mipSizes[m];
+                         }
+                      }
+                   } else {
+                      logger.warning("This card does not support CubeMaps.");
+                      return;
+                   }
+                } else {
+                    data = image.getData(0);
+                    int pos = 0;
+                    int max = 1;
+                   
+                    if (mipSizes == null) {
+                        mipSizes = new int[] { data.capacity() };
+                    } else if (texture.getMinificationFilter().usesMipMapLevels()) {
+                        max = mipSizes.length;
                     }
-                }
-                int max = 1;
-                int pos = 0;
-                if (mipSizes == null) {
-                    mipSizes = new int[] { data.capacity() };
-                } else if (texture.getMinificationFilter().usesMipMapLevels()) {
-                    max = mipSizes.length;
-                }
+                   
+                    if (type == Type.ThreeDimensional) {
+                       if (supportsTexture3D) {
+                          // concat data into single buffer:
+                          int dSize = 0;
+                          int count = 0;
+                          for (int x = 0; x < image.getData().size(); x++) {
+                             if (image.getData(x) != null) {
+                                data = image.getData(x);
+                                dSize += data.limit();
+                                count++;
+                             }
+                          }
+                          // reuse buffer if we can.
+                          if (count != 1) {
+                             data = BufferUtils.createByteBuffer(dSize);
+                             for (int x = 0; x < image.getData().size(); x++) {
+                                if (image.getData(x) != null) {
+                                   data.put(image.getData(x));
+                                }
+                             }
+                             // ensure the buffer is ready for reading
+                             data.flip();
+                          }
+                       } else {
+                          logger.warning("This card does not support Texture3D.");
+                          return;
+                       }
+                    }
 
-                for (int m = 0; m < max; m++) {
-                    int width = Math.max(1, image.getWidth() >> m);
-                    int height = type != Type.OneDimensional ? Math.max(1,
-                            image.getHeight() >> m) : 0;
-                    int depth = type == Type.ThreeDimensional ? Math.max(1,
-                            image.getDepth() >> m) : 0;
+                   for (int m = 0; m < max; m++) {
+                      int width = Math.max(1, image.getWidth() >> m);
+                      int height = type != Type.OneDimensional ? Math.max(1,
+                            image.getHeight() >> m) : 0;
+                        int depth = type == Type.ThreeDimensional ? Math.max(1,
+                              image.getDepth() >> m) : 0;
 
-                    data.position(pos);
-                    data.limit(pos + mipSizes[m]);
+                                data.position(pos);
+                                data.limit(pos + mipSizes[m]);
 
-                    switch (type) {
-                        case TwoDimensional:
-                            if (TextureStateRecord.isCompressedType(image
-                                    .getFormat())) {
-                                ARBTextureCompression
-                                        .glCompressedTexImage2DARB(
-                                                GL11.GL_TEXTURE_2D, m,
-                                                TextureStateRecord
-                                                        .getGLDataFormat(image
-                                                                .getFormat()),
-                                                width, height, hasBorder ? 1
-                                                        : 0, data);
-                            } else {
-                                GL11.glTexImage2D(GL11.GL_TEXTURE_2D, m,
-                                        TextureStateRecord
-                                                .getGLDataFormat(image
-                                                        .getFormat()), width,
-                                        height, hasBorder ? 1 : 0,
-                                        TextureStateRecord
-                                                .getGLPixelFormat(image
-                                                        .getFormat()),
-                                        GL11.GL_UNSIGNED_BYTE, data);
-                            }
-                            break;
-                        case OneDimensional:
-                            if (TextureStateRecord.isCompressedType(image
-                                    .getFormat())) {
-                                ARBTextureCompression
-                                        .glCompressedTexImage1DARB(
-                                                GL11.GL_TEXTURE_1D, m,
-                                                TextureStateRecord
-                                                        .getGLDataFormat(image
-                                                                .getFormat()),
-                                                width, hasBorder ? 1 : 0, data);
-                            } else {
-                                GL11.glTexImage1D(GL11.GL_TEXTURE_1D, m,
-                                        TextureStateRecord
-                                                .getGLDataFormat(image
-                                                        .getFormat()), width,
-                                        hasBorder ? 1 : 0, TextureStateRecord
-                                                .getGLPixelFormat(image
-                                                        .getFormat()),
-                                        GL11.GL_UNSIGNED_BYTE, data);
-                            }
-                            break;
-                        case ThreeDimensional:
-                            // already checked for support above...
-                            if (TextureStateRecord.isCompressedType(image
-                                    .getFormat())) {
-                                ARBTextureCompression
-                                        .glCompressedTexImage3DARB(
-                                                GL12.GL_TEXTURE_3D, m,
-                                                TextureStateRecord
-                                                        .getGLDataFormat(image
-                                                                .getFormat()),
-                                                width, height, depth,
-                                                hasBorder ? 1 : 0, data);
-                            } else {
-                                GL12.glTexImage3D(GL12.GL_TEXTURE_3D, m,
-                                        TextureStateRecord
-                                                .getGLDataFormat(image
-                                                        .getFormat()), width,
-                                        height, depth, hasBorder ? 1 : 0,
-                                        TextureStateRecord
-                                                .getGLPixelFormat(image
-                                                        .getFormat()),
-                                        GL11.GL_UNSIGNED_BYTE, data);
-                            }
-                            break;
-                        case CubeMap:
-                            if (supportsTextureCubeMap) {
-                                for (TextureCubeMap.Face face : TextureCubeMap.Face
-                                        .values()) {
-                                    if (TextureStateRecord
-                                            .isCompressedType(image.getFormat())) {
-                                        ARBTextureCompression
-                                                .glCompressedTexImage2DARB(
-                                                        getGLCubeMapFace(face),
-                                                        m,
-                                                        TextureStateRecord
-                                                                .getGLDataFormat(image
-                                                                        .getFormat()),
-                                                        width, height,
-                                                        hasBorder ? 1 : 0, data);
-                                    } else {
-                                        GL11.glTexImage2D(
-                                                getGLCubeMapFace(face), m,
-                                                TextureStateRecord
-                                                        .getGLDataFormat(image
-                                                                .getFormat()),
-                                                width, height, hasBorder ? 1
-                                                        : 0, TextureStateRecord
-                                                        .getGLPixelFormat(image
-                                                                .getFormat()),
-                                                GL11.GL_UNSIGNED_BYTE, data);
-                                    }
+                                switch (type) {
+                                case TwoDimensional:
+                                   if (TextureStateRecord.isCompressedType(image
+                                         .getFormat())) {
+                                      ARBTextureCompression
+                                      .glCompressedTexImage2DARB(
+                                            GL11.GL_TEXTURE_2D, m,
+                                            TextureStateRecord
+                                            .getGLDataFormat(image
+                                                  .getFormat()),
+                                                  width, height, hasBorder ? 1
+                                                        : 0, data);
+                                   } else {
+                                      GL11.glTexImage2D(GL11.GL_TEXTURE_2D, m,
+                                            TextureStateRecord
+                                            .getGLDataFormat(image
+                                                  .getFormat()), width,
+                                                  height, hasBorder ? 1 : 0,
+                                                        TextureStateRecord
+                                                        .getGLPixelFormat(image
+                                                              .getFormat()),
+                                                              GL11.GL_UNSIGNED_BYTE, data);
+                                   }
+                                   break;
+                                case OneDimensional:
+                                   if (TextureStateRecord.isCompressedType(image
+                                         .getFormat())) {
+                                      ARBTextureCompression
+                                      .glCompressedTexImage1DARB(
+                                            GL11.GL_TEXTURE_1D, m,
+                                            TextureStateRecord
+                                            .getGLDataFormat(image
+                                                  .getFormat()),
+                                                  width, hasBorder ? 1 : 0, data);
+                                   } else {
+                                      GL11.glTexImage1D(GL11.GL_TEXTURE_1D, m,
+                                            TextureStateRecord
+                                            .getGLDataFormat(image
+                                                  .getFormat()), width,
+                                                  hasBorder ? 1 : 0, TextureStateRecord
+                                                        .getGLPixelFormat(image
+                                                              .getFormat()),
+                                                              GL11.GL_UNSIGNED_BYTE, data);
+                                   }
+                                   break;
+                                case ThreeDimensional:
+                                   // already checked for support above...
+                                   if (TextureStateRecord.isCompressedType(image
+                                         .getFormat())) {
+                                      ARBTextureCompression
+                                      .glCompressedTexImage3DARB(
+                                            GL12.GL_TEXTURE_3D, m,
+                                            TextureStateRecord
+                                            .getGLDataFormat(image
+                                                  .getFormat()),
+                                                  width, height, depth,
+                                                  hasBorder ? 1 : 0, data);
+                                   } else {
+                                      GL12.glTexImage3D(GL12.GL_TEXTURE_3D, m,
+                                            TextureStateRecord
+                                            .getGLDataFormat(image
+                                                  .getFormat()), width,
+                                                  height, depth, hasBorder ? 1 : 0,
+                                                        TextureStateRecord
+                                                        .getGLPixelFormat(image
+                                                              .getFormat()),
+                                                              GL11.GL_UNSIGNED_BYTE, data);
+                                   }
+                                   break;
                                 }
-                            }
-                            break;
-                    }
-
-                    pos += mipSizes[m];
+                                pos += mipSizes[m];
+                   }
                 }
-                data.clear();
+                if (data != null) {
+                   data.clear();
+                }
             }
         }
     }



I believe it should also be done for JOGL renderer. Please let me know if someone is interested - I can do it for JOGL to.

After applying this patch you can easily use DDS textures with or without pregenerated mipmaps as cubemap faces.

Thanks,
Konrad.

Thanks, I tested this patch and it seems to work with my DDSLoader updates.

See this thread: http://www.jmonkeyengine.com/jmeforum/index.php?topic=8869.msg68662#new

Great news.



Thanks,

Konrad.

There was an issue though; if you use ATI's Compressonator tool with D3DX mipmap generator, it will sometimes make less mipmaps levels than needed, which will make an invalid texture on the card (just whiteness). So you have to use the other two mipmap generator algorithms (Box-Filter and D3D)

I also make a small patch to TextureManager. It have to be used of course with your updated of DDSLoader.

After applying this patch you can just load and use DDS cubemap textures through TextureManager:



### Eclipse Workspace Patch 1.0
#P JME2
Index: src/com/jme/util/TextureManager.java
===================================================================
--- src/com/jme/util/TextureManager.java   (revision 4009)
+++ src/com/jme/util/TextureManager.java   (working copy)
@@ -60,6 +60,7 @@
 import com.jme.image.Image;
 import com.jme.image.Texture;
 import com.jme.image.Texture2D;
+import com.jme.image.TextureCubeMap;
 import com.jme.image.util.DDSLoader;
 import com.jme.image.util.TGALoader;
 import com.jme.renderer.Renderer;
@@ -345,11 +346,6 @@
             return texture;
         }
 
-        // Default to Texture2D
-        if (texture == null) {
-            texture = new Texture2D();
-        }
-
         if (imageData == null)
             imageData = loadImage(tkey);
 
@@ -360,6 +356,15 @@
             return TextureState.getDefaultTexture();
         }
 
+        // Default to Texture2D
+        if (texture == null) {
+           if (imageData.getData().size() == 6) {
+              texture = new TextureCubeMap();
+           } else {
+              texture = new Texture2D();
+           }
+        }
+
         // Use a tex state only to determine if S3TC is available.
         TextureState state = null;
         if (DisplaySystem.getDisplaySystem() != null



Thanks,
Konrad

Nice! I sent an email to MrCoder to request those patches to be applied.

I had the itch to do something engine related and saw no one has gotten around to helping apply these patches yet… so in they go.

off topic: hehe, I'm glad you found this answer to the "where" question :wink: