Texture Mapping

Hi,

I’ve looked at the example of texture mapping on the NeHe site, and was wondering if you can put four different images on the four sides of the cube??

Thanks!

Yes you can. You must modify init to load the 4 textures. Then in your display method :

bind texture 1
draw quad 1

bind texture 4
draw quad 4

I have tried this but it doesn’t seem to work… it only displays the last texture that was initialised on all the cube sides.

I want to display four different textures on the same cube, so that I have one texture on the front of the cube, another texture on the back of the cube, one texture on the left side of the cube, and finally one texture on the right side of the cube. the top and bottom are not required as I will only be rotating the cube along the y axis…

this is what i have so far…

//draw the cube within the display() method

gl.glBegin(GL.GL_QUADS);

// Front Face
gl.glBindTexture(GL.GL_TEXTURE_2D, texture1);
gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, 1.0f);
gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, 1.0f);
gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, 1.0f);
gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f);

// Back Face
gl.glBindTexture(GL.GL_TEXTURE_2D, texture2);
gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f);
gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, -1.0f);
gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, -1.0f);
gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f);

// Right face
gl.glBindTexture(GL.GL_TEXTURE_2D, texture3);
gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f);
gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, -1.0f);
gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, 1.0f);
gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, 1.0f);

// Left Face
gl.glBindTexture(GL.GL_TEXTURE_2D, texture4);
gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f);
gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, 1.0f);
gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f);
gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, -1.0f);

gl.glEnd();

then this is my init() method, it is basically straight out of NeHE Lesson 06 about Texture Mapping, I have just created three extra textures.

public void init(GLDrawable gLDrawable)
{

final GL gl = gLDrawable.getGL();
gl.glShadeModel(GL.GL_SMOOTH);gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
gl.glClearDepth(1.0f);gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LEQUAL);gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);Calculations
gl.glEnable(GL.GL_TEXTURE_2D);
gLDrawable.addKeyListener(this);

texture1 = genTexture(gl);
gl.glBindTexture(GL.GL_TEXTURE_2D, texture1);
BufferedImage img1 = readPNGImage(“data/NeHe.png”);
makeRGBTexture(gl, gLDrawable.getGLU(), img1, GL.GL_TEXTURE_2D, false);

texture2 = genTexture(gl);
gl.glBindTexture(GL.GL_TEXTURE_2D, texture2);
BufferedImage img2 = readPNGImage(“data/HL_Pitch_Big.png”);
makeRGBTexture(gl, gLDrawable.getGLU(), img2, GL.GL_TEXTURE_2D, false);

texture3 = genTexture(gl);
gl.glBindTexture(GL.GL_TEXTURE_2D, texture3);
BufferedImage img3 = readPNGImage(“data/NeHe.png”);
makeRGBTexture(gl, gLDrawable.getGLU(), img3, GL.GL_TEXTURE_2D, false);

texture4 = genTexture(gl);
gl.glBindTexture(GL.GL_TEXTURE_2D, texture4);
BufferedImage img4 = readPNGImage(“data/Shading_Velocity_Big.png”);
makeRGBTexture(gl, gLDrawable.getGLU(), img4, GL.GL_TEXTURE_2D, false);

gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR);
}

Any help would be great!
Thanks

Just a wild guess : aren’t calls to glBindTexture supposed to be forbidden within glBegin / glEnd ? That would explain why the last texture you initialised is the only one used.

EDIT : Yes they are (just checked the redbook). Change your code with :

glBindTexture 1
glBegin
//draw quad 1
glEnd

Okay sorry to be a pain in the a$$, but this still ain;t working for me!

I have taken your advice and made the glBind calls outside the Begin and End statements… but this still only seems to draw the last texture that I intialised. Can you help? I will post most of the program here, it is just jogl nehe lesson 6 with a few extra textures added.

There are a few methods within this that i don’t understand fully, so maybe the problem lies in there somewhere.

This is my display method…


      gl.glBindTexture(GL.GL_TEXTURE_2D, texture1);
      gl.glBegin(GL.GL_QUADS);
        // Front Face
        gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f,  1.0f);
        gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f,  1.0f);
        gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f,  1.0f);
        gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f,  1.0f);
      gl.glEnd();
      
      
      gl.glBindTexture(GL.GL_TEXTURE_2D, texture2);
      gl.glBegin(GL.GL_QUADS);
        // Back Face
        gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f);
        gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f);
      gl.glEnd();


      gl.glBindTexture(GL.GL_TEXTURE_2D, texture3);
      gl.glBegin(GL.GL_QUADS);
        // Right face
        gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f);
        gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f,  1.0f);
        gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f,  1.0f);
      gl.glEnd();
      
      gl.glBindTexture(GL.GL_TEXTURE_2D, texture4);
      gl.glBegin(GL.GL_QUADS);
        // Left Face
        gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f);
        gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f,  1.0f);
        gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f,  1.0f);
        gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f, -1.0f);
      gl.glEnd();


