Why I draw an png image using glDrawPixels() can't work well?

Started by wdl7770016, August 06, 2012, 03:12:27

Previous topic - Next topic

wdl7770016

now I first use the Slick-Util which lwjgl recommand to load my game data(now just some image^_^)
the code like these:
png = new PNGImageData();
		try {
		png.loadImage(ResourceLoader.getResourceAsStream("src/img/logo.png"));
		System.out.println(png.isRGB());
		}
		catch (IOException e) {
			e.getStackTrace();
		}

then I draw image like these:
GL14.glWindowPos2d(20, 20);
		//GL11.glBitmap(142, 142, 0, 0, 0, 0, this.byteBuffer);
		GL11.glDrawPixels(142, 142, GL11.GL_RGB, GL11.GL_BYTE, png.getImageBufferData());

but the result is let me sad !! image can't display correct
!!

I don't know why? how about you to load image and draw it in openGL?
(what I sad about is 2d Image  not Texture, but I can't find any tutorial for 2D openGL)
Thx for help^_^

Evil-Devil

Though you were using slick, haven't allready looked at their examples?

// loading
Image myTexture = new Image("src/img/logo.pn");

// drawing at 100, 100:
myTexture.draw(100, 100);


Thats it with Slick ;)
http://slick.cokeandcode.com/wiki/doku.php?id=01_-_a_basic_slick_game#loading_an_image

//edit: Every image in opengl is kind of a texture. 2D is just another way of looking at your screen space.

wdl7770016

Quote from: Evil-Devil on August 06, 2012, 09:59:45
Though you were using slick, haven't allready looked at their examples?

// loading
Image myTexture = new Image("src/img/logo.pn");

// drawing at 100, 100:
myTexture.draw(100, 100);


Thats it with Slick ;)
http://slick.cokeandcode.com/wiki/doku.php?id=01_-_a_basic_slick_game#loading_an_image

//edit: Every image in opengl is kind of a texture. 2D is just another way of looking at your screen space.

I‘m sor but I just use lwjgl not the slick

though I use slick-util to load resource

Evil-Devil

Though with slick util you can load a fully qualified texture image and display it. All you have to do is bind it and apply to your vertices.

Why the direct drawing to the backbuffer with glDrawPixel does not seem to work is not within my reach. Haven't tried that function yet. Maybe it works as intended, but then you maybe clear the screen?

wdl7770016

Quote from: Evil-Devil on August 07, 2012, 07:38:53
Though with slick util you can load a fully qualified texture image and display it. All you have to do is bind it and apply to your vertices.

Why the direct drawing to the backbuffer with glDrawPixel does not seem to work is not within my reach. Haven't tried that function yet. Maybe it works as intended, but then you maybe clear the screen?
sor
but what do you mean for "Maybe it works as intended, but then you maybe clear the screen?" ?
Does it mean if I bind the texture instead of drawPixels that I can don't call glClear() to clear the screen?

Evil-Devil

What I mean is that in the general application flow you start with clearing the screen. Then you draw something on it like a textured quad and it is displayed. This is done in the backbuffer. So when you write something to the backbuffer it might be overwritten by something else you do inside your application logic.

Thats what i meant.
In your start post you just wrote the image is not displayed correct, neither you said what is not correct ;)

loadTextures()
drawScene()
writeRawImageDataToBuffer() ???

drawScene
Begin
 clearScene()
 bindTextureOne()
 drawTexturedQuad()
 bindTextureTwo()
 drawTexturedQuad()
End


With a little bit more info from your side we might find the solution to the problem ;)

wdl7770016

Quote from: Evil-Devil on August 07, 2012, 09:04:21
What I mean is that in the general application flow you start with clearing the screen. Then you draw something on it like a textured quad and it is displayed. This is done in the backbuffer. So when you write something to the backbuffer it might be overwritten by something else you do inside your application logic.

Thats what i meant.
In your start post you just wrote the image is not displayed correct, neither you said what is not correct ;)

loadTextures()
drawScene()
writeRawImageDataToBuffer() ???

drawScene
Begin
 clearScene()
 bindTextureOne()
 drawTexturedQuad()
 bindTextureTwo()
 drawTexturedQuad()
End


With a little bit more info from your side we might find the solution to the problem ;)

