Only seeing one texture

I’m currently seeing one texture, instead of 3 only the first one is displayed:

This is my ‘render’ method still in it’s infant stage



    public static void drawFace( BSPFace face )
    {
        gl.glBegin( GL.GL_POLYGON );
        gl.glEnable( GL.GL_TEXTURE_2D );
              
        gl.glBindTexture( GL.GL_TEXTURE_2D, Textures.textureNameDiffuse[face.getTextureID()] );
        //loop through the vertices
        for(int i = 0; i < face.getNumberVertices(); i++ )
        {
             gl.glTexCoord2f( face.getVertices()[i].getU(),
                             face.getVertices()[i].getV() );
             gl.glVertex3f( face.getVertices()[i].getX(),
                            face.getVertices()[i].getY(),
                            face.getVertices()[i].getZ() );
        }
        gl.glDisable(GL.GL_TEXTURE_2D);
        gl.glEnd();
    }

i’m pretty sure i’ve loaded all the textures into my ‘textureDiffuse’ array. So what could be the problem?

I would move those glEnable/glDisable/glBindTexture calls outside the immediate drawing code:



    gl.glEnable( GL.GL_TEXTURE_2D );
    gl.glBindTexture( GL.GL_TEXTURE_2D, Textures.textureNameDiffuse[face.getTextureID()] );
    
    gl.glBegin( GL.GL_POLYGON );
    ...          
    gl.glEnd();

    gl.glDisable(GL.GL_TEXTURE_2D);


From glEnable spec:
“GL_INVALID_OPERATION is generated if glEnable is called between a call to glBegin and the corresponding call to glEnd.”

…and the same applies to glDisable and glBindTexture

Hi,

I am wondering whether you found the solution of your problem because i am facing something similar.

i define an integer array of size three called “textures”

In the init methods i use

glGentextures(3, textures);

and i repeat three times
loadTexture(url[i]); //this load the texture into a byte buffer
glBindTexture(GL_TEXTURE_2D,textures[i])
glTexImage2D(…)

where i goes from 0 to 2 inclusive.

I am pretty sure that all the parameters of this functions are corrects as it works for one textures.

But once loaded when i use glBindTexture() inside the display method only the last one loaded is actually applied…

I had the same problem and it took me 3 days before I can figure it out.

Instead of

 gl.glBindTexture(GL_TEXTURE_2D,textures[i]) 

you must use:

 gl.glBindTexture(GL_TEXTURE_2D, i ) 

No, don’t do that.

cyberyoyo: it’s a coincidence, that your array index matches your texture name!

You seem to have a problem in your texture-initialization, so that you don’t have the right texture names in your textures-array. Print out it contents and see, if there are different integers in the array…

      myGL.glGenTextures(3,textures);
  myGL.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
      loadTexture(0);
      myGL.glTexImage2D(GL.GL_TEXTURE_2D, 0, 3, tWidth, tHeight,0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, texture);
      myGL.glBindTexture(GL.GL_TEXTURE_2D, textures[1]);
      loadTexture(1);
      myGL.glTexImage2D(GL.GL_TEXTURE_2D, 0, 3, tWidth, tHeight,0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, texture);
            myGL.glBindTexture(GL.GL_TEXTURE_2D, textures[2]);
      loadTexture(2);
      myGL.glTexImage2D(GL.GL_TEXTURE_2D, 0, 3, tWidth, tHeight,0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, texture);

I initialize the textures in this way in the init method, and later in the display method i used
myGL.glBindTexture(GL.GL_TEXTURE_2D, textures[i]);
each time before starting drawing an object. but only the last texture loaded is effectively working.
The trick about puting i instead of textures[i] still produce the same output…
I have checked the content of the 3 entries of the textures array and they are 1 2 and 3 either in display or in the init method, i am really wondering where is the problem

This is pretty basic stuff that should work even on the worst drivers. Post you code so someone else can take a look at the bigger picture.

[quote]No, don’t do that.

cyberyoyo: it’s a coincidence, that your array index matches your texture name!

You seem to have a problem in your texture-initialization, so that you don’t have the right texture names in your textures-array. Print out it contents and see, if there are different integers in the array…
[/quote]
Toi answer your question, I have examined the array and the numbers are the same(0).But I’m sure I didn’t make any problem in my initialisation code, I’ve followed the exampe program stickied at the top of this forum.

Why do you say it is an error to do that? do you mean there can be more textures than the size of the array? would that result in mismatched textures?

Anyway, so far it works absolutely perfectly in all my tests, different programs,different number of textures.
and the method with
glBindTexture(gl.gl_texture_2d,texture[i])
doesn’t work at all (always the last texture)

Incidentally the JOGL tutorials at NeHe’s site, all use the
method glBind*texture(gl_texture_2d,i)