And this is my init() method…


final GL gl = gLDrawable.getGL();
      gl.glShadeModel(GL.GL_SMOOTH);              // Enable Smooth Shading
      gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    // Black Background
      gl.glClearDepth(1.0f);                      // Depth Buffer Setup
      gl.glEnable(GL.GL_DEPTH_TEST);                                          // Enables Depth Testing
      gl.glDepthFunc(GL.GL_LEQUAL);                                                // The Type Of Depth Testing To Do
      gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);      // Really Nice Perspective Calculations
      gl.glEnable(GL.GL_TEXTURE_2D);
      gLDrawable.addKeyListener(this);
      
      texture1 = genTexture(gl);
      gl.glBindTexture(GL.GL_TEXTURE_2D, texture1);
      BufferedImage img1 = readPNGImage("data/NeHe.png");
      makeRGBTexture(gl, gLDrawable.getGLU(), img1, GL.GL_TEXTURE_2D, false);
      
      texture2 = genTexture(gl);
      gl.glBindTexture(GL.GL_TEXTURE_2D, texture2);
      BufferedImage img2 = readPNGImage("data/HL_Pitch_Big.png");
      makeRGBTexture(gl, gLDrawable.getGLU(), img2, GL.GL_TEXTURE_2D, false);
      
      texture3 = genTexture(gl);
      gl.glBindTexture(GL.GL_TEXTURE_2D, texture3);
      BufferedImage img3 = readPNGImage("data/NeHe.png");
      makeRGBTexture(gl, gLDrawable.getGLU(), img3, GL.GL_TEXTURE_2D, false);
      
      texture4 = genTexture(gl);
      gl.glBindTexture(GL.GL_TEXTURE_2D, texture4);
      BufferedImage img4 = readPNGImage("data/Shading_Velocity_Big.png");
      makeRGBTexture(gl, gLDrawable.getGLU(), img4, GL.GL_TEXTURE_2D, false);
      
              gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
              gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR);


And finally, these are the methods that I don’t fully understand… I have a feeling that the problem lies maybe in the last method, private int genTexture(GL gl).



    private BufferedImage readPNGImage(String resourceName)
    {
      try
      {
        URL url = getResource(resourceName);
        if (url == null)
        {
          throw new RuntimeException("Error reading resource " + resourceName);
        }
        BufferedImage img = ImageIO.read(url);
        java.awt.geom.AffineTransform tx = java.awt.geom.AffineTransform.getScaleInstance(1, -1); 
        tx.translate(0, -img.getHeight(null)); 
        AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); 
        img = op.filter(img, null); 
        return img;
      }
      catch (IOException e)
      {
        throw new RuntimeException(e);
      }
    }
    
    private void makeRGBTexture(GL gl, GLU glu, BufferedImage img, int target, boolean mipmapped)
    {
      ByteBuffer dest = null;
      switch (img.getType())
      {
        case BufferedImage.TYPE_3BYTE_BGR:
        case BufferedImage.TYPE_CUSTOM:
        {
          byte[] data = ((DataBufferByte) img.getRaster().getDataBuffer()).getData();
          dest = ByteBuffer.allocateDirect(data.length);
          dest.order(ByteOrder.nativeOrder());
          dest.put(data, 0, data.length);
          break;
        }
        case BufferedImage.TYPE_INT_RGB:
        {
          int[] data = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
          dest = ByteBuffer.allocateDirect(data.length * BufferUtils.SIZEOF_INT);
          dest.order(ByteOrder.nativeOrder());
          dest.asIntBuffer().put(data, 0, data.length);
          break;
        }
        default:
          throw new RuntimeException("Unsupported image type " + img.getType());
      }
      
      if (mipmapped)
      {
        glu.gluBuild2DMipmaps(target, GL.GL_RGB8, img.getWidth(), img.getHeight(), GL.GL_RGB, GL.GL_UNSIGNED_BYTE, dest);
      }
      else
      {
        gl.glTexImage2D(target, 0, GL.GL_RGB, img.getWidth(), img.getHeight(), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, dest);
      }
    }

    private int genTexture(GL gl)
    {
      final int[] tmp = new int[1];
      gl.glGenTextures(1, tmp);
      return tmp[0];
    }

Thanks again for any help provided.

Add :


gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR);

after each makeRGBTexture call. I can’t test it at the moment but I should be able to spent more time on it in a few hours. :slight_smile:

what value does genTexture(GL gl) return?
Maybe the each texture is overwritten by the next.

funny thing: My game had the same problem.
My mistake was binding textures this way:

gl.glBindTexture(GL.GL_TEXTURE, number);

