lwjgl 2d transparency not working

I’ve finally decided that instead of using wrappers it’s time to learn lwjgl for myself, and I’m making acceptable progress but I’m having a problem with sprite transparency. The last thing I want to do is ask for help, but I’ve spent enough time failing to fix the code…

The background of the player sprite is transparent, but when rendered, it’s white. And that’s the problem :clue:

Code Used:


	/**
	 * Converts a buffered image file into a texture instance, and
	 * caches it in memory for later use.
	 */
	public void addTexture(String name, File image) {
		try {
			BufferedImage bufferedImage = ImageIO.read(image);
			int w = bufferedImage.getWidth();
			int h = bufferedImage.getHeight();
			int[] pixels = new int[w * h];
			bufferedImage.getRGB(0, 0, w, h, pixels, 0, w);
			ByteBuffer buffer = BufferUtils.createByteBuffer(w * h * 3);

	         //DataBufferByte rawData =  (DataBufferByte) ((RenderedImage) bufferedImage).getData().getDataBuffer();
	         //ByteBuffer buffer = BufferUtils.createByteBuffer(rawData.getSize());

			for(int y = 0; y < h; y++) {
				for(int x = 0; x < w; x++) {
					int pixel = pixels[y * w + 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.flip();

			int textureId = GL11.glGenTextures();

			if (doesTextureExist(name)) {
				System.err.println("Texture '" + name + "' already exists! Request denied.");
				return;
			}

			Texture texture = new Texture(name, bufferedImage, textureId);
			textureCache.add(texture);

			/*
			 * Create a new texture object in memory and bind it
			 */
			GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
			
			// don't think this is needed a 2D pokemon style game?
			//GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
			//GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
			
			GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
			GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
			
			/*
			 * Upload the texture data and generate mip maps (for scaling)
			 */
			GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, w, h, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, buffer);

			// XXX we need to use RGBA? but it throws an exception..
			//GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, w, h, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Draws texture <name> at the given 2D coordinates <x> <y>.
	 */
	public void draw(String name, int x, int y) {
		Texture texture = getTextureByName(name);
		if (texture != null) {
			GL11.glPushMatrix();
			GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getTextureId());
			GL11.glColor3f(1.0f, 1.0f, 1.0f);
			GL11.glBegin(GL11.GL_QUADS);
			GL11.glTexCoord2f(0, 0);
			GL11.glVertex2f(x, y);
			GL11.glTexCoord2f(1, 0);
			GL11.glVertex2f(x + texture.getWidth(), y);
			GL11.glTexCoord2f(1, 1);
			GL11.glVertex2f(x + texture.getWidth(),y + texture.getHeight());
			GL11.glTexCoord2f(0, 1);
			GL11.glVertex2f(x, y + texture.getHeight());
			GL11.glLoadIdentity();
			GL11.glEnd();
			GL11.glPopMatrix();
		}
	}


Exception:


java.lang.IllegalArgumentException: Number of remaining buffer elements is 768, must be at least 1024. Because at most 1024 elements can be returned, a buffer with at least 1024 elements is required, regardless of actual returned element count
	at org.lwjgl.BufferChecks.throwBufferSizeException(BufferChecks.java:162)
	at org.lwjgl.BufferChecks.checkBufferSize(BufferChecks.java:189)
	at org.lwjgl.BufferChecks.checkBuffer(BufferChecks.java:230)
	at org.lwjgl.opengl.GL11.glTexImage2D(GL11.java:2855)
	at wrapper.texture.TextureManager.addTexture(TextureManager.java:89)

Are you declaring what size the image should be and not making it that size?

you’re not adding alpha to your buffer


//before nested loop
boolean hasAlpha = image.getColorModel().hasAlpha();

if (hasAlpha) {
    buffer.put((byte) ((pixel >> 24) & 0xFF));
} else {
    buffer.put((byte) ((pixel) & 0xFF));
}

EDIT :
Also shoudl be this:

ByteBuffer buffer = BufferUtils.createByteBuffer(w * h * 4);

Make sure you also blend when rendering.

Thank you KudoDEV, that did the trick!

It also doesn’t appear like you are setting the blending mode, which may or may not cause problems down the road. Add this to your initialization:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

I’m calling what you mentioned, once when the application starts up, after the Display is created.

You only need to enable blend when you require it. In your case you can set it at initialization.