3

我使用带有以下代码的 Mac 计算机在 Java 6 中创建图像。然后我尝试使用 OpenGL ES 在 Android 设备中显示该图像。不显示图像,仅显示白色图像。但是,如果没有半透明像素,则图像会很好地显示。

显示在 Photoshop 中创建的半透明图像没有问题。只有用 Java 创建的半透明图像才有问题。我还尝试了用 Java 创建半透明图像的不同方法,但我总是得到相同的结果,即在 OpenGL 中显示的白色图像。在这一点上,我相信这是 Java 的一个错误,(在 Mac 计算机中)。有没有人遇到过这样的事情?知道为什么会发生这种情况吗?

//创建图片的代码

int cmap[] = { 
0x00000000, /*transparent*/ 
0xFF000000, /*black*/ 
0xFFFF0000, /*red*/ 
0xFFFFFF00, /*yellow*/ 
0xFF00FF00, /*green*/ 
//...... 
}; 
IndexColorModel colorModel = new IndexColorModel(8, 
cmap.length, cmap, 0, true, -1, DataBuffer.TYPE_BYTE); 
BufferedImage image = new BufferedImage(256, 256, 
BufferedImage.TYPE_BYTE_INDEXED, colorModel); 
Graphics2D g = image.createGraphics(); 
g.setBackground(new Color(0,0,0,0)); /*transparent*/ 
g.clearRect(0 , 0, image.getWidth(), image.getHeight()); 
g.setColor(Color.red); 
g.draw(new Rectangle(10, 10, 40, 40));


ImageIO.write(image, "PNG", new File("rectangle.png")); 

下面是加载纹理的代码。请注意,这是特定于 Android 环境的。

public static void loadAndBindTexture(GL10 gl) throws Exception
{ 
    int numberTextures=1;
    int[] textures = new int[numberTextures];
    gl.glGenTextures(numberTextures, textures, 0);
    int textureID=textures[0];

    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);//polyBreaker3DObject_.mTextureID);

    checkGLError(gl, 998);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_LINEAR);
    checkGLError(gl, 997);
    //NOTE: FOR GL_TEXTURE_MAG_FILTER only GL_NEAREST or GL_LINEAR are valid.
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    checkGLError(gl, 996);

    /*Commented on Sept. 30, 2010 6:21AM
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);
    */
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,GL10.GL_CLAMP_TO_EDGE);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,GL10.GL_CLAMP_TO_EDGE);
    checkGLError(gl, 1000);

    gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,GL10.GL_DECAL);
    checkGLError(gl, 1001);
    gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
    checkGLError(gl, 1002);


 if(mContext==null)//mContext is the Context of the current Android application (it is set before this method is called
    throw new Exception("Context has not been set.");
 InputStream is = mContext.getResources().openRawResource(R.drawable.metal128x128);//blueski);//robot);
Bitmap bitmap;
try {

    bitmap = BitmapFactory.decodeStream(is);

} finally {
    try {
        is.close();
    } catch(IOException e) {
        Log.printCaughtExceptionMsg(e);
    }
}

GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();

   checkGLError(gl, 1003);

}
4

2 回答 2

1

您可以将实际调用发布到glDrawElements()orglDrawArrays()吗?如果不查看实际的 OpenGL 绘图调用,很难判断您做错了什么。但是您可能在绘制纹理之前没有启用混合。

这样的事情应该可以解决问题:

gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL10.GL_BLEND);

如果您想了解更多信息,请查看这个问题。

编辑:

我的错误,我看错了你的问题。你应该看看你正在使用的 BufferedImage 格式。 根据文档TYPE_BYTE_INDEXED,似乎不支持 alpha 值。您是否尝试过使用?TYPE_INT_ARGB

于 2012-04-13T17:57:21.710 回答
0

我仍然无法弄清楚为什么用 Java 创建的透明图像在 Android OpenGL ES 中不起作用。但是,我确实找到了一个允许图像工作的 hack。

在java中创建新的透明图像时,您应该做的第一件事是使用方法调用在其上绘制半透明图像

        g.drawImage(Image img, x, y,  null);

//g 是从正在创建的新图像中获取的 Graphics 对象

//img 参数是半透明的,不是 100% 透明的(否则它将不起作用)在 Photoshop 中创建的图像。我使用 4x4 尺寸,这样它就不会被注意到。

在此调用之后,您可以继续执行原始代码。新图像现在可以在 Android OpenGL ES 中使用。

我的猜测是,通过绘制一个半透明的图像,它会改变生成的 PNG 文件的格式,而这种格式的改变使它可以在 Android OpenGL ES 中工作。

于 2012-04-13T17:56:22.430 回答