简体   繁体   中英

Transparent PNG isn't transparent in LWJGL

I have a PNG with a transparent background, and I'm trying to display it using LWJGL. But instead of a transparent background, it appears with a black opaque background. I'm following the code from the "space invaders" example.

Here's my code. I apologise for its length, but I couldn't cut it down any further and still show the graphic. "ball.png" is a 256x256 image with a transparent background.

package com.ziroby.kata.bouncingBalls;

import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.opengl.Display;

import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.*;
import java.io.IOException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Hashtable;
import javax.swing.ImageIcon;

public class Game {

public void start() throws Exception {
    Display.setInitialBackground(0.5f, 0.5f, 0.5f);
    Display.create();

    // enable textures since we're going to use these for our sprites
    glEnable(GL_TEXTURE_2D);

    glMatrixMode(GL_PROJECTION);

    glOrtho(0, 800, 600, 0, -1, 1);
    glMatrixMode(GL_MODELVIEW);

    getTexture("ball.png");

    // clear screen
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // translate to the right location and prepare to draw
    glTranslatef(300, 200, 0);

    // draw a quad textured to match the sprite
    glBegin(GL_QUADS);
    {
        glTexCoord2f(0, 0);
        glVertex2f(0, 0);

        glTexCoord2f(0, 1);
        glVertex2f(0, 100);

        glTexCoord2f(1, 1);
        glVertex2f(100, 100);

        glTexCoord2f(1, 0);
        glVertex2f(100, 0);
    }
    glEnd();

    // update window contents
    Display.update();
    Thread.sleep(1000);

    Display.destroy();
}

public void getTexture(String resourceName) throws IOException {
    glBindTexture(GL_TEXTURE_2D, 1);

    BufferedImage bufferedImage = loadImage(resourceName);
    ByteBuffer textureBuffer = convertImageData(bufferedImage);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // produce a texture from the byte buffer
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferedImage.getWidth(),
            bufferedImage.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
            textureBuffer);
}

/**
 * Convert the buffered image to a texture
 */
private ByteBuffer convertImageData(BufferedImage bufferedImage) {
    ByteBuffer imageBuffer;
    WritableRaster raster;
    BufferedImage texImage;

    ColorModel glAlphaColorModel = new ComponentColorModel(ColorSpace
            .getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8, 8 },
            true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);

    raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
            bufferedImage.getWidth(), bufferedImage.getHeight(), 4, null);
    texImage = new BufferedImage(glAlphaColorModel, raster, true,
            new Hashtable());

    // copy the source image into the produced image
    Graphics g = texImage.getGraphics();
    g.setColor(new Color(0f, 0f, 0f, 0f));
    g.fillRect(0, 0, 256, 256);
    g.drawImage(bufferedImage, 0, 0, null);

    // build a byte buffer from the temporary image
    // that be used by OpenGL to produce a texture.
    byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer())
            .getData();

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

    return imageBuffer;
}

/**
 * Load a given resource as a buffered image
 */
private BufferedImage loadImage(String ref) throws IOException {
    URL url = getClass().getClassLoader().getResource(ref);

    // due to an issue with ImageIO and mixed signed code
    // we are now using good oldfashioned ImageIcon to load
    // images and the paint it on top of a new BufferedImage
    Image img = new ImageIcon(url).getImage();
    BufferedImage bufferedImage = new BufferedImage(img.getWidth(null), img
            .getHeight(null), BufferedImage.TYPE_INT_ARGB);
    Graphics g = bufferedImage.getGraphics();
    g.drawImage(img, 0, 0, null);
    g.dispose();

    return bufferedImage;
}
}

You need to enable blending to allow transparent bits on an image when using OpenGL.

You'll need to add something like the following to your code:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM