Прозрачный PNG не является прозрачным в LWJGL

#java #opengl #lwjgl

#java #opengl #lwjgl

Вопрос:

У меня есть PNG с прозрачным фоном, и я пытаюсь отобразить его с помощью LWJGL. Но вместо прозрачного фона он отображается с черным непрозрачным фоном. Я следую коду из примера «space invaders».

Вот мой код. Я приношу извинения за его длину, но я не мог сократить его дальше и по-прежнему показывать графику. «ball.png» — это изображение размером 256×256 с прозрачным фоном.

 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;
}
}
  

Ответ №1:

Вам необходимо включить смешивание, чтобы разрешить прозрачные биты на изображении при использовании OpenGL.

Вам нужно будет добавить в свой код что-то вроде следующего:

Изменяемый (GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);