Here is my complete code, if you see an error even stupid one tell me ??? :-[

import net.java.games.jogl.*;
import net.java.games.jogl.util.*;
import javax.swing.*;
import java.nio.*;
import java.net.*;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import javax.imageio.ImageIO;
import java.io.IOException;

public class JoGLtest extends JPanel implements GLEventListener
{
      private GLCanvas canvas;
      private Animator anim;
      private  double eyex;
      private  double eyey;
      private  double eyez;
      private  double lookx;
      private  double looky;
      private  double lookz;
      ByteBuffer texture;
    int textures[];
    int tWidth;
    int tHeight;
      private URL[] theurl;
    private BuildingList buildList;

   public JoGLtest(URL[] url)
      {
        super();
        GLCapabilities capabilities=new GLCapabilities();
        capabilities.setHardwareAccelerated(true);      //We want hardware acceleration
        capabilities.setDoubleBuffered(true);           //And double buffering

        canvas=GLDrawableFactory.getFactory().createGLCanvas(capabilities);

        canvas.addGLEventListener(this);
            theurl=new URL[3];
            textures=new int[3];
            theurl=url;
        this.add(canvas);
        this.setSize(800,600);
        canvas.setSize(800,600);//We want the JPanel and the GLCanvas to have the same size
        canvas.setVisible(true);//This is somehow necessary
            eyex=-5.0;
            eyey=4.0;
            eyez=6.0;
            /*eyex=-2.5;
            eyey=1.5;
            eyez=3.0;
            lookx=-3.75;
            looky=1.3;
            lookz=-4.75;*/
            lookx=-1.75;
            looky=0;
            lookz=-1.75;
    }

      
 public void init(GLDrawable glDrawable) 
      {
    GL myGL=glDrawable.getGL();//Get the GL object from glDrawable
      GLU myGLU=glDrawable.getGLU();
      myGL.glClearColor( 0, 0, 0, 0 ); // Couleur de suppression noire
    myGL.glClear(GL.GL_COLOR_BUFFER_BIT); // Supprime le buffer d'affichage boolean currentCube
    myGL.glShadeModel (GL.GL_SMOOTH);
      myGL.glGenTextures(3,textures);
  myGL.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
      loadTexture(0);
      myGL.glTexImage2D(GL.GL_TEXTURE_2D, 0, 3, tWidth, tHeight,0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, texture);
      myGL.glBindTexture(GL.GL_TEXTURE_2D, textures[1]);
      loadTexture(1);
      myGL.glTexImage2D(GL.GL_TEXTURE_2D, 0, 3, tWidth, tHeight,0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, texture);
            myGL.glBindTexture(GL.GL_TEXTURE_2D, textures[2]);
      loadTexture(2);
      myGL.glTexImage2D(GL.GL_TEXTURE_2D, 0, 3, tWidth, tHeight,0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, texture);
      anim = new Animator(glDrawable);
      anim.start();
      canvas.repaint();
    }

public void update()
{
canvas.repaint();
}
public void reshape(GLDrawable glDrawable, int i, int i1, int i2, int i3) 
            {
        GL myGL=glDrawable.getGL();
            GLU glu = glDrawable.getGLU();
            myGL.glViewport(0,0,i2,i3);
        myGL.glMatrixMode(GL.GL_PROJECTION);
        myGL.glLoadIdentity();
        glu.gluPerspective(45.0,(i2*1.0)/(i3*1.0),0.5,20.0);
              myGL.glMatrixMode(GL.GL_MODELVIEW);
             myGL.glLoadIdentity();
          }

 public void display(GLDrawable glDrawable) 
      {
        GL myGL=glDrawable.getGL();
            GLU glu = glDrawable.getGLU();
            GLUT glut = new GLUT();
            myGL.glClearColor( 0, 0, 0, 0 ); // Couleur de suppression noire
            myGL.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); // Supprime les buffers d'affichage et de profondeur 
            myGL.glShadeModel(GL.GL_SMOOTH); // rendu des surfaces lissées
              myGL.glEnable(GL.GL_DEPTH_TEST); // active le Z-buffer
             myGL.glEnable(GL.GL_NORMALIZE); // active la normalisation des normales declarees avec glNormal
            myGL.glEnable(GL.GL_CULL_FACE); // active la differentiation des exterieurs et interieurs des surfaces
      
          float[] lightDiffuse = {1f, 1f, 1f, 1.0f};   
          float[] lightAmbient = {1.0f, 1.0f, 1.0f, 0.1f};    
          float[] lightPosition= {2.0f, 10.0f, 2.0f, 1.0f};

          //Ambient light component
          myGL.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, lightAmbient);
          //Diffuse light component
          myGL.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, lightDiffuse);
          //Light position
          myGL.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lightPosition);
                  
             myGL.glEnable(GL.GL_LIGHT0);
            myGL.glEnable(GL.GL_LIGHTING);
            myGL.glEnable(GL.GL_TEXTURE_2D);
        myGL.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
        myGL.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR);

            myGL.glMatrixMode(GL.GL_MODELVIEW);
            myGL.glLoadIdentity();
            glu.gluLookAt(eyex,eyey,eyez,lookx,looky,lookz,0,1.0,0);
            
            myGL.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
          BuildingList.enceinte(myGL); //static method building walls and towers
                  
            myGL.glBindTexture(GL.GL_TEXTURE_2D, textures[1]);
            //making the soil
            myGL.glBegin(GL.GL_QUADS);
            myGL.glNormal3f(0,1f,0);
            myGL.glTexCoord2f(0,0);
            myGL.glVertex3f(-20f,0,20f);
                        myGL.glTexCoord2f(40f,0);
            myGL.glVertex3f(20f,0,20f);
                                    myGL.glTexCoord2f(40f,40f);
            myGL.glVertex3f(20f,0,-20f);
                                    myGL.glTexCoord2f(0,40f);
            myGL.glVertex3f(-20f,0,-20f);
            myGL.glEnd();
            
            myGL.glBindTexture(GL.GL_TEXTURE_2D, textures[2]);
            myGL.glTranslatef(-2f,0,-2f);
            //adding a medieval Oven
            BuildingList.addOven(myGL,glu);
            myGL.glDisable(GL.GL_TEXTURE_2D);
              myGL.glFlush();

}

            

