android 纹理中的GLUtils.texImage2D和Alpha问题

kqqjbcuj  于 2022-12-21  发布在  Android
关注(0)|答案(6)|浏览(189)

我使用GLUtils.texImage2D成功地生成了我的纹理,但是当我使用生成的纹理时,我的alpha出现了问题:它们比想要的更暗。
在检查了几件事之后,我最终得出结论,问题来自GLUtils.texImage2D(GL10.GL_TEXTURE_2D,level,bmp,0);
我创建了第二个函数,它使用gl.glTexImage2D(GL10.GL_TEXTURE_2D,级别,GL10.GL_RGBA,宽度,高度,0,GL10.GL_RGBA,GL10.GL_UNSIGNED_BYTE,像素2);
但是创建pixels 2的处理成本很高,pixels 2是一个字节缓冲区,我必须在将位图ARGB的值更改为纹理RGBA时重新复制字节。
有人注意到了吗?如果是的话,你是怎么解决这个问题的......
贾森
谢谢你的回答,我已经在用

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

我遇到了一个问题
我的问题是由GLUtils生成的alpha不是纹理的alpha,它更暗。
这种区别就像在阳光下和阴凉处看一种颜色(如果这有意义的话)。
我已经试过gl.gltextimage2d了,但是创建缓冲区的时间太长了,除非有一个我不知道的工具可以把位图转换成字节缓冲区...

j8ag8udp

j8ag8udp1#

texImage 2D生成一个预乘alpha纹理。在这个生成的纹理中,所有像素都乘以alpha值,所以你不需要再乘以alpha值。让我们试试
gl.glBlendFunc(GL 10.葡萄糖_一,GL 10.葡萄糖_一减去SRC_ALPHA);

58wvjzkj

58wvjzkj2#

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

  • 估计最大的纹理(如1024x1024)并创建一个该大小的int数组(1024*1024),将其存储在某个静态变量中或您可以访问它的某个地方,这样就不需要重新创建该数组(分配时间在这里非常宝贵)
  • 然后执行以下操作:
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通道,导致图像显示得比实际大时出现黑色边框(双线性滤波器计算四个像素之间的颜色并且当具有透明阿尔法的像素的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);
}
piv4azn7

piv4azn73#

解为here,它与其他人所述的预乘alpha相关。
在surfaceView构造函数中

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

在视图中,曲面上的渲染器已创建

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

8gsdolmq4#

Android Bitmap存储从PNG加载的具有预乘颜色的图像。GLUtils.texImage2D还使用由alpha预乘的颜色,因此您无法通过这种方式获得原始颜色。
为了在没有 RGB 通道预乘的情况下加载PNG图像,我使用第三方PNGDecoder并使用glTexImage2D加载纹理。您可以从此处获取 PNGDecoder 库来解码PNG:http://twl.l33tlabs.org/#downloads

c2e8gylq

c2e8gylq5#

在GLUtils中有一个问题,我建议的唯一解决方法是用途:

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

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

bkkx9g8r

bkkx9g8r6#

Android的BitmapFactory.decode()默认在加载时预乘alpha,所以如果你不想加载预乘的位图,在加载纹理位图时使用Bitmap.Options并将inPremultiplied设置为true

//kotlin
val options = BitmapFactory.Options()
options.inPremultiplied = false

val bitmap = BitmapFactory.decodeStream(inputStream, null, options)

然后将此位图传递给GLUtils.texImage2D
P.S.了解预乘alpha的好视频:
https://www.youtube.com/watch?v=wVkLeaWQOlQ

相关问题