Basic Textures In JOGl

I’m trying to put some textures in my 3D-world and the problem i encounter is that all the info i find seems to be rather advanced. Now, i understand that’s the most convienient way when doing some serious work. However, at this point, i’d like to simply get my “grass.gif” and put it visible somewhere in my world. From there, i can start laborating.

So - anybody willing to point me to a the source code for the most simple operation that loads an image from a file (i’m guessing it will be an instance of BufferedImage) and actually put that thing into an existing and working “display-method”?

Have you looked at the JOGL demos? Most of them load textures in some format or another and create an OpenGL texture from the result.

Yes, of course. That was the very first thing. The thing is that i got more confused by it. There’s too much to digest in there. I’m looking for a minimal example of how to get from a graphical file to a “something” on the screen. From there i can work by myself.

As it is now, i understand i need three steps.

  1. Read from a file to a BufferedImage.
  2. Convert BufferedImage-object as an array of byte.
  3. Represent the contents of the array on the screen.
    Is the above correct?

Look at makeRGBTexture() in the VertexProgRefract demo. This shows how to load the BufferedImage into an OpenGL texture object. Once you have your OpenGL texture you just need to draw a pair of triangles with the appropriate texture coordinates in order to get it on the screen.

There’s also an entire thread on this forum somewhere covering a TextureManager for loading and managing textures. It was being extended some time ago to include avi and quicktime stuff as well but it’s been a quiet thread for some time.

Hi

Jogl is a binding for OpenGL, NeHe has a large range of good OpenGL tutorials, articles and examples.

HTH

Endolf

To get you going with super-simple texture loading, you could try out this:

http://www.g0dmode.com/javastuff/jogl-textureio.zip

Use the TextureIO class to load textures from files. Then call initialize and bind methods for the created texture to use it.

Thanks for the replies. I’m still not there yet but on the way. Just a little bit more of the whining and i’ll be happy. So, let’s whine.

Whine #1
I was checking The Blue Book to find glBindTexture and guess what - no such thing as far as i can see. What’s up with that?

Whine#2
I have my byte[] but i still get nada on the screen. My nada is created by this code.

byte[] data = ((DataBufferByte) img.getRaster ().getDataBuffer ()).getData ();
this.gl.glTexImage2D (target, 0, GL.GL_RGB, img.getWidth (), img.getHeight (), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, data);

this.gl.glBegin (GL.GL_TRIANGLE_STRIP);
this.loadPNGFile (“grass.png”);
this.gl.glEnable (GL.GL_TEXTURE_2D);
this.gl.glBindTexture (GL.GL_TEXTURE_2D, 0);
this.gl.glTexCoord3d (0, 0, 0);
this.gl.glTexCoord3d (30, 0, 0);
this.gl.glTexCoord3d (0, 30, 0);
this.gl.glTexCoord3d (30, 30, 0);
this.gl.glEnd ();

I have tried the above with and without drawing triangle using glVertex3d and enabling/disabling GL_TEXTURE_2D. I also tried to scream a little bit until the neibs started yelling. :slight_smile:

Whine #3
What did you mean by “a pair of triangles with the appropriate texture coordinates”? I assumed i had to draw the triangles and then SOMEHOW put the texture on them. Now, that SOMEHOW is a little bit unclear to me. I looked into examples you mentioned and it helped this far but no further, i’m affraid.

Whine #4
How do i go from having a byte[] (size 256^2) to a graphical representation on the screen (i tried the glBindTexture(…) but it’s still something wrong there). Please reply as if you were talking to a retarded banana. Rest assured you won’t hit very far from the truth in that aim. :slight_smile:

Looks like the Blue Book that is online on opengl.org is so old that it don’t contain glBindTexture. Might have been a 1.1 feature. Anyway, here is a link to slightly more complete doc:
OpenGL Man Pages

That code don’t make much sense. Please read the Red Book. Any help we try to give will be useless unless you know the basics. In your case the Texture Mapping chapter would be the most important one. Although the online version is missing some important parts.

  1. “this.loadPNGFile (“grass.png”);” should be done once at startup, not in the rendering loop.
  2. Nothing is drawn unless you call glVertex. It is at this call the data is copied.
  3. Use 1 as texture coordinates instead of 30. Texture coordinates is normailized and 1 means the full width or height.

Textures has its own coordinate system that you have to use to tell what part of the texture you will use. This is explained in the Red Book, I’m sure.

First the texture uploaded to the card. Since you no longer have the data, you use a id/name instead. This is what glBindTexture does. It sets what texture id to use.

To use textures in opengl you do:

