Basic Textures In JOGl

Well it should be 2562563 since it’s RGB, but I’m sure it’s fine.

I’ve made a complete texturing example so that you’ve got something to look at. The only problem is that it uses LWJGL instead of JOGL, but I’m sure it can be of some help:


import java.nio.*;
import org.lwjgl.opengl.*;

public class TextureTest {
	
	public static void main(String args[]) throws Exception {
		try {
			Display.setDisplayMode(new DisplayMode(640, 480));
			Display.create();
			GL11.glClearColor(0.0f, 0.0f, 1.0f, 0.0f);

			// generate a pretty texture in RGBA format
			int width = 256;
			int height = 256;
			ByteBuffer textureData = ByteBuffer.allocateDirect(4 * width * height);
			for (int y=0; y<height; y++) {
				for (int x=0; x<width; x++) {
					textureData.put((byte)(x|y)).put((byte)(x&y)).put((byte)(x^y)).put((byte)0xff);
				}
			}
			textureData.rewind();
			
			// transfer texture to the card
			int textureId = 1;
			GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
			GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, textureData);
			
			// IMPORTANT: gets white quad without this, and I don't know why. Mipmapping issue pherhaps.
			GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); 
			
			while (!Display.isCloseRequested()) {
				GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
				
				// we want it to be white
				GL11.glColor4f(1, 1, 1, 1);

				// enable texturing and bind our pretty image
				GL11.glEnable(GL11.GL_TEXTURE_2D);
				GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
									
				// draw a 256x256 quad
				int size = 256;
				GL11.glBegin(GL11.GL_QUADS); 
				GL11.glTexCoord2f(0, 0); 
				GL11.glVertex2i(200, 200); 
				GL11.glTexCoord2f(0, 1); 
				GL11.glVertex2i(200, 200+size); 
				GL11.glTexCoord2f(1, 1); 
				GL11.glVertex2i(200+size, 200+size); 
				GL11.glTexCoord2f(1, 0); 
				GL11.glVertex2i(200+size, 200); 
				GL11.glEnd();		
				
				Display.update();
				Thread.yield();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			Display.destroy();      
		}
	}
}

The only thing that stands out is this line:


GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); 

Good luck!

Whoa! Finally got it to work. It turns out, some of the files we had were corrupted or something like that. Once we got rid of them it started to roll. Still, it was very educational and we’d like to thank all of you guys. You’ve been a real rock.

i’m also trying to get a texture set up, but it just straight up doesn’t work. i’m using the TextureIO class specified here and have done everything that sephiroth got to work, but I don’t seem to have any luck at all. here is the code that’s supposed to be drawing the texture, but I just get a box displayed gray (the previous color that glColor3f was called to)



tex.bind(gl);
		
		gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE); 
		
		gl.glBegin(GL.GL_QUADS);

			gl.glTexCoord2d(0.0, 0.0); gl.glVertex2d(x-quadWidth/2,y-quadHeight/2);
			gl.glTexCoord2d(1.0, 0.0); gl.glVertex2d(x+quadWidth/2,y-quadHeight/2);
			gl.glTexCoord2d(1.0, 1.0); gl.glVertex2d(x+quadWidth/2,y+quadHeight/2);
			gl.glTexCoord2d(0.0, 1.0); gl.glVertex2d(x-quadWidth/2,y+quadHeight/2);
			
		gl.glEnd();


the ‘tex’ variable is my Texture, and quadWidth/quadHeight are just doubles that specify the location. The quad is drawn in the correct place on the screen, so i know these are working. i just get no texture. what’s up?!

Hi,

Did you call glEnable with GL_TEXTURE_2D ?

No, I hadn’t done that, since I thought it was done explicitly by the Texture class. I was wrong about that.

Now, however, still just get a black quad drawn on the screen, so it’s no longer gray and also not my texture. My texture image doesn’t have any black in it at all.

Does the fact that I’m creating the image myself using a BufferedImage so i can draw text on the screen have anything to do with it? Here’s my BufferedImage creation code:


// draw the string to a BufferedImage
		data = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
		Graphics2D g2d = (Graphics2D) data.getGraphics();
		g2d.setColor(Color.white);
		//g2d.setComposite(AlphaComposite.Clear);
		g2d.fillRect(0,0,width,height);
		
		g2d.setFont(font);
		g2d.setColor(Color.red);
		//g2d.setComposite(AlphaComposite.SrcOver);
		g2d.drawString(text,0,str_baseline);
		
		tex = TextureIO.createTexture(data);

The alpha stuff is commented out so that I could just get a texture working before messing with all that, but I’d like to eventually put that in also if you have any comments on how to make that work.

The texture will be multiplied by the current color. Try setting it to white by calling “glColor4f(1,1,1,1)” before rendering the quad.

Did that and all i get is still a black square. I am reading the red book chapter on texture mapping now, but i’m pretty sure i understand it I just don’t know what’s going on in this situation. especially given that I’m using the Texture class to do all the texture loading. I’m sure i’m doing something wrong with my bufferedImage, but idk.

