Android 使用半透明png';s作为纹理并淡入淡出OpenGL ES 2.0

Android 使用半透明png';s作为纹理并淡入淡出OpenGL ES 2.0,android,opengl-es-2.0,textures,alphablending,translucency,Android,Opengl Es 2.0,Textures,Alphablending,Translucency,我有一些.png文件,我正在使用它们作为2d游戏四精灵的纹理 其中一些已经有部分透明的像素,我需要能够正确显示它们并淡入/淡出 最初,我使用以下混合模式绘制它们: GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); 这适用于刚开始时为实体的纹理,我可以使用1.0f和0.0f之间的任何值来引入透明度。到目前为止还不错,但当我尝试使用已经有透明度的png时,它们将无法正确显示(它们太暗,轮廓太暗) 我做了很

我有一些.png文件,我正在使用它们作为2d游戏四精灵的纹理

其中一些已经有部分透明的像素,我需要能够正确显示它们并淡入/淡出

最初,我使用以下混合模式绘制它们:

GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
这适用于刚开始时为实体的纹理,我可以使用1.0f和0.0f之间的任何值来引入透明度。到目前为止还不错,但当我尝试使用已经有透明度的png时,它们将无法正确显示(它们太暗,轮廓太暗)

我做了很多研究,发现我需要为这些类型的纹理更改混合模式,因为上面的一种无法正常工作,所以这就是我现在拥有的(包括我的着色器)

片段着色器

String strFShader =
"precision mediump float;" +
"varying vec2 v_texCoords;" +
"uniform sampler2D u_baseMap;" +
"void main()" +
"{" +
"gl_FragColor = texture2D(u_baseMap, v_texCoords);" +
"gl_FragColor.a *= "+1.0f+";"+  //** Where 1.0f is the amount to blend, with 0.0f being completely transparent and 1.0f being as per the original png file.
 "}";
代码

GLES20.glEnable(GLES20.GL_BLEND); 
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

GLES20.glDisable(GLES20.GL_BLEND);
如果我在着色器中使用该值1.0f绘制半透明纹理(如上所述),它将绘制得非常好。然而,如果我尝试淡出它,当它在0.0f时,有些颜色似乎淡出,有些则不淡出,我只剩下原始纹理的奇色版本

如果有人能告诉我如何正确渲染这些类型的纹理,我将不胜感激


谢谢

如果它们太暗且轮廓较暗,这似乎是由于颜色通道被alpha通道预乘造成的。在这种情况下,在纹理非常透明的部分,颜色会变暗。比方说,如果像素的alpha值为0.9,那么预乘RGB颜色将比实际颜色暗90%


为了加载PNG图像而不使RGB通道被alpha预乘,我们使用第三方
PNGDecoder
,然后使用
glTexImage2D()
加载纹理。您可以从这里获取解码PNG的
PNGDecoder
库:

我最终不需要将图像转换为非预乘图像,我只是将它们保留为该格式,并将着色器中的行更改为:

"gl_FragColor *= "+op+";"+
而且用

GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);

工作完美。

Hi@keaukraine-非常感谢您的评论!然而,我不太明白。为什么我需要下载PNGDecoder?你是说如果没有它,就无法在Android中使用半透明纹理?我更愿意在不下载任何exta的情况下(例如,仅仅通过修改我的代码)执行此操作,我假设这是可能的,因为使用surfaceview时位图显示正常,而不是使用openGL-。。。。。如果你能详细说明,那就太好了-谢谢!Android
Bitmap
类始终按alpha通道对颜色进行预乘。这就是为什么我们必须使用
PNGDecoder
。谢谢@keaukraine,你知道有什么方法不使用任何第三方库就能做到这一点吗?你用过这个解码器吗?这是否意味着将使用3倍的内存?这似乎与我刚刚发现的手动解码位图的方法非常相似,但这种方法的内存效率不是很高,如何比较,内存效率方面?谢谢你的建议。如果可能的话,我们会使用股票Android类。但事实并非如此。这就是我们使用第三方库的原因。内存分配是正常的,但我还没有执行任何精确的测量。你可以在这里找到谷歌对此问题的官方回应: