2014-03-26 53 views
0

我的應用使用全屏glSurface疊加,8888格式。對於大多數設備來說,這很好 - 我可以使用OpenGL ES繪製半透明圖像,這確實會在我的其他原生視圖上覆蓋透明度。Android EGL疊加透明度問題,截圖和顯示區別

但是,在Nexus 10和Note 2(以及最有可能的其他設備)上,半透明像素在物理顯示屏上看起來不正確,即使通過DDMS採集的截圖看起來絕對正確!這讓我難以置信 - 視覺顯示如何與截圖看起來如此不同?

看起來奇怪發生在幀緩衝區中的alpha值不是1(0xff)或0(0x00)的任何像素。

我附加了Nexus 10的DDMS截圖,顯示的測試卡圖像完全如其應該的樣子。我還附加了一張來自顯示器的照片,顯示了非常不同的圖像......如上所述,看起來EGL疊加alpha值不是0x00或0xff的像素被錯誤地顯示。注2是相同的。

有誰知道如何解決這個問題?這是我們的主要障礙,因爲我們甚至不知道如何以編程方式確定設備顯示是否存在問題。

Nexus 10 display photograph, looks incorrect Nexus 10 DDMS screenshot, looks correct

回答

1

在Android半透明窗口預計含有的α預乘顏色。由窗口合成中使用的混合公式是:

dest.rgb = src.rgb + dest.rgb*(1 - src.a) 

有效預乘顏色總是已經color.rgb < = color.a。如果情況並非如此,則混合等式的結果可能大於1.0。在OpenGL ES中,如果您嘗試寫入大於1.0的顏色,它將被限制爲1.0(除非您正在渲染到浮點顏色緩衝區)。因此,在GL渲染中,或者當窗口合成器使用GL進行合成時,無效的預乘顏色往往不被注意。

但是,Android並不要求具有專門組合硬件(現在幾乎所有Android設備)的設備在混合溢出時鉗制到1.0。大多數設備都會進行鉗位,但Nexus 10中的Exynos 5250不會;它在8位定點執行混合數學運算,並在溢出(0xFF + 0x2 == 0x01)處進行包裝。如果Note 2中的Exynos 4412的行爲方式相同,這並不會讓我感到意外。

要解決這個問題,您需要在幀結尾的framebuffer中保留有效的預乘顏色。包括Android用戶界面框架在內的許多應用都通過確保任何非透明輸入(紋理,頂點顏色等)預乘 - 這些數學大多數在此之後自動完成。如果無法確保預乘輸入,則可以將

gl_FragColor.rgb *= gl_FragColor.a; 

添加到片段着色器的末尾。如果您進行混合,您需要調整您使用的混合方程/因子。