Ok, I’ve done a lot of reading on textures, played around with it more, and I still have no idea what’s wrong. Here’s all of my code involved with the textures. Somebody please help!



import mvt.util.Texture;
import mvt.util.TextureIO;

import java.awt.*;
import java.awt.geom.*;

import java.awt.image.*;
import java.io.*;
import java.nio.*;
import javax.imageio.*;

import javax.media.opengl.*;
import javax.media.opengl.glu.*;
import com.sun.opengl.utils.*;

public class TextObject extends GraphicsComponent {

    private String text;
    private Point2D.Double pt;
    private Plot2DPanel parent = null;
    private Color color;
	private Font font;
	private BufferedImage data;
	private int texture;
	private boolean textureMade;
	private Texture tex;

    /**
     * Creates a new <code>TextObject</code> instance.
     *
     * @param pt a <code>Point2D.Double</code> object representing
     * the location of the text. 
     * @param text a <code>String</code> object which is to be 
     * printed on the screen.
     * @param plotPanel a <code>Plot2DPanel</code> where this 
     * object will be showed on
     * @param color the <code>Color</code> of the cross
     */
    
    public TextObject(Point2D.Double pt, String text,
		      Plot2DPanel plotPanel, Color color, Font font){
			  
		super();
		this.text=text;
		this.pt = pt;
		this.parent = plotPanel;
		this.color = color;
		this.font = font;
		
		textureMade = false;
		
		BufferedImage temp = new BufferedImage(1,1, BufferedImage.TYPE_3BYTE_BGR);
		Graphics g = temp.getGraphics();
		g.setFont(font);
		int str_width = g.getFontMetrics().stringWidth(text)+2;
		int str_height = g.getFontMetrics().getHeight()+2;
		int str_baseline = g.getFontMetrics().getHeight()-g.getFontMetrics().getMaxDescent();
		
		// create an image with dimensions that are powers of two
		// which is large enough to hold the desired text
		int width, height;
		for (width = 2; width<str_width; width *= 2)
			;
		for (height = 2; height<str_height; height *= 2)
			;
		
		// draw the string to a BufferedImage
		data = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
		Graphics g2d = data.createGraphics();
		g2d.setColor(Color.white);
		//g2d.setComposite(AlphaComposite.Clear);
		g2d.fillRect(0,0,width,height);
		
		g2d.setFont(font);
		g2d.setColor(Color.red);
		//g2d.setComposite(AlphaComposite.SrcOver);
		g2d.drawString(text,0,str_baseline);
		
		tex = TextureIO.createTexture(data);

    }

	public void glDraw(GL gl) {
		System.out.println("TextObject");
		
		// create the texture on the first time through only
		if (!textureMade) {
			System.out.println("Create Texture");
			tex.initialize(false, true, GL.GL_LINEAR, GL.GL_LINEAR, gl, new GLU());
			textureMade = true;
		}
		
		double xmin = parent.getXMin();
		double xmax = parent.getXMax();
		double ymin = parent.getYMin();
		double ymax = parent.getYMax();
		
		double x = pt.getX();
		double y = pt.getY();
		
		// figure out how big the image is in our current GL coordinate system
		double quadWidth = (double)(data.getWidth()*(xmax-xmin)/parent.getWidth());
		double quadHeight = (double)(data.getHeight()*(ymax-ymin)/parent.getHeight());

		gl.glEnable(GL.GL_TEXTURE_2D);
		tex.bind(gl);
		gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_DECAL); 
		
		gl.glBegin(GL.GL_QUADS);
		
			gl.glColor4f(1.0f,1f,1.0f,1.0f);
			gl.glTexCoord2d(0.0, 0.0); gl.glVertex2d(x-quadWidth/2,y-quadHeight/2);
			gl.glTexCoord2d(1.0, 0.0); gl.glVertex2d(x+quadWidth/2,y-quadHeight/2);
			gl.glTexCoord2d(1.0, 1.0); gl.glVertex2d(x+quadWidth/2,y+quadHeight/2);
			gl.glTexCoord2d(0.0, 1.0); gl.glVertex2d(x-quadWidth/2,y+quadHeight/2);
			
		gl.glEnd();
		
		gl.glDisable(GL.GL_TEXTURE_2D);
	}
	
	public void setLocation(Point2D.Double newPt) {
	
		pt = newPt;
		
	}

}

The Texture and TextureIO classes included in the first few lines are the same texture and textureio classes linked to earlier in this thread. GLDraw() is called by the display() method of something that implements GL event listener, and it passes in the GL context of it. The black square is drawn correctly on that screen in the right place… the only issue is i want a texture with a string written on it, not a black square!

The TextObject constructor must also be called from the OpenGL thread because TextureIO.createTexture uses GL functions.

I do have it being called from one of the GL context functions, but actually I don’t think that matters since createTexture() doesn’t use any gl functions, just a few constants. I thought maybe the textures weren’t getting binded correctly, but that is in fact all working, so I just don’t know.