Pretty tricky, eh?
The right method is:

gl.glBindTexture(GL.GL_TEXTURE_2D, number);

[quote]private int genTexture(GL gl)
{
final int[] tmp = new int[1];
gl.glGenTextures(1, tmp);
return tmp[0];
}


Thanks again for any help provided.
[/quote]
The method above (genTexture()) (as far as I understand (please correct me if I'm wrong  ;) ) is only designed to work with a single texture.

My solution (which currently is not displaying any textures at all!!) But might be of some use to you:


public class TextureLibrary {
private static final int maxNumberOfTextures_ = 10;
private static int numLoadedTextures_ = 0;
private static int[] textureAddressLookupTable_ = new int[maxNumberOfTextures_];

public TextureLibrary(GL gl) {
//init the textureAddressLookupTable
gl.glGenTextures(maxNumberOfTextures_, textureAddressLookupTable_);
}

  public void addTexture(GL gl, GLU glu, String pngFileName) {
        int textureIDNum = genTextureIDNum(gl);
        gl.glBindTexture(GL.GL_TEXTURE_2D, textureIDNum);
        BufferedImage img = ImageUtils.readPNGImage(pngFileName);
        System.out.println(
              "Reading Texture: '"
                    + pngFileName
                    + "', width="
                    + img.getWidth()
                    + ", height="
                    + img.getHeight());
        
        gl.glLoadIdentity();
        
        //uncomment the lines below to verify that image has been read into
        //img properly...
        //gl.glDrawPixels (img.getWidth(), img.getHeight(), GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, img.getRGB(0,
        //0,
        //img.getWidth(),
        //img.getHeight(),
        //null,
        //0,
        //img.getWidth()));
        
        ImageUtils.makeRGBTexture(gl, glu, img, numLoadedTextures_, false);

        //texture filtering.  Don't understand...
        //gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
        //gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
        numLoadedTextures_++;
  }

  private int genTextureIDNum(GL gl) {
        return textureAddressLookupTable_[numLoadedTextures_];
  }

  /**
   * @param i
   * @return
   */
  public int getTexture(int i) {
        return textureAddressLookupTable_[i];
  }

}



My understanding is that glGenTextures returns an array of indices to textures (into it's second argument).  (The reason for this, I would imagine is so that openGL code can quickly access textures that you've loaded into memory).

Of course -- I must be wrong about something -- because I just get a black quad, when I try to map a texture to it.  (I'm currently wondering if it is this computers on-board-shite-graphics card giving me grief)...

Tips / objections / crit welcome...

Hello All,

I’ve figrured out how to get this to work.
Pretty simple after you figure it out.
Just get rid of genTexture()
In you init method do this

     //setup textures
      int[] tmp = new int[2];
      gl.glGenTextures(1, tmp);
      //now we have space for 2 textures
      gl.glBindTexture(GL.GL_TEXTURE_2D, tmp[0]);
      BufferedImage img = readPNGImage("image1.png");
      makeRGBTexture(gl, drawable.getGLU(), img, GL.GL_TEXTURE_2D, false);
      gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
      gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR);
      
      gl.glBindTexture(GL.GL_TEXTURE_2D, tmp[1]);
      BufferedImage img1 = readPNGImage("image2.png");
      makeRGBTexture(gl, drawable.getGLU(), img1, GL.GL_TEXTURE_2D, false);
      gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
      gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR);

I then build some display lists using tmp[0] and tmp[1] and call them in display.
Checkout my little app here

http://www.drobbins.net:8080/SpriteIIServer/SpriteII.html

use the top scrollbar to see my first feeble attempts at IK

Dave

Pffffffffft people; you should know how to use some of Opengl’s hidden sweetness :smiley:


  public static void drawSkyBox(float size){

    GL11.glPushMatrix();
    if(!center)
    GL11.glTranslatef(GLCamera.getXPosition(),
                      GLCamera.getYPosition(),
                      GLCamera.getZPosition());
    GL11.glDisable(GL11.GL_DEPTH_TEST);

    GL11.glEnable(ARBTextureCubeMap.GL_TEXTURE_CUBE_MAP_ARB);
    GL11.glBindTexture(ARBTextureCubeMap.GL_TEXTURE_CUBE_MAP_ARB, staticCM);

    GL11.glBegin(GL11.GL_QUADS);
    GL11.glTexCoord3f( 1.0f, 1.0f,-1.0f);  GL11.glVertex3f( size,  size,-size);
    GL11.glTexCoord3f( 1.0f,-1.0f,-1.0f);  GL11.glVertex3f( size, -size,-size);
    GL11.glTexCoord3f( 1.0f,-1.0f, 1.0f);  GL11.glVertex3f( size, -size, size);
    GL11.glTexCoord3f( 1.0f, 1.0f, 1.0f);  GL11.glVertex3f( size,  size, size);
    GL11.glTexCoord3f(-1.0f, 1.0f, 1.0f);  GL11.glVertex3f(-size,  size, size);
    GL11.glTexCoord3f(-1.0f,-1.0f, 1.0f);  GL11.glVertex3f(-size, -size, size);
    GL11.glTexCoord3f(-1.0f,-1.0f,-1.0f);  GL11.glVertex3f(-size, -size,-size);
    GL11.glTexCoord3f(-1.0f, 1.0f,-1.0f);  GL11.glVertex3f(-size,  size,-size);
    GL11.glTexCoord3f(-1.0f, 1.0f, 1.0f);  GL11.glVertex3f(-size,  size, size);
    GL11.glTexCoord3f(-1.0f, 1.0f,-1.0f);  GL11.glVertex3f(-size,  size,-size);
    GL11.glTexCoord3f( 1.0f, 1.0f,-1.0f);  GL11.glVertex3f( size,  size,-size);
    GL11.glTexCoord3f( 1.0f, 1.0f, 1.0f);  GL11.glVertex3f( size,  size, size);
    GL11.glTexCoord3f(-1.0f,-1.0f,-1.0f);  GL11.glVertex3f(-size, -size,-size);
    GL11.glTexCoord3f(-1.0f,-1.0f, 1.0f);  GL11.glVertex3f(-size, -size, size);
    GL11.glTexCoord3f( 1.0f,-1.0f, 1.0f);  GL11.glVertex3f( size, -size, size);
    GL11.glTexCoord3f( 1.0f,-1.0f,-1.0f);  GL11.glVertex3f( size, -size,-size);
    GL11.glTexCoord3f( 1.0f, 1.0f, 1.0f);  GL11.glVertex3f( size,  size, size);
    GL11.glTexCoord3f( 1.0f,-1.0f, 1.0f);  GL11.glVertex3f( size, -size, size);
    GL11.glTexCoord3f(-1.0f,-1.0f, 1.0f);  GL11.glVertex3f(-size, -size, size);
    GL11.glTexCoord3f(-1.0f, 1.0f, 1.0f);  GL11.glVertex3f(-size,  size, size);
    GL11.glTexCoord3f(-1.0f, 1.0f,-1.0f);  GL11.glVertex3f(-size,  size,-size);
    GL11.glTexCoord3f(-1.0f,-1.0f,-1.0f);  GL11.glVertex3f(-size, -size,-size);
    GL11.glTexCoord3f( 1.0f,-1.0f,-1.0f);  GL11.glVertex3f( size, -size,-size);
    GL11.glTexCoord3f( 1.0f, 1.0f,-1.0f);  GL11.glVertex3f( size,  size,-size);
    GL11.glEnd();
    GL11.glDisable(ARBTextureCubeMap.GL_TEXTURE_CUBE_MAP_ARB);
    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glPopMatrix();
  }

^That code only needs few modifications to go along with JoGL :wink:

Hi, I am currently trying
to learn JOGL, and I used NeHe Lesson06 sample code, the sample code works
fine with NeHe.png image file, but if you change to other images, and after you put the pictures on the Cube, the texture
becomes different color, for example, the picture for the earth (I converted it from BMP to JPEG using microsoft paint progream), I
put it onto the cube, then color of the ocean originally was blue, but when it
is on the earth ball, it changed to brown.
I tried some other image files, both .jpg and .png images, some of them worked
fine, some of them changed color as well. I am not sure why.
I checked the image type, for the NeHe.png file ,it’s type is BufferedImage.TYPE_CUSTOM, it means unkown type, in this case it is working fine, BUT images with other types like TYPE_3BYTE_BGR will change color or even do not show up when I put onto the cube in NeHe example lesson06 (the NeHe.png works fine).

Anybody knows what happened here? or what have I missed?

Thanks very much in advance.

David

ddu88 : IIRC the texture loader from the NeHe Lesson06 ports makes heavy assumption on image formats. It was not designed to handle any images, so you’ll have to create your own BufferedImage -> GL texture code.

For a quick’n’dirty solution, you could try to change GL_RGB to GL_BGR in the GL calls : since the two channels are reversed when the texture is loaded, it should work.

Hi, I just tried again, with GL_RGB, the texture can be loaded, but color changed, with GL_BGR, the texture can not be loaded.

Well it took me almost 2 days to get a “generic” texture loading class which can convert most BufferedImages into textures. I first wrote a small program that loads an image and dumps every useful information and then I tested various GL parameters to display it correctly.

Now it works nicely, but I haven’t tested it much (currently I mostly do ports from C++ tutorials to Java). I’ll have to clean it when I’ll start my first engine :slight_smile: If you want I can mail you the files.