Can't figure out textures

Started by bbjam, October 04, 2008, 04:08:05

Previous topic - Next topic

bbjam

I'm sorry to bother you people with this dumb question, but I have been unable to get a handle on texturing in openGL/lwjgl, dispite trying some "Texturing in OpenGL" tuts.

What I really want is a well commented code snippit that renders a quad with a procedurally generated checker board texture.
However any help you can give would be nice. Anyone who helps will be thanked on glass-flame.blogspot.com.

tomb

import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

public class TextureTest {
	public static void main(String[] args) throws Exception {
		int windowWidth = 640;
		int windowHeight = 480;
		Display.setLocation((Display.getDisplayMode().getWidth() - windowWidth) / 2,
							(Display.getDisplayMode().getHeight() - windowHeight) / 2);
		Display.setDisplayMode(new DisplayMode(windowWidth, windowHeight));
		Display.create();

		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GL11.glFrustum(-1, 1, -1, 1, 1, 1000);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		GL11.glTranslatef(0, 0, -4);
		
		ByteBuffer pixels = BufferUtils.createByteBuffer(256*256*3);
		for (int i=0; i<256*256*3; i+=3) {
			pixels.put((byte) (Math.random() * 255));
			pixels.put((byte) (Math.random() * 255));
			pixels.put((byte) (Math.random() * 255));
		}
		pixels.rewind();
		
		IntBuffer textureId = BufferUtils.createIntBuffer(1);
		GL11.glGenTextures(textureId);
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId.get(0));
		GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);		
		GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, 256, 256, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, pixels);
		
		// must use this or get white triangle
		GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); 
		
		while (!Display.isCloseRequested()) {
			GL11.glEnable(GL11.GL_TEXTURE_2D);
			GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId.get(0));
			
			GL11.glBegin(GL11.GL_TRIANGLES);
			GL11.glTexCoord2f(0, 0);
			GL11.glVertex3f(0, 0, 0);
			GL11.glTexCoord2f(1, 0);
			GL11.glVertex3f(1, 0, 0);
			GL11.glTexCoord2f(1, 1);
			GL11.glVertex3f(1, 1, 0);
			GL11.glEnd();
			Display.update();
		}
		
		Display.destroy();
	}
}

bbjam

Thank you very much!  :) :D ;D

Your code runs fine on my computer, and I copied its structure into my game engine, but I still cant figure out what is wrong. ???

Perhaps you could do me another favor, here is some code which should draw a textured square, but absolotly nothing happens. Could you please take a look and give me some advise? thanks.
public void drawImage(double x, double y, GFImage sprite,
			double scale, double rotation) throws IllegalArgumentException {
		loadImage(sprite);
		GL11.glEnable(GL11.GL_TEXTURE_2D);
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, loadedTex.get(new Long(sprite.getID())));
		GL11.glColor4d(1.0, 1.0, 1.0,1.0);
		GL11.glBegin( GL11.GL_QUADS );
		GL11.glTexCoord2d(0.0,0.0); GL11.glVertex2d(x + 0.0, y + 0.0);
		GL11.glTexCoord2d(1.0,0.0); GL11.glVertex2d(x + sprite.getWidth(), y + 0.0);
		GL11.glTexCoord2d(1.0,1.0); GL11.glVertex2d(x + sprite.getWidth(), y + sprite.getHeight());
		GL11.glTexCoord2d(0.0,1.0); GL11.glVertex2d(x + 0.0, y + sprite.getHeight());
		GL11.glEnd();
		GL11.glDisable(GL11.GL_TEXTURE_2D);

		System.out.println("rendering image: " + x + ", " + y);
	}


here is the loadImage method:
private void loadImage(GFImage i)
	{
		//if the texture is not alredy loaded
		if(!loadedTex.containsKey(new Long(i.getID())))
		{
			IntBuffer texID = BufferUtils.createIntBuffer(1);
			GL11.glGenTextures(texID);
			GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID.get(0));
			GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);

			GL11.glTexEnvf( GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);

			GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 
					0, 
					GL11.GL_RGBA, 
					i.getWidth(), 
					i.getHeight(), 
					0, 
					GL11.GL_RGBA, 
					GL11.GL_UNSIGNED_BYTE, 
					i.getData());
			loadedTex.put(new Long(i.getID()), new Integer(texID.get(0)));
			System.out.println("loaded texture: " + texID.get(0));
			
			GL11.glTexParameterf( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR );
			GL11.glTexParameterf( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR );

			// the texture wraps over at the edges (repeat)
			GL11.glTexParameterf( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP );
			GL11.glTexParameterf( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP );
		}
	}

tomb

Can't see any bugs.

So when you say nothing happens, does this mean that nothing is rendered? Not even a white or black quad? If that is the case you could try turning off cullling and making sure the quad is inside the frustum.

You could also try using REPLACE  as the TEX_ENV_MODE, incase the texture is 100% transparent.

bbjam

Thanks again for your help!  ;D

The problem with my program seems to be unconnected to texturing, because any rendering code I put in drawImage() dose not produse any resaults, even if I copy the code from drawLine, which works.
I have disabled GL_CULL_FACE, is there any other kinds of culling I should disable?
I know that drawImage is getting exceuted, because I put a println in it.