I read through this thread again and saw that some people had problems with corrupted files and the like, so what I tried doing was loading in another image that we use in our program which I know works for sure, just so that I could ensure that the problem was in fact with the image I was creating rather than with the code. However, its still broken. I still get the black square. I know for sure the image I’ve loaded is not corrupt, since it appears elsewhere in my program (in a part that isn’t affected by anything JOGL-related). Somehow something else is going wrong here. Here is the code that creates/calls the GLdraw functions:


public void init(GLAutoDrawable gld) {

		gld.setGL(new DebugGL(gld.getGL()));
		gld.getGL().glClearColor(1.0f,1.0f,1.0f,0.5f);
	
	} // init()
	
	public void display(GLAutoDrawable gld) {
	
		GL gl = gld.getGL();
		
		setCamera(gl);
		
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
		gl.glEnable(GL.GL_POLYGON_SMOOTH);
		
		glDraw(gl);
		
		TextObject text = new TextObject(new Point2D.Double(1,1),"Hello",(Plot2DPanel)this,Color.black, new Font("Helvetica",Font.BOLD,12));
		text.glDraw(gl);
	
	} // display()

I know that glDraw works, since it successfully draws other graphics components on the screen where they should be. there’s just something wrong with the texture. Just for quick reference, here’s the code that loads and initializes the texture:


// from Texture.java
 public void initialize(boolean createMipMaps, boolean wrap, int minFilter, int magFilter, GL gl, GLU glu)
    {
        int[] textureID = new int[1];

        gl.glGenTextures(1, textureID, 0);
        id = 1;//textureID[0];

        gl.glBindTexture(GL.GL_TEXTURE_2D, id);

        int wrapMode = wrap ? GL.GL_REPEAT : GL.GL_CLAMP;
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapMode);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapMode);

        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter);

        if (createMipMaps)
        {
            glu.gluBuild2DMipmaps(
                GL.GL_TEXTURE_2D,
                componentCount,
                width,
                height,
                glFormat,
                GL.GL_UNSIGNED_BYTE,
                buffer
            );
        }
        else
        {
            gl.glTexImage2D(
                GL.GL_TEXTURE_2D,
                0,
                componentCount,
                width,
                height,
                0,
                glFormat,
                GL.GL_UNSIGNED_BYTE,
                buffer
            );
        }
    }

    public void bind(GL gl)
    {
        gl.glBindTexture(GL.GL_TEXTURE_2D, id);
    }

and the IO…


// from TextureIO.java
  public static Texture createTexture(BufferedImage image)
    {
        BufferedImage textureImage;
        WritableRaster raster;
        ColorModel colorModel;

        int imageWidth = image.getWidth();
        int imageHeight = image.getHeight();
        int textureWidth = getPowerOfTwo(imageWidth);
        int textureHeight = getPowerOfTwo(imageHeight);
        int textureFormat;

        if (image.getColorModel().hasAlpha())
        {
            textureFormat = GL.GL_RGBA;
            colorModel = glAlphaColorModel;
            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, textureWidth, textureHeight, 4, null);
        }
        else
        {
            textureFormat = GL.GL_RGB;
            colorModel = glColorModel;
            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, textureWidth, textureHeight, 3, null);
        }

        textureImage = new BufferedImage(colorModel, raster, false, new Hashtable());
        copyImage(image, textureImage);
        byte[] data = ((DataBufferByte) textureImage.getRaster().getDataBuffer()).getData();

        ByteBuffer textureDataBuffer = ByteBuffer.allocateDirect(data.length);
        textureDataBuffer.order(ByteOrder.nativeOrder());
        textureDataBuffer.put(data, 0, data.length);

        return new Texture(textureDataBuffer, textureWidth, textureHeight, textureFormat);
    }

Now all the code I’ve got that has anything to do with the creation of the text object has been pasted within my last few posts. I don’t see how its out of line with anything else that’s been done in these threads or in any of the tutorials.

Any thoughts? or should i just give up completely

Another shot in the dark then :slight_smile:

If your using the latest verision of JOGL you need to rewind the buffers. In this case textureDataBuffer need to be rewound in createTexture, before the Texture object is created. This has changed lately and it is possible the TextureLoader was writtin against an older version of JOGL.

Good luck.

i would do that… how? :wink:

After the line “textureDataBuffer.put(data, 0, data.length);” in createTexture you add “textureDataBuffer.rewind()”.

You can also add buffer.rewind() at the beginning of Texture.initalize(…) in case the buffer position is changed somwhere else in the code.

Read the javadoc for java.nio.Buffer for more information about buffers. Remember that JOGL uses position and limit of the buffers and they need to be set correctly to mark what data to use.

sweet! that got the texture to load. however, its upside down and backwards, and the background is black. I was able to fix the position alignment by moving my texture coords around, but why is the background black? I’m not calling glColor3f(black) anywhere. The parts that are black should be transparent (and are in fact transparent in the place the image appears elsewhere in my program) but aren’t for some reason in this. are there options i need to set to activate transparency?

also, i was pretty sure i had the position alignment set up right, so i think that it was upside down and backwards might have been something else that went wrong with loading the texture in.

You definitively need to enable blending…

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

got it! :slight_smile: thanks a LOT to everybody who helped me! I really appreciate it, even though I was annoying at times i’m sure :slight_smile: