0

私のアプリは、8888 形式のフルスクリーン glSurface オーバーレイを使用しています。ほとんどのデバイスでは、これで問題なく動作します。OpenGL ES を使用して半透明の画像を描画できます。これは実際に、他のネイティブ ビューの上に透明でオーバーレイされます。

ただし、Nexus 10 および Note 2 (およびおそらくその他のデバイス) では、DDMS で撮影したスクリーンショットは完全に正しく見えますが、半透明のピクセルは物理ディスプレイでは正しく見えません! これは私を困惑させました - 視覚的な表示がスクリーンショットとどう違うのでしょうか?

フレームバッファ内のアルファ値が 1 (0xff) または 0 (0x00) 以外のピクセルの場合、異常が発生するようです。

Nexus 10 の DDMS スクリーンショットを添付しました。テストカードの画像が正確に表示されているはずです。非常に異なる画像を示すディスプレイからの写真も添付しました...説明したように、EGL オーバーレイ アルファ値が 0x00 または 0xff ではないピクセルが正しく表示されていないようです。注 2 も同様です。

この問題を解決する方法を知っている人はいますか? デバイスのディスプレイに問題があるかどうかをプログラムで判断する方法さえわからないため、これは私たちにとって大きな障害です。

Nexus 10 ディスプレイの写真が正しくないように見える Nexus 10 DDMS スクリーンショット、正しいように見える

4

1 に答える 1

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 が同じように動作しても驚かないでしょう。

これを修正するには、フレームの最後にあるフレーム バッファに、事前に乗算された有効な色が必要です。Android UI フレームワークを含む多くのアプリは、不透明でない入力 (テクスチャ、頂点カラーなど) が事前に乗算されるようにすることでこれを行います。その後、ほとんどの計算は自動的に行われます。事前に乗算された入力を確保できない場合は、追加するだけです

gl_FragColor.rgb *= gl_FragColor.a;

フラグメントシェーダーの最後まで。ブレンドを行う場合は、使用するブレンド方程式/係数を調整する必要があります。

于 2014-03-28T03:27:17.050 に答える