我想要做的就是这个,想象一下我的太阳里面有一个小瓦片(32x32),这是一个黑色背景的黄色圆圈。
我想画天空中的太阳(淡蓝色)。显然黑色边框会破坏我的构图。我必须让OpenGL删除那种黑色。
在Photoshop中,我会使用魔术工具选择所有黑色像素,然后将其删除,并使用Alpha通道保存新文件。
但如果您拥有数百万张图片,那么这可能太长了。我必须在运行时处理这个问题。
我一直在寻找glStencilMask
方法,但是如果你实际上有一个纹理可以用作蒙版,那将会有效。
我找到了一个C#的例子,谈到了采用24位图像并使用alpha通道转换为32位,这听起来不错,但可能耗费时间和资源支出太多,特别是如果瓷砖的数量是高(大约30x20瓦,60fps)
事情是这很难达到,达到这个目标的人不会告诉任何人......
实际上绘制图块的代码是这样的,它将剪切,翻译,旋转以及所需的所有内容。
GL11.glPushMatrix();
// bind to the appropriate texture for this sprite
this.texture.bind();
// translate to the right location and prepare to draw
GL11.glColor3f(1, 1, 1);
GL11.glTranslated(x + ((32 - this.texture.getImageWidth()) / 2) + (this.texture.getImageWidth() / 2), y + ((32 - this.texture.getImageHeight()) / 2)
+ (this.texture.getImageHeight() / 2), 0);
// System.out.println(this.angle);
GL11.glRotated(this.angle, 0, 0, 1);
GL11.glTranslated(-this.texture.getImageWidth() / 2, -this.texture.getImageHeight() / 2, 0);
// draw a quad textured to match the sprite
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(0, this.texture.getHeight());
GL11.glVertex2f(0, this.texture.getImageHeight());
GL11.glTexCoord2f(this.texture.getWidth(), this.texture.getHeight());
GL11.glVertex2f(this.texture.getImageWidth(), this.texture.getImageHeight());
GL11.glTexCoord2f(this.texture.getWidth(), 0);
GL11.glVertex2f(this.texture.getImageWidth(), 0);
}
GL11.glEnd();
// restore the model view matrix to prevent contamination
GL11.glPopMatrix();
texture.bind就是这样:
public void bind() {
GL11.glBindTexture(this.target, this.textureID);
}
对于包含透明层的图像,一切都很完美。
一旦我找到了如何删除该特定颜色,我希望根据左上角像素删除颜色,这将通过glReadPixels()
这是装载机:
public Texture getTexture(String resourceName, int target, int dstPixelFormat, int minFilter, int magFilter) throws IOException {
int srcPixelFormat = 0;
// create the texture ID for this texture
int textureID = this.createTextureID();
Texture texture = new Texture(target, textureID);
// bind this texture
GL11.glBindTexture(target, textureID);
BufferedImage bufferedImage = this.loadImage(resourceName);
texture.setWidth(bufferedImage.getWidth());
texture.setHeight(bufferedImage.getHeight());
if (bufferedImage.getColorModel().hasAlpha()) {
srcPixelFormat = GL11.GL_RGBA;
} else {
srcPixelFormat = GL11.GL_RGB;
}
// convert that image into a byte buffer of texture data
ByteBuffer textureBuffer = this.convertImageData(bufferedImage, texture);
if (target == GL11.GL_TEXTURE_2D) {
GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, minFilter);
GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, magFilter);
}
// produce a texture from the byte buffer
GL11.glTexImage2D(target, 0, dstPixelFormat, this.get2Fold(bufferedImage.getWidth()), this.get2Fold(bufferedImage.getHeight()), 0, srcPixelFormat,
GL11.GL_UNSIGNED_BYTE, textureBuffer);
return texture;
}
答案 0 :(得分:0)
实际上我已经为这个问题创建了一个解决方案,所以我创建了一个方法,我将在这里发布,以便为未来的人们提供知识。
/**
* Sets the specified colour, or the color taken from the top-left pixel, to transparent
*
* @param image
* The image to process (<code>BufferedImage</code>)
* @param cornerTransparency
* If true the method will take the top-left pixel's colour and make it transparent in the image
* @param transCol
* If <code>cornerTransparency</code> is false, this is the color that will be set to transparent.
* @return The loaded buffered image
* @throws IOException
* Indicates a failure to find a resource
*/
private BufferedImage loadImage(BufferedImage image, boolean cornerTransparency, int transCol) throws IOException {
if(image == null){
throw new IllegalArgumentException();
}
int firstPixel = bufferedImage.getRGB(0, 0);
BufferedImage bff = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
for (int y = 0; y < bufferedImage.getHeight(); ++y) {
for (int x = 0; x < bufferedImage.getWidth(); ++x) {
int argb = bufferedImage.getRGB(x, y);
if (cornerTransparency) {
if (argb == firstPixel) {//we are certain that they are of the same type (RGB,ARGB etc)
bff.setRGB(x, y, 0); //black with alpha = 0
} else {
bff.setRGB(x, y, argb);
}
} else {
if ((argb & 0xFF000000) == (transCol & 0xFF000000)) {//not sure if are of the same type, I remove the alpha data.
bff.setRGB(x, y, 0); //black with alpha = 0
} else {
bff.setRGB(x, y, argb);
}
}
}
}
return bff;
} else {
return bufferedImage;
}