mipmap problems

Hi All,

I’m seeing my mipmapped textures corrupted with unexpected colours (usually bright red). The corruption seems to be occuring in the
2x2 or possibly 1x1 mipmap levels. All the other levels seem OK.

This happens on both Win32 and Solaris9, so I suspect it’s not a driver problem. If anyone can suggest anything wrong with my texture loading code, I’d appreciate the feedback. Note that this code is overriding all mipmap data to be white pixels, and I’m still seeing the unexpected ‘red’.

If anyone can explain to me how to attach a screen grab here, I’ll happily show what I’m seeing.

(Apologies for the indentation of the attached)

Code follows:


     private void init(Texture2D t,GL gl) {
        //
        // Convert the BufferedImages to buffers that JOGL can deal with
        //
        BufferedImage[] images = t.getImages();

        buffers = new ByteBuffer[images.length];

        for (int i = 0; i < images.length; i++) {
            switch(images[i].getType()) {

                case BufferedImage.TYPE_INT_ARGB: {
                    int[] data = ((DataBufferInt)
                        images[i].getRaster().getDataBuffer()).getData();
                    buffers[i] = ByteBuffer.allocateDirect(data.length * 3);

                    byte[] b = new byte[3];
                
                    int h = images[i].getHeight();
                    int w = images[i].getWidth();

                    // We must invert the image
                    for (int y = h - 1; y >= 0; y--) {
                        for (int x = 0; x < w; x++) {
                            int index = y * w + x;
                            int val = data[index];

                            int blue  = val & 0xff;
                            int green = (val >> 8)  & 0xff;
                            int red   = (val >> 16) & 0xff;
                        
                            b[0] = (byte)red;
                            b[1] = (byte)green;
                            b[2] = (byte)blue;

                            //
                            // Debug - override the supplied data
                            // with WHITE
                            //
                            b[0] = (byte)0xff;
                            b[1] = (byte)0xff;
                            b[2] = (byte)0xff;

                            buffers[i].put(b);
                        }
                    }
                    break;
                }
 
                default:
                    System.out.println("Unsupported image type " +
                                                images[i].getType()); 
                    System.exit(-1);
            
            }
        }

        //
        // Allocate a texture id
        //
        textureID = createTextureID();
        
        bind(gl);

        gl.glTexParameteri(     GL.GL_TEXTURE_2D,
                                GL.GL_TEXTURE_WRAP_S,
                                GL.GL_REPEAT);

        gl.glTexParameteri(     GL.GL_TEXTURE_2D,
                                GL.GL_TEXTURE_WRAP_T,
                                GL.GL_REPEAT);

        gl.glTexParameteri(     GL.GL_TEXTURE_2D,
                                GL.GL_TEXTURE_MIN_FILTER,
                                GL.GL_LINEAR_MIPMAP_LINEAR);    // Check this
        gl.glTexParameteri(     GL.GL_TEXTURE_2D,
                                GL.GL_TEXTURE_MAG_FILTER,
                                GL.GL_LINEAR);                  // Check this

        //
        //
        //
        for (int i = 0; i < buffers.length; i++) {
            gl.glTexImage2D(GL.GL_TEXTURE_2D,
                            i,
                            GL.GL_RGB,
                            images[i].getWidth(),
                            images[i].getHeight(),
                            0,                          // border width
                            GL.GL_RGB,
                            GL.GL_UNSIGNED_BYTE,
                            buffers[i]);
        }
    }

    protected void bind(GL gl) {
        gl.glBindTexture(GL.GL_TEXTURE_2D, textureID );
    }


I don’t have a lot of time to figure it out for sure. But the one thing that is jumping out to me is that the buffer is ARGB which is 4 byts, not 3. Thats unless you set up your buffered image to be backed by a sperate alpha raster, which is unlikely.

Check out my TextureLoader in the Xith3D project (com.xith3d.loaders.texture.TextureLoader) and the DirectBufferedImage in com.xith3d.image.

David,

If might be somethig like that. The ‘input’ BufferedImages are all TYPE_INT_ARGB. I don’t care about the alpha channel, so I’m trying to discard it and only give the RGB bits of the data to JOGL in a direct ByteBuffer where the data is laid out RGBRGBRGB… etc.

This is working nicely for all the ‘large’ mipmap levels 128x128,64x64,32x32 etc, but seems to break for 2x2 and/or 1x1.

If I change this to give JOGL the full RGBA data (and change the code to specify GL_RGBA) I get no corruption. I don’t see why the first approach doesn’t work though, and I’d prefer not to be incurring a 33% overhead on my texture storage.

Still puzzled,
Rob

If the input buffered images are ARGB then you either have to convert them to RGB or send the data to the card as ARGB. To convert them, just create a buffered image of RGB then write into it from the other.

hmm, /me looks at code again

David,

The code I posted is converting the TYPE_INT_ARGB BufferedImages to RGB format data in the direct ByteBuffers which are then given to JOGL.

It’s taking each int from each BufferedImage, strips out the R,G and B bytes, and puts those in the ByteBuffer.

Rob