Børre Stenseth
JOGL>Textured Box

Textured Cube

What
screen
Drawing a textured box

Texturing is explained in module: Textures. We will write a program that displays different textures on all 6 sides of a cube. We need some code to load images and prepare the data for OpenGL textures. This code is implemented in class TextureReader below. This class is a modified version of the class used by NeHe's [1] texture examples.

We modify the box-class used in Draw a box and we use the stdMaterial class from Some Materials

The application has mouse action and a zoom controller, all implemented in the main class Tex1.java.

TextureReader

This is a simplified version. The complete class as used by NeHe [1] may be found at koders [2] , search with TextureReader

_TextureReader.java
package tex1;
/**
 *
 * @author bs
 */
import com.sun.opengl.util.BufferUtil;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
 * Image loading class that converts BufferedImages into a data
 * structure that can be easily passed to OpenGL.
 * @author Pepijn Van Eeckhoudt
 *
 * Modified by bs: simplified: no .bmp load, no resource access
 * Search in: www.koders.com/? for original
 */
public class TextureReader {
    public static Texture readTexture(String filename)
            throws IOException {
        return readTexture(filename, false);
    }
    public static Texture readTexture(String filename, 
                                      boolean storeAlphaChannel)
            throws IOException {
        BufferedImage bufferedImage;
        bufferedImage=ImageIO.read(new FileInputStream(filename));
        return readPixels(bufferedImage, storeAlphaChannel);
    }

    private static Texture readPixels(BufferedImage img,
                                      boolean storeAlphaChannel) {
        int[] packedPixels = new int[img.getWidth() * img.getHeight()];
        PixelGrabber pixelgrabber =
                new PixelGrabber(img, 0, 0,
                                 img.getWidth(), img.getHeight(),
                                 packedPixels, 0, img.getWidth());
        try {
            pixelgrabber.grabPixels();
        } catch (InterruptedException e) {
            throw new RuntimeException();
        }
        int bytesPerPixel = storeAlphaChannel ? 4 : 3;
        ByteBuffer unpackedPixels =
                BufferUtil.newByteBuffer(packedPixels.length * bytesPerPixel);
        for (int row = img.getHeight() - 1; row >= 0; row--) {
            for (int col = 0; col < img.getWidth(); col++) {
                int packedPixel = packedPixels[row * img.getWidth() + col];
                unpackedPixels.put((byte) ((packedPixel >> 16) & 0xFF));
                unpackedPixels.put((byte) ((packedPixel >> 8) & 0xFF));
                unpackedPixels.put((byte) ((packedPixel >> 0) & 0xFF));
                if (storeAlphaChannel) {
                    unpackedPixels.put((byte) ((packedPixel >> 24) & 0xFF));
                }
            }
        }
        unpackedPixels.flip();
        return new Texture(unpackedPixels, img.getWidth(), img.getHeight());
    }
    public static class Texture {
        private ByteBuffer pixels;
        private int width;
        private int height;
        public Texture(ByteBuffer pixels, int width, int height) {
            this.height = height;
            this.pixels = pixels;
            this.width = width;
        }
        public int getHeight() {return height;}
        public ByteBuffer getPixels() {return pixels;}
        public int getWidth() {return width;}
    }
}

oneTexturedBox

The textures are stored in a array, and are loaded during onconstruction:

// keep an image for each side of the cube
TextureReader.Texture[] textures=new TextureReader.Texture[6];
public oneTexturedBox()
{
    // load images as textures
    textures=new TextureReader.Texture[6];
    for(int ix=0;ix<6;ix++)
    {
        try {
            String filename="images/bs-" + (ix + 1) + ".png";
            textures[ix] = TextureReader.readTexture(filename);
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }       
}

The drawing of the first side:

gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_WRAP_S,GL.GL_CLAMP);
  gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_WRAP_T,GL.GL_CLAMP);
  gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_NEAREST);
  gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_NEAREST);
  gl.glTexEnvi(GL.GL_TEXTURE_ENV,GL.GL_TEXTURE_ENV_MODE,GL.GL_MODULATE);
  gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT,GL.GL_NICEST);
  gl.glDisable(GL.GL_TEXTURE_2D);
  gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB,
                  textures[0].getWidth(),textures[0].getHeight(), 0,
                  GL.GL_RGB, GL.GL_UNSIGNED_BYTE,
                  textures[0].getPixels());
  gl.glEnable(GL.GL_TEXTURE_2D);
gl.glBegin(GL.GL_POLYGON);/* f1: front */
  gl.glNormal3f(-1.0f,0.0f,0.0f);
  gl.glTexCoord2f(0.0f, 0.0f);gl.glVertex3f(0.0f,0.0f,0.0f);
  gl.glTexCoord2f(1.0f, 0.0f);gl.glVertex3f(0.0f,0.0f,1.0f);
  gl.glTexCoord2f(1.0f, 1.0f);gl.glVertex3f(1.0f,0.0f,1.0f);
  gl.glTexCoord2f(0.0f, 1.0f);gl.glVertex3f(1.0f,0.0f,0.0f);
gl.glEnd();

The other sides are rendered according to this pattern:

gl.glDisable(GL.GL_TEXTURE_2D);
  gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB,
                  textures[1].getWidth(),textures[1].getHeight(), 0,
                  GL.GL_RGB, GL.GL_UNSIGNED_BYTE,
                  textures[1].getPixels());
  gl.glEnable(GL.GL_TEXTURE_2D);
gl.glBegin(GL.GL_POLYGON);/* f2: bottom */
  gl.glNormal3f(0.0f,0.0f,-1.0f);
  gl.glTexCoord2f(0.0f, 0.0f);gl.glVertex3f(0.0f,0.0f,0.0f);
  gl.glTexCoord2f(1.0f, 0.0f);gl.glVertex3f(1.0f,0.0f,0.0f);
  gl.glTexCoord2f(1.0f, 1.0f);gl.glVertex3f(1.0f,1.0f,0.0f);
  gl.glTexCoord2f(0.0f, 1.0f);gl.glVertex3f(0.0f,1.0f,0.0f);
gl.glEnd();

The complete class, oneTexturedBox

_oneTexturedBox.java
References
  1. Latest 'NEHE' NewsNEHE, NeonHelium ProductionsOpenGL-tutorials.nehe.gamedev.net/14-03-2009
  1. KodersA site with a lot of searchable code exampleswww.koders.com/?14-05-2009
  • Cube project: https://svn.hiof.no/svn/psource/JOGL/tex1
Maintainance
May 2009, Børre Stenseth
(Welcome) JOGL>Textured Box (Bezier surface)