纹理中GLUtils.texImage2D和Alpha的问题

时间:2010-10-13 07:48:27

标签: android opengl-es bitmap

我使用GLUtils.texImage2D成功生成纹理, 但是当我使用生成的纹理时,我的alpha会出现问题:它们比想要的更暗。

在检查了几件事之后,我终于得出了问题来自GLUtils.texImage2D(GL10.GL_TEXTURE_2D,level,bmp,0)的结论;

我创建了第二个使用gl.glTexImage2D的函数(GL10.GL_TEXTURE_2D,level,GL10.GL_RGBA,width,height,0,GL10.GL_RGBA,GL10.GL_UNSIGNED_BYTE,pixels2);

但是处理创建像素2的代价很高,这是一个字节缓冲区,我必须重新复制字节,同时将位图ARGB中的值更改为纹理RGBA。

有人注意到了吗?如果是这样,你是如何解决这个问题的?

杰森


感谢您的回答, 我已经在使用

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

我遇到了这个问题

我的问题是GLUtils生成的alpha不是纹理中的一个,它的颜色较深。

区别就像在阳光下和阴影中看颜色(如果有任何意义)。

我已经尝试了gl.gltextimage2d但是创建缓冲区需要太长时间,除非有一个工具将位图转换为我不知道的字节缓冲区...

5 个答案:

答案 0 :(得分:5)

GLUtils.texImage2D生成一个预乘的alpha纹理。在此生成的纹理中,所有像素都乘以alpha值,因此您无需再次将Alpha值相乘。 我们试试

gl.glBlendFunc(GL10.GL_ONE,GL10.GL_ONE_MINUS_SRC_ALPHA);

答案 1 :(得分:3)

alpha通道是我所能说的大量程序员的不良受虐待的继子...但如果你这样做,上传工作效率相当高:

  • 估算最大的纹理(如1024x1024)并创建一个大小为(1024 * 1024)的int数组,存储在某个静态变量中或可以访问它的某个位置,这样就不需要重新创建那个数组(这里的分配时间很宝贵)

  • 然后这样做:

    bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, width, height, 
         0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, IntBuffer.wrap(pixels));
    

我很抱歉没有找到不同的解决方案......最初的问题是,GLUtils.texImage2D函数的实现者错误地处理了alpha通道,当图像显示得比它大时,会导致黑色边框(双线性滤波器计算四个像素之间的颜色,当具有透明alpha的像素的rgb值被破坏时(如设置为黑色),结果是,在透明边界上发生了某种“颜色渗色”,即非常难看。可能是为了提高压缩率,因为PSD中alpha透明区域的RGB值包含大量垃圾,当消除时会为压缩算法带来很大的改进空间)

编辑:遗憾的是,这种方法仅适用于灰度图像,因为在从位图获取像素时交换了红色和蓝色通道。至少在我的设备上。我不确定这对其他设备有多正确,但在我的情况下,这就是诀窍:

for (int i=0;i<pixels.length;i+=1) {
    int argb = pixels[i];
    pixels[i] = argb&0xff00ff00 | ((argb&0xff)<<16) | ((argb>>16)&0xff);
}

答案 2 :(得分:3)

找到解决方案here。如其他人所述,它与预乘alpha有关。

在surfaceView构造函数

    setEGLConfigChooser(8, 8, 8, 8, 0, 0); 
    getHolder().setFormat(PixelFormat.RGBA_8888); 

在View.Renderer onSurfaceCreated

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

答案 3 :(得分:1)

Android Bitmap存储从PNG加载的具有预乘颜色的图像。 GLUtils.texImage2D也使用alpha预乘的颜色,因此您不能以这种方式获得原始颜色。

为了在没有 RGB 频道预加载的情况下加载PNG图像,我使用第三方PNGDecoder并使用glTexImage2D加载纹理。您可以从 PNGDecoder 库中解码PNG:http://twl.l33tlabs.org/#downloads

答案 4 :(得分:0)

GLUtils中存在预乘alpha的问题。我可以建议的唯一解决方法是使用:

gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA)

如果您需要其他混合功能,则必须使用gl.glTexImage2D