Any ideas how to trouble-shoot this kind of problem?

Thanks.

broumbroum

Quote from: bbjam on October 06, 2008, 23:42:59
Thanks again for your help!  ;D

The problem with my program seems to be unconnected to texturing, because any rendering code I put in drawImage() dose not produse any resaults, even if I copy the code from drawLine, which works.
I have disabled GL_CULL_FACE, is there any other kinds of culling I should disable?
I know that drawImage is getting exceuted, because I put a println in it.

Any ideas how to trouble-shoot this kind of problem?

Thanks.
Have you ever tried by replacing all of the GL_Texture_2d's with GL_TEXTURE_RECTANGLE_EXT ? this works for me, because I can't get my texture on screen with the GL_TEXTURE_2D.
see http://www.gamedev.net/reference/programming/features/2dogl/

bbjam

Thanks for all the help. :)

However my problem seems to be deeper than I thought: NO openGL drawing code inside the method drawImage has any effect! I put code to draw a untextured square in some other methods and there it worked, but inside drawImage it dose nothing! Examining the call stack when drawImage is called, using the debugger, revealed nothing that could cause openGL to be in a invalid state. Strangely, a call to GL11.glColor4d() inside drawImage worked perfectly, changing the color of the line and point drawing, which work fine.

:-\

broumbroum

From the link I quoted above, it can be checked that your graphics card supports rectangle textures. If it is not the case (you may check by the LWJGL javadoc), try it with a GC supporting rectangle textures. As far as I tested this, it should work fine with all ATI and NVidia, as far as they feature a 2D/3D acceleration support. Here's what to change in both of the methods, and whenever you specify the GL_TEXTURE_2D target :
public void drawImage(double x, double y, GFImage sprite,
			double scale, double rotation) throws IllegalArgumentException {
		loadImage(sprite);
		GL11.glEnable(EXTTextureRectangle.GL_TEXTURE_RECTANGLE_EXT);
		GL11.glBindTexture(EXTTextureRectangle.GL_TEXTURE_RECTANGLE_EXT, loadedTex.get(new Long(sprite.getID())));
		GL11.glColor4d(1.0, 1.0, 1.0,1.0);
		GL11.glBegin( GL11.GL_QUADS );
/** as mentioned by the short tutorial on rectangle textures, coords have to be casted to the plain texture sizes*/
		GL11.glTexCoord2d(0.0,0.0); GL11.glVertex2d(x + 0.0, y + 0.0);
		GL11.glTexCoord2d(sprite.getWidth(),0.0); GL11.glVertex2d(x + sprite.getWidth(), y + 0.0);
		GL11.glTexCoord2d(sprite.getWidth(),sprite.getHeight()); GL11.glVertex2d(x + sprite.getWidth(), y + sprite.getHeight());
		GL11.glTexCoord2d(0.0,sprite.getHeight()); GL11.glVertex2d(x + 0.0, y + sprite.getHeight());
		GL11.glEnd();
		GL11.glDisable(EXTTextureRectangle.GL_TEXTURE_RECTANGLE_EXT);

		System.out.println("rendering gl_texture_rectangle_ext image: " + x + ", " + y);
	}


here is the loadImage method:
private void loadImage(GFImage i)
	{
		//if the texture is not alredy loaded
		if(!loadedTex.containsKey(new Long(i.getID())))
		{
			IntBuffer texID = BufferUtils.createIntBuffer(1);
			GL11.glGenTextures(texID);
			GL11.glBindTexture(EXTTextureRectangle.GL_TEXTURE_RECTANGLE_EXT, texID.get(0));
			GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);

			GL11.glTexEnvf( GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);

			GL11.glTexImage2D(EXTTextureRectangle.GL_TEXTURE_RECTANGLE_EXT, 
					0, 
					GL11.GL_RGBA, 
					i.getWidth(), 
					i.getHeight(), 
					0, 
					GL11.GL_RGBA, 
					GL11.GL_UNSIGNED_BYTE, 
					i.getData());
			loadedTex.put(new Long(i.getID()), new Integer(texID.get(0)));
			System.out.println("loaded texture: " + texID.get(0));
			
			GL11.glTexParameterf( EXTTextureRectangle.GL_TEXTURE_RECTANGLE_EXT, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR );
			GL11.glTexParameterf( EXTTextureRectangle.GL_TEXTURE_RECTANGLE_EXT, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR );

			// the texture wraps over at the edges (repeat)
			GL11.glTexParameterf( EXTTextureRectangle.GL_TEXTURE_RECTANGLE_EXT, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP );
			GL11.glTexParameterf( EXTTextureRectangle.GL_TEXTURE_RECTANGLE_EXT, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP );
		}
	}


Obviously hard to imagine that the GL_TEXTURE_2D is wrong, but it is easier with GL_TEXTURE_RECTANGLE_EXT. ;)
GL_TEXTURE_RECTANGLE_EXT is set at the same int value as _NV and ARB_ ext's, so that you don't need to focus on what card manufacturer is involved.