Android:加载没有预乘alpha的位图(OpenGL ES 2.0)

这可能吗? 以非预乘的格式(直alpha?)加载纹理?

我的游戏有1或2个具有半透明像素的图像,我需要能够淡入淡出,但这似乎不太容易。

据我所知Android总是加载graphics预乘alpha格式,但如果是这样的话,如何正确地融合他们?

任何帮助,将不胜感激。

编辑我已经包含了一些代码:

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 *= "+opVal+";"+ //where opVal is a value from 0.0f to 1.0f "}"; 

接着……

 //Enable Alpha blending and set blending function GLES20.glEnable(GLES20.GL_BLEND); GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); //Draw it GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); //Disable Alpha blending GLES20.glDisable(GLES20.GL_BLEND); 

使用这种方式,图像的半透明部分将显示得太暗(包括消除锯齿边缘的黑色边框),但是会淡入和淡出(虽然图像不正确,但这并不好)。

如果我将混合模式更改为:

//启用Alpha混合和设置混合function

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

然后,它将在完全不透明度(1.0f)下完美显示,但会变得“过饱和”(这是我可以描述的最好方式),所引入的透明度越高(即0.9f降至0.0f)。

感谢您的建议,如最后接受的答案中突出显示,我不需要加载“直接alpha”,因为我能够正确使用Android预装版本,默认情况下通过更改第二我的片段着色器的行:

 "gl_FragColor *= "+opVal+";"+ 

有没有方法来加载图像没有在Android预乘,如在这个线程建议。 这也可以做到这一点,没有任何额外的内存损失,至less完全在本地进行,但我不想在这里的细节。

如果你可以使用预乘alpha,而不是例如让你的内容管道更难,你应该。 它解决了在使用双线性滤波处理半透明图像时,邻域纹理出血的其他一些问题。

预乘alpha只是意味着所有input的颜色值已经与alpha值相乘。 正常的alpha混合则需要不同的混合函数。 1-SRC_ALPHA代替SRC_ALPHA,您需要使用1,1-SRC_ALPHA,因为您已经尝试过了。 你所错过的是在着色器中考虑预乘alpha。 由于您将纹理Alpha与其他值相乘,因此您也必须对纹理颜色通道执行相同的操作。 从而

 gl_FragColor = texture2D(u_baseMap, v_texCoords); gl_FragColor.a *= opacity; 

变得简单

 gl_FragColor = texture2D(u_baseMap, v_texCoords) * opacity; 

这应该足以使你的淡出工作正确。

我记得有一种方法可以这样做,但是我想建议你使用透明胶片的预乘alpha,因为它比非预乘好得多。

只有当您的alpha值意味着不同于透明度的东西时才加载而不进行预乘,但这似乎不是您的情况。

有一个更透彻的解释,为什么在这里 preultiplied更好。 但是暂时来说,为了让你的代码能够在预乘alpha的情况下工作,你只需要在混合的时候通过alpha来停止mutliplying。 这意味着,而不是

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

你应该做

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