public void displayChanged(GLDrawable glDrawable, boolean b, boolean b1){}



public void loadTexture(int i)

    {

      BufferedImage buff=null;

      try{buff=ImageIO.read(theurl[i]);}catch(IOException ioex){System.out.println("Oups probleme");}
// the url is an array containing urls for the image files

      Raster r = buff.getRaster();

            int[] img = null;

            img = r.getPixels(0, 0, buff.getWidth(), buff.getHeight(), img);

            texture = ByteBuffer.allocateDirect(buff.getWidth() * buff.getHeight() * 3);

            for (int y = 0; y < buff.getHeight(); y++)

                for (int x = 0; x < buff.getWidth(); x++) {

                    texture.put((byte) img[(y * buff.getWidth() + x) * 3]);

                    texture.put((byte) img[(y * buff.getWidth() + x) * 3 + 1]);

                    texture.put((byte) img[(y * buff.getWidth() + x) * 3 + 2]);

                }

            tWidth = buff.getWidth();

            tHeight = buff.getHeight();

    }

cyberyoyo:
I looked at two nehe-tutorials and both use the correct way with the array-content and not the array-index as parameter.

Anyway, to answer your question: glGenTextures generates texture-names for the given amount of textures you want to use. A texture name is an ID, that identifies the texture in the gl state machine. In your application you probably only use one call to this function, so your use of the array index does not seem to cause a problem.

In more complex applications (different texture-arrays, more than one call to glGenTextures) you will get arbitrary results as texture names. As you can see, this leeds to wrong texture selection in your rendering, if you use the texture-index. This is logical, since the gl state machine has no knowledge of your application organisation, so it can only use values provided by itself to identify a texture.

Malek:
Try a gl.glEnable(gl.GL_TEXTURE_2D); call at the beginning of your init()-Method…

i tried but still change nothing,

I have notice something strange, here is a screenshot of the “normal” code execution from the code above.
http://ece.fsa.ucl.ac.be/fremacle/screenshot.jpg

Now here is a screenshot of what happen if i add

myGL.glBindTexture(GL.GL_TEXTURE_2D, textures[1]);

After drawing everything just before the lines

            myGL.glDisable(GL.GL_TEXTURE_2D);
              myGL.glFlush();

http://ece.fsa.ucl.ac.be/fremacle/screenshot2.jpg

Suddenly a second texture appears,
if i bind the other one than the wall will be correct but not the floor anymore…

if you are willing to send me the source and the textures or a testcase showing the problem, I can take a look at it. send to cylab at gmx dot de.

could it be a problem with the drivers of the video card?
I have the standard nVidia drivers.

no. there must be something wrong in your glGenTextures-call or prior initialization. this is one of the most basic opengl feature and should work on all cards with all drivers.

I tried again with what you said was the good version and what do you know, now it works ??? ???
I have updated my graphic drivers to the latest just before I try , but I can’t say for sure that it is the change in driver that made it works bcause I forgot to test this version with the old drivers :stuck_out_tongue:

:-*

I found the problem ;D.

In fact it was rekated to these two lines

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

They have to be specified for each textures binding!

i thought they were global parameters but it turned out it is not :o

Great! I was just going to look at the problem right now :wink: