I've been attempting to solve this problem without any luck. I have four classes, the main class, an Object class, a sprite class and an image loader class.
I'm attempting to load a png using the image loader and using the method found here: http://www.java-gaming.org/topics/bufferedimage-to-lwjgl-texture/25516/msg/220280/view.html#msg220280 to convert to a ByteBuffer, and then bind to OpenGL.
The Image is in it's own seperate resource folder. What should be being drawn is this: (http://i.imgur.com/j8GBU4c.png) (32x32), but what I'm seeing is a white box that has the dimensions of the image, but not the actual texture.
If anyone has any idea of where I could go to fix this I'd appreciate it. I'm new to OpenGL and looking to avoid using an external library in order to learn how the actual code works. Thanks.
Updated!
To anyone following, I implemented the suggestion provided by Vallentin, however the quad is now taking the color of the first pixel in the image. I've attempted implementing an image loader provided by C.S here. However now I'm receiving this error:
javax.imageio.IIOException: Error reading PNG image data
at com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1291)
at com.sun.imageio.plugins.png.PNGImageReader.read(PNGImageReader.java:1560)
at pImageLoader.loadBIn(pImageLoader.java:60)
at Monkeybars.main(Monkeybars.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: javax.imageio.IIOException: Destination type from ImageReadParam does not match!
at javax.imageio.ImageReader.getDestination(ImageReader.java:2862)
at com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1263)
... 8 more
Exception in thread "main" java.lang.NullPointerException
at pImageLoader.loadpSprite(pImageLoader.java:75)
at Monkeybars.main(Monkeybars.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
I'm using IntelliJ 12 on Windows 7, using Java 6. The Image I'm trying to load is linked above. If anyone has any ideas, I'm open to suggestions.
Main Block:
public static void main(String[] args){
System.out.println("Sup!");
int width = 800 ;
int height = 600;
try{
Display.setDisplayMode(new DisplayMode(width,height));
Display.setTitle("The Playground");
Display.create();
}catch (LWJGLException e){
e.printStackTrace();
Display.destroy();
System.exit(1);
}
//Initialize OpenGL
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, width, height, 0f, 1f, -1f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glEnable(GL11.GL_BLEND);
pObject MrRedSquare = new pObject(300f,300f,pImageLoader.loadpSprite(pImageLoader.loadBIn("test.png")));
while(!Display.isCloseRequested()){
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
MrRedSquare.drawMe();
Display.sync(60);
Display.update();
}
}
}
Texture Loader, new method.
public static BufferedImage loadBIn(String filepath){
BufferedImage image;
// get the reader
ImageReader ir = ImageIO.getImageReadersByFormatName("png").next();
// get the default param
ImageReadParam p = ir.getDefaultReadParam();
p.setDestinationType(
// define the image type to return if supported
ImageTypeSpecifier.createInterleaved(
ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[] {0, 1, 2, 3}, // <-- the order of the color bands to return so the bytes are in the desired order
DataBuffer.TYPE_BYTE,
true, false)
);
try{
InputStream stream = pImageLoader.class.getClassLoader().getResourceAsStream(filepath);
ImageInputStream imageStream = ImageIO.createImageInputStream(stream);
ir.setInput(imageStream);
image = ir.read(0, p);
}catch(Exception e){
System.out.print("IMAGELOADER CANNOT OBTAIN ASSET");
e.printStackTrace();
return null;
}
return image;
}
Older code, kept for archival purposes
Main:
public static void main(String[] args){
System.out.println("Sup!");
try{
Display.setDisplayMode(new DisplayMode(800,600));
Display.setTitle("The Playground");
Display.create();
}catch (LWJGLException e){
e.printStackTrace();
Display.destroy();
System.exit(1);
}
//Initialize OpenGL
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 800, 0, 600, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
pObject MrRedSquare = new pObject(300,300,pImageLoader.loadpSprite(pImageLoader.loadBI("square.png")));
while(!Display.isCloseRequested()){
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
MrRedSquare.drawMe();
Display.sync(60);
Display.update();
}
}
Object (draw code):
public void drawMe(){
// store the current model matrix
GL11.glPushMatrix();
// bind to the appropriate texture for this sprite
texture.bind();
// translate to the right location and prepare to draw
GL11.glTranslatef(x, y, 0);
// draw a quad textured to match the sprite
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(0, texture.getHeight());
GL11.glVertex2f(0, height);
GL11.glTexCoord2f(texture.getWidth(), texture.getHeight());
GL11.glVertex2f(width,height);
GL11.glTexCoord2f(texture.getWidth(), 0);
GL11.glVertex2f(width,0);
}
GL11.glEnd();
// restore the model view matrix to prevent contamination
GL11.glPopMatrix();
}
Texture:
public class pSprite {
protected ByteBuffer spriteData;
protected BufferedImage spriteImage;
protected int id;
protected int width;
protected int height;
//---------------------------------------------------------------------------------------
//Constructors:
pSprite(BufferedImage sI, ByteBuffer s, int i){
spriteImage = sI;
spriteData = s;
id = i;
width = spriteImage.getWidth();
height = spriteImage.getHeight();
}
//---------------------------------------------------------------------------------------
//Methods:
public void bind(){
GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);
}
ImageLoader:
public class pImageLoader {
public static BufferedImage loadBI(String filepath){
BufferedImage image;
try{
InputStream input = pImageLoader.class.getResourceAsStream(filepath);
image = ImageIO.read(input);
}catch (Exception e){
System.out.print("IMAGELOADER: Cannot obtain asset.");
e.printStackTrace();
return null;
}
return image;
}
public static pSprite loadpSprite(BufferedImage image){
//http://www.java-gaming.org/topics/bufferedimage-to-lwjgl-texture/25516/msg/220280/view.html#msg220280
int pixels[] = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4); // <-- 4 for RGBA, 3 for RGB
for(int y = 0; y < image.getHeight(); y++){
for(int x = 0; x < image.getWidth(); x++){
int pixel = pixels[y * image.getWidth() + x];
buffer.put((byte) ((pixel >> 16) & 0xFF)); // Red component
buffer.put((byte) ((pixel >> 8) & 0xFF)); // Green component
buffer.put((byte) (pixel & 0xFF)); // Blue component
buffer.put((byte) ((pixel >> 24) & 0xFF)); // Alpha component. Only for RGBA
}
}
buffer.flip();
int textureID = glGenTextures(); //Generate texture ID
glBindTexture(GL_TEXTURE_2D, textureID);
// Setup wrap mode
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
//Setup texture scaling filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//Send texel data to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
return new pSprite(image, buffer, textureID);
}
}
glEnable(GL_TEXTURE_2D)
before binding the texture for the first time and before uploading to OpenGL. This might be enough depending on your image (is it RGBA? RGB?). If you still have problems try to read the image in the way suggested in the answer I have provided to the link I gave, you should not make assumptions about the byte order returned when reading png files. But you can request toImageIO
to use the order you expect. – c.s.