透明 PNG 在 LWJGL 中不透明

发布于 2024-11-02 18:40:22 字数 4024 浏览 1 评论 0原文

我有一个带有透明背景的 PNG,我正在尝试使用 LWJGL 显示它。但它不是透明背景,而是黑色不透明背景。我正在遵循“太空入侵者”示例中的代码。

这是我的代码。我对它的长度表示歉意,但我无法进一步削减它并仍然显示图形。 “ball.png”是具有透明背景的 256x256 图像。

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

使用 OpenGL 时,您需要启用混合以允许图像上的透明位。

您需要在代码中添加类似以下内容:

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文