Thx for your enthusiastic and sorry for my careless


I have see something but pixels are garbage....
It's my code:
import java.io.IOException;
import java.nio.ByteBuffer;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import org.newdawn.slick.opengl.PNGImageData;
import org.newdawn.slick.util.ResourceLoader;

public class GameMain2 {
	private ByteBuffer byteBuffer;
	/**
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		new GameMain2().launch();
	}

	public void launch() {
		try {
			Display.setDisplayMode(new DisplayMode(800, 600));
			Display.setTitle("YourGame");
			Display.create();
			this.initGL();
		}
		catch (LWJGLException e) {
			e.getStackTrace();
		}

		while (!Display.isCloseRequested()) {
			this.render();
			Display.update();
			Display.sync(60);
		}
		Display.destroy();
	}

	private void initGL() {
		GL11.glClearColor(0, 0, 0, 0);
		
		GL11.glOrtho(0, 800, 0, 600, -1, 1); 

		//GL11.glEnable(GL11.GL_TEXTURE_2D);
		
		try {
			PNGImageData png = new PNGImageData();
			png.loadImage(ResourceLoader.getResourceAsStream("src/img/logo.png"));
			this.byteBuffer = png.getImageBufferData();
		}
		catch (IOException e) {
			e.getStackTrace();
		}
	}
	
	private void render() {
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
		//GL11.glColor3f(0, 1, 1);
		GL14.glWindowPos2d(20, 20);
		//GL11.glBitmap(142, 142, 0, 0, 0, 0, this.byteBuffer);
		GL11.glDrawPixels(142, 142, GL11.GL_RGB, GL11.GL_BYTE, this.byteBuffer);
	}
}


this is the image what I want to display(I don't know why img can't display, you can click it to display) :

and this is the garbage pixels what display:

I had ask this problem in java-Gaming.org but no result they all say use texture bind...
I just thought that there are glDrawPixels method in opengl  but I had to use the Texture bind to make a 2D game it's feel so shit。。(may because I just a newer for opengl and I always think that use Texture may more waste performance because we should draw a rec and bind texture, but drawPixels just need draw it, right?)

Evil-Devil

Actually it should be way more easier to use an opengl texture object you bind than using the raw data.

For the data in glDrawPixel, have you allready tried GL_UNSIGNED_BYTE or took a look what kind of buffer the data uses.
The 142x142x32bit PNG should fit into a ByteBuffer with the size of 80.656 bytes.

I think that the overall effort to display your image data is a neat idea, but you will end up with a lot of problems. Especially with Z-Ordering, Effects etc.


wdl7770016

Quote from: Evil-Devil on August 07, 2012, 12:41:27
Actually it should be way more easier to use an opengl texture object you bind than using the raw data.

For the data in glDrawPixel, have you allready tried GL_UNSIGNED_BYTE or took a look what kind of buffer the data uses.
The 142x142x32bit PNG should fit into a ByteBuffer with the size of 80.656 bytes.

I think that the overall effort to display your image data is a neat idea, but you will end up with a lot of problems. Especially with Z-Ordering, Effects etc.


I had try a lot but all no use  
I had print the this.byteBuffer.capacity()and it return 196608 >80656...so strange..!!
then how does PNGImageData to use which from slick-util.jar


and do you know why when I bind Texture the Texture'size not same as the square ... I 'm newer for opengl

Evil-Devil

A texture in opengl has to be p^2. Afaik slick gets around with this by padding the missing width/height to the next power.

Some valid sizes: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096

For your texture i guess it has been put into a 192x256 texture. That would match your 196.608

what do you mean with your last statement? Does is look different or is it scaled?

wdl7770016

Quote from: Evil-Devil on August 07, 2012, 14:35:10
A texture in opengl has to be p^2. Afaik slick gets around with this by padding the missing width/height to the next power.

Some valid sizes: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096

For your texture i guess it has been put into a 192x256 texture. That would match your 196.608

what do you mean with your last statement? Does is look different or is it scaled?
what I mean is that when I bind Texture it will be like this(image size is 142 x 142) :

only a part of square will be bind with Texture and others will be transparent(in fact the part of white will be black, I just want you to know how the texture will bind. :P)
and the direction of texture will be upside down

the code is here :
public class GameMain {
	private Texture tex;
	/**
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		new GameMain().launch();
	}

	public void launch() {
		try {
			//DisplayMode disMode = Display.getDesktopDisplayMode();
			Display.setDisplayMode(new DisplayMode(800, 600));
			Display.setTitle("YourGame");
			Display.create();
			this.initGL();
		} catch (LWJGLException e) {
			e.getStackTrace();
		}

		while (!Display.isCloseRequested()) {
			this.rollInput();
			this.render();
			Display.update();
			Display.sync(60);
		}
		Display.destroy();
	}

	private void rollInput() {
		while (Keyboard.next()) {
			if (Keyboard.getEventKey() == Keyboard.KEY_LSHIFT) {
				if (Keyboard.getEventKeyState()) {
					System.out.println("sb");
				}
			}
		}
	}
	
	private void initGL() {
		GL11.glClearColor(0, 0, 0, 0);
		//GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glOrtho(0, 800, 0, 600, -1, 1); 
		GL11.glEnable(GL11.GL_TEXTURE_2D);
		//GL11.glViewport(0, 0, 800, 600);
		//GL11.glEnable(GL11.GL_BLEND); 
		//GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); 

		try {
			tex = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("src/img/logo.png"));
		}
		catch (IOException e) {
			e.getStackTrace();
		}
	}
	
	private void render() {
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
		//GL11.glColor3f(0, 1, 1);
		//GL14.glWindowPos2d(20, 20);
		//GL11.glBitmap(142, 142, 0, 0, 0, 0, this.byteBuffer);
		//GL11.glDrawPixels(142, 142, GL11.GL_RGB, GL11.GL_BYTE, bb);
		tex.bind();
		GL11.glBegin(GL11.GL_QUADS);
		GL11.glTexCoord2f(0, 0);
		GL11.glVertex2f(0, 0); 
		GL11.glTexCoord2f(1,0); 
		GL11.glVertex2f(tex.getImageWidth(), 0); 
		GL11.glTexCoord2f(1,1); 
		GL11.glVertex2f(tex.getImageWidth(), tex.getImageHeight()); 
		GL11.glTexCoord2f(0,1); 
		GL11.glVertex2f(0, tex.getImageHeight()); 
		GL11.glEnd(); 
	}
}

Evil-Devil

Yea, thats what i said. Your source texture is about 142x142. OpenGL can't work with that dimension. It does need some power of 2 sized texture. The SLICK-Util loading will add the needed padding.

It will bind the texture as it is after the loading.

When you load the image with slick util you can provide some behaviors. Like transparent color, flipping the image and so on (take a look at the javadocs).

For the best results i advise you to create well sized textures. That way you don't have to relay on the auto-padding ;)

wdl7770016

Quote from: Evil-Devil on August 08, 2012, 13:05:42
Yea, thats what i said. Your source texture is about 142x142. OpenGL can't work with that dimension. It does need some power of 2 sized texture. The SLICK-Util loading will add the needed padding.

It will bind the texture as it is after the loading.

When you load the image with slick util you can provide some behaviors. Like transparent color, flipping the image and so on (take a look at the javadocs).

For the best results i advise you to create well sized textures. That way you don't have to relay on the auto-padding ;)

yup you are right
it works
but a new problem is that the texture had be upside down,like these:

the original img is like this:

...

Evil-Devil

Ha, yea. Thats easy to explain. Take a look at your draw order.

You start at 0/0 (x/y, bottom left area) and proceed with width/0, width/height, 0/height. So your image is drawn inverted ;)

Take a look at this picture

and you can see how the coordinates apply.

You started in the bottom left place ;) When starting at top left and proceeding down to right to rop it should look right.

wdl7770016

Quote from: Evil-Devil on August 08, 2012, 15:57:44
Ha, yea. Thats easy to explain. Take a look at your draw order.

You start at 0/0 (x/y, bottom left area) and proceed with width/0, width/height, 0/height. So your image is drawn inverted ;)

Take a look at this picture

and you can see how the coordinates apply.

You started in the bottom left place ;) When starting at top left and proceeding down to right to rop it should look right.

yup you are right!!!
but why the Texture bind order is different with draw order?
and another question is  that Texture.bind() will auto call GL11.glEnable(GL11.GL_TEXTURE_2D) right ?