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