At startup:

  1. bind a id with glBindTexture. This can be hardcoded or you can get a unused id with glGenTextures.
  2. Upload the texture data to the card using glTexImage2D. The texture is now on the card and is bound the the id you used in 1)

When rendering:

  1. Bind the id of the texture you want to use.
  2. specify the triangles with texture coordinates

I second Endolf’s advice regarding the nehe stuff. I suggest you check out the demos on drawing a polygon, drawing 3D shapes and texture mapping in particular.

Hi there,

I’m using the Texture and TextureIO classes pointed by nnevatie as in

[quote]To get you going with super-simple texture loading, you could try out this:

http://www.g0dmode.com/javastuff/jogl-textureio.zip

Use the TextureIO class to load textures from files. Then call initialize and bind methods for the created texture to use it.
[/quote]
So, i load the png image into a Texture object. I then put the texture object into a HashMap (to be able to give a string name to the texture when searching for it), and i then use this hashmap when i’m doing the binding before drawing a quad that will contain the texture. However, when the application runs, i only get a black square, no texture rendered.
The code is:


public void display(GLDrawable drawable)
    {
        GL gl = drawable.getGL();

        gl.glClear(GL.GL_COLOR_BUFFER_BIT);
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();

        //We draw the alien
        ((Texture)this.texturesTable.get("ship")).bind(gl);
        gl.glBegin(GL.GL_QUADS);
        {
        	gl.glTexCoord2f(0.0f,1.0f);
        	gl.glVertex3i(500,700,0);
        	gl.glTexCoord2f(1.0f,1.0f);
        	gl.glVertex3i(700,700,0);            
        	gl.glTexCoord2f(1.0f,0.0f);
        	gl.glVertex3i(700,500,0);
        	gl.glTexCoord2f(0.0f,0.0f);
            gl.glVertex3i(500,500,0);
        }gl.glEnd();        
    }

The init code is


   public void init(GLDrawable drawable)
    {
    	GL gl = drawable.getGL();
    	GLU glu = drawable.getGLU();
    	
    	//GL init
    	{	    	    	
    		gl.glClearColor(1.0f,1.0f,1.0f,1.0f);
	        
    		gl.glColor3f(0f,0f,0f);
	        gl.glPointSize(4.0f);
	        
	        gl.glEnable(gl.GL_TEXTURE_2D);	        
    	}
        
        //Texture loading
        {
        	try
        	{
        		Texture ship = TextureIO.createTexture("ship.png");
        		ship.initialize(gl,glu);
        		this.texturesTable.put("ship",ship);
        		Texture alien = TextureIO.createTexture("alien.gif");
        		alien.initialize(gl,glu);
        		this.texturesTable.put("alien",alien);
        	}
        	catch(IOException e){System.out.println("Error while loading textures: "+e.getMessage());}
        }
        
    }    

¿What may the problem be? ¿Why shouldn’t it render correctly the ship image?

Well, i have been doing some tests this morning, and if i add color to all vertices of the quad, the image (of the ship) gets displayed within the quad…


        ((Texture)this.tablaTexturas.get("ship")).bind(gl);
        gl.glBegin(GL.GL_QUADS);
        {
        	gl.glColor3f(1.0f,1.0f,1.0f); gl.glTexCoord2f(0.0f,1.0f); gl.glVertex2i(500,550);
        	gl.glColor3f(1.0f,1.0f,1.0f); gl.glTexCoord2f(1.0f,1.0f); gl.glVertex2i(550,550);            
        	gl.glColor3f(1.0f,1.0f,1.0f); gl.glTexCoord2f(1.0f,0.0f); gl.glVertex2i(550,500);
        	gl.glColor3f(1.0f,1.0f,1.0f); gl.glTexCoord2f(0.0f,0.0f); gl.glVertex2i(500,500);
        }gl.glEnd();

The color here acts as some kind of light source, that doesn’t show up the texture if not activated. I haven’t read anywhere, that i should add color to the vertices of the polygon i’m rendering the texture in, in order to render the texture itself, so…¿does someone know why this is happening?

I think that the call gl.glColor3f(0f,0f,0f) causes them to appear black - this happens because of the texture-color modulation.

Simplest solution is to set the color to white (1, 1, 1).
You may also disable the texture modulation with the following code:


gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE); 

Thanks a lot for the answer, nnevatie, it worked perfectly. The texture-color modulation disabling, i mean.

The images are in png format. ¿Do you know where i should look to get the transparent parts of the texture not rendered in black?

I’m trying the blending approach with, in my init code:


gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_SRC_ALPHA,GL.GL_ONE);

yet when i enable the BlendFunc, the texture does not get rendered. In fact, the whole quad doesn’t get rendered.

I’ve tried to put a color4f function before the rendering of the quad, with the alpha componente set to 1.0f, 0.0f, 0.5f, and it doesn’t seems to have any effect. My real problem here is that i don’t understand what the parameters to the BlendFunc do.

Ok, now i have my textures well rendered, including their alpha transparency.

All i had to do is to set the Blend Function factors to (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) (with a call to glBlendFunc). Why this does work, i have no idea. I’ve read the blending basic tutorial, yet i fail to grasp why GL_SRC_ALPHA works and GL_ONE does not.

Thank you very much for the info. We’ve read the manual part once again and that, combined with the tips you gave us, lead to a better understanding. However, our texture doesn’t seem to know that and keeps refusing to show up. So, here’s a follow up to your kind reply.

In init we do something like this.


this.gl.glEnable (GL.GL_TEXTURE_2D);
BufferedImage img = ImageIO.read (new File ("grass.gif"));
byte[] data = ((DataBufferByte) img.getRaster ().getDataBuffer ()).getData ();
this.gl.glBindTexture (GL.GL_TEXTURE_2D, 0);
this.gl.glTexImage2D (target, 0, GL.GL_RGB, img.getWidth (), img.getHeight (), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, data);
this.gl.glTexEnvf (GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_DECAL);

We’ve checked that the byte[] contains something and, in fact, the right number of something’s, namely 2562 elements. So, give or take that the file itself is screwed up, we still got a set of 65536 elements between 0 and 255. It should be suitable for texturing. Please point out any mistakes we’ve done here.

In display we do something like this.


this.gl.glBegin (GL.GL_QUADS);
this.gl.glColor3d (1.0, 0.9, 0.1);
this.gl.glBindTexture (GL.GL_TEXTURE_2D, 0);

this.gl.glTexCoord2d (0, 0); this.gl.glVertex3d (0, 0, 0);
this.gl.glTexCoord2d (1, 0); this.gl.glVertex3d (30, 0, 0);
this.gl.glTexCoord2d (1, 1); this.gl.glVertex3d (30, 30, 0);
this.gl.glTexCoord2d (0, 1); this.gl.glVertex3d (0, 30, 0);

this.gl.glEnd ();

We use glBindTexture (GL.GL_TEXTURE_2D, 0) twice. Once in init, to get the byte[] to the graphic card and assign it an ID (namely zero), and then a second time in display to make it the current texture.

The result is still a yellow square with hardly any grass on it (unless we’re regarding some really hot and dry country where all grass actually is yellow). What did we done stupidishly this time?

Hi there,

You must call gl.glGenTextures to have a valid texture id since (quote from glBindTexture ) :
"Texture names are unsigned integers. The value 0 is reserved to represent the default texture for each texture target. "

What you want to do is to bind a new texture, not the default one…

OK, i did the following.


private int[] tex = new int[10];
...
byte[] data = ((DataBufferByte) img.getRaster ().getDataBuffer ()).getData ();
this.gl.glGenTextures (1, this.tex);
this.gl.glBindTexture (GL.GL_TEXTURE_2D, this.tex[0]);

Still not working, though. I only have one texture and i refer to it’s ID as this.tex[0] in both init and display. More hints, please.

I’m assuming two things here.

  • I only have to call glGenTex (int, int[]) once, right before glBindTexture (…).

  • The use of an int[] (which is supposed to be an object) leads in Java to be regarded as a call by reference. Id est, i actually get some changes done in the array i send in.

Using 1 as id is fine.

You must have glBindTexture outside glBegin()/glEnd(). You can not change state inside begin/end, you can only call geomtry functions like glColor, glVertex etc.

The color should be:

this.gl.glColor4d (1, 1, 1, 1);

That way you get exactly the colors of the original texture.

We made those changes you recommended but the only visible difference is that we got a white, instead of a yellow square. Still no texture in the vicinity. Is texture mapping somehow platform dependent? We use WinXP and we assumed that if JOGl existed for our machine, it would include ALL the fun stuff (including the most fun stuff of all - texturing). ;D

Since we’re rather noobs when it comes to OpenGL, we have kind of limited resources to error-search the program. We’ve made sure that the byte[] isn’t empty (it has a wide range of values - all from 250 down to 5), has right number of elements. We’ve made sure that the returned ID is something good (it was 1, doh). As of now, we’re sitting and praying for somebody to pull us out of the misery or shoot us so we don’t need to suffer. :’(

Any hints are greatly appreciated.