透明ピクセルに注意してください

画像






ゲームで透明度のあるスプライトを使用する場合(少なくともUIで通常発生します)、おそらく完全に透明なテクスチャピクセル(または「テクセル」)に注意する必要があります。



アルファチャネル値が0であっても、色値はピクセルに関連付けられたままです。 この色は何にも影響しませんよね? 最終的に、ピクセルは完全に透明になり、その色を気にします...



したがって、実際、この色は重要です。これを理解しないと、多くのゲームで目立つアーティファクトを取得できます。 ほとんどの場合、歪みは非常に小さく目立ちませんが、時には非常に印象的です。



歪みの例



実生活から例を挙げましょう! PS3(メインメニュー)のXMBと 、いくつかのゲームのデモがあります。



Limboが最初に選択され、次に上に押すと、未完成のSawnに移動します

(ところで、両方のゲームは素晴らしいです)。



画像

スタート。



画像

押し下げます。 リンボがダウンします。



画像

背景が白に変わります。



画像

アーティファクト。



Limboのロゴエリアに何が起こったのかをご覧ください。



背景がThe Unfinished Swanの白い背景に変わり、その結果、「完全に白い」 Limboロゴが背景の上に描かれ、これも完全に白いです。 この領域は完全に白いはずですが、これらの奇妙な灰色のピクセルはどこから来たのでしょうか?



最も可能性が高いのは、 Limboテクスチャが完全に透明なピクセルに間違ったRGBカラーを使用しているという事実が原因で発生した歪みです。



テクスチャフィルタリング



実際に、アーティファクトは、画面にスプライトをレンダリングするときにビデオプロセッサがテクスチャをフィルタリングする方法から発生します。 彼の作品を簡単な例で見てみましょう。



これは、12x12の赤い十字の小さなピクセルテクスチャです。







これが彼の拡大画像です。チェスセルは、これがアルファチャネル値が0の完全に透明な領域であることを示しています。



このスプライトは、UIヘルスに表示するアイコンとして、または応急処置キットのゲームモデルのテクスチャとして使用できます。 (そうではありません!実際、これはそれだけの価値はありません!



アルファ透明度がゼロのピクセルのカラー値を変更するだけで、このスプライトの3つのバージョンを作成しましょう。



画像

透明領域:緑。 画像は次のようになります:



画像

透明領域:青。 画像は次のようになります:



画像

透明領域:赤。 画像は次のようになります:



(ファイルをダウンロードして、透明ピクセルのRGB値を確認できます)



これらの3つのスプライトは、画面上でまったく同じに見えますか? これは論理的です。透明ピクセルの色の値を変更しただけで、透明ピクセルは表示されません。



しかし、これらのスプライトが動いているときに何が起こるか見てみましょう。 画面のピクセルをよく見るための大きな画像を次に示します。



画像



ここで歪みが見られます! 最初のスプライトに茶色、2番目に紫色。 三番目は大丈夫です、それはそれがどのように見えるべきかです。



青いバージョンを見てみましょう。



画像



ご覧のとおり、テクスチャの位置がピクセル単位のスクリーンピクセルに対応していない場合に問題が発生します。 これは、画面にスプライトをレンダリングするときにビデオプロセッサが実行するバイリニアフィルタリングによって説明できます。テクスチャをサンプリングするとき、ビデオプロセッサは、最も近い隣接ピクセルの色値を、要求された垂直および水平方向の座標で平均します。



スプライトの位置がピクセルのちょうど半分と一致しない場合を考えてみましょう。



画像



各画面ピクセルは、2つのテクセル間でスプライトテクスチャを正確にサンプリングします。 これは、画像に表示されるピクセルで起こることとまったく同じです。つまり、固体の赤いテクセルと透明な青いテクセルの中間にあるスプライトテクスチャを選択します。 平均色は次のとおりです。

$$表示$$ 0.5 \ ast \ begin {bmatrix} \ color {#ff2c2c} 1 \\ \ color {#00c300} 0 \\ \ color {#2f9fff} 0 \\ 1 \\ \ end {bmatrix} + 0.5 \ ast \ begin {bmatrix} \ color {#ff2c2c} 0 \\ \ color {#00c300} 0 \\ \ color {#2f9fff} 1 \\ 0 \\ \ end {bmatrix} = \ begin {bmatrix } \ color {#ff2c2c} {0.5} \\ \ color {#00c300} 0 \\ \ color {#2f9fff} {0.5} \\ 0.5 \\ \ end {bmatrix} $$ display $ $





これは部分的に透明な紫色で、次のようなものです:



テクスチャサンプラーによって返されるこの色は、レンダリング結果のアルファチャネルに混ざります(白一色)。



混合方程式の形式は次のとおりです。

 alphabackground astRGBsprite+1 alphasprite astRGBbackground





$$表示$$ = 0.5 \ ast \ begin {bmatrix} \ color {#ff2c2c} {0,5} \\ \ color {#00c300} 0 \\ \ color {#2f9fff} {0,5} \ \ \ end {bmatrix} +(1-0.5)\ ast \ begin {bmatrix} \ color {#ff2c2c} 1 \\ \ color {#00c300} 1 \\ \ color {#2f9fff} 1 \\ \ end {bmatrix} = \ begin {bmatrix} \ color {#ff2c2c} {0.75} \\ \ color {#00c300} {0.5} \\ \ color {#2f9fff} {0.75} \\ \ end {bmatrix} $$ディスプレイ$$





したがって、画面上のピクセルの最終的な色は次のようになります:



これは私たちには合いません。 正しい結果(透明ピクセルが赤のときに得られた)は次のようになります。



$$ display $$ \ begin {bmatrix} \ color {#ff2c2c} {1} \\ \ color {#00c300} 0 \\ \ color {#2f9fff} {0} \\ 0.5 \\ \ end {bmatrix } $$表示$$





双線形補間された値で、その後混合されて取得されます

$$ display $$ \ begin {bmatrix} \ color {#ff2c2c} {1} \\ \ color {#00c300} {0,5} \\ \ color {#2f9fff} {0,5} \\ \ end { bmatrix} $$表示$$





画面上のピクセルは次のようになります:



これらの不快なアーティファクトをどのように回避しますか?



この問題を回避する方法



あなたがアーティストの場合:すべてを漏らします!



グラフィックリソースを作成する責任がある場合は、作業を保護し、プログラマとエンジンを信頼しないでください。



コンベアのある段階で、透明ピクセルの色が周囲のグラフィックに「漏れる」可能性が非常に高くなります。 テクスチャのバイリニアフィルタリングでこれがどのように発生するかは既に見てきましたが、MIPテクスチャの生成でも発生する可能性があります...



あなたはそのような花の浸透に対処することができます... 余分な浸透



画像

ソーススプライト



画像

RGBのみ



これにより、グラフィックをディスクにエクスポートする前に、まずすべての不透明ピクセルが隣接する透明ピクセルのRGB値に「漏れる」ことを確認する必要があります(これはフラッドフィリングまたはエッジパディングとも呼ばれます )。 この場合、ゲーム中に透明ピクセルが不透明な隣接ピクセルに漏れると、少なくとも正しい色で漏れます。



上の画像は、実際の世界の例です。GTAVから抽出された植物のスプライトのアトラスで、アルファチャネルがある場合とない場合があります。



ゼロ以外の透明度を持つピクセルの周囲の境界に注意してください。透明なピクセルは、最も近い目に見える隣の色を借ります。 ロックスターは偶然このすべての仕事をしませんでした。



このプロセスではツールが役立ちます。PhotoshopにSolidifyプラグインがあり

Gimp用のプラグインもあります ...



また、PNGを保存するときなど、透明ピクセルのRGB値をエクスポートするときは注意してください。多くのプログラムは、デフォルトで透明ピクセルのRGBデータを破棄し、エクスポート時に圧縮を改善するために単色(白または黒)に置き換えます。



プログラマーの場合:Premultiplied Alphaを使用してください!



プログラマーであれば、アーティストが作成したグラフィックリソースを盲目的に信頼するべきではないことを既に知っています。 幸いなことに、プログラマーにはこの問題に対処するためのオプションがたくさんあります。



このツールを使用して、色の漏れを自動化できます。これについては、前に説明しました。 リソースをインポートするときに使用する必要があります。 しかし、はるかに優れた信頼性の高いソリューションがあります。事前乗算されたアルファです。



他の人がここここなど良い説明を書いているので、私はそれについて詳しく語りません。



また、Tom Forsythの投稿(このトピックに関する12)を強くお勧めします。



アイデアは非常に単純です:テクスチャを次のように保存する代わりに

$$表示$$ \ begin {bmatrix} \ color {#ff2c2c} {R} \\ \ color {#00c300} G \\ \ color {#2f9fff} {B} \\ \ alpha \\ \ end {bmatrix} $$ディスプレイ$$





として保存する必要があります

$$表示$$ \ begin {bmatrix} \ alpha \ ast \ color {#ff2c2c} {R} \\ \ alpha \ ast \ color {#00c300} {G} \\ \ alpha \ ast \ color {#2f9fff} {B} \\ \ alpha \\ \ end {bmatrix} $$表示$$





RGBコンポーネントには、ピクセルのアルファ透明度値が乗算されます。 元の色は、値をアルファ透明度で除算することで簡単に取得できます。



したがって、スプライトを有効にできます。



画像

オリジナル



画像

事前乗算されたアルファ



テクスチャに最初の乗算の結果が含まれるようになり、アルファ透明度の値を再度乗算する必要がないため、混合方程式を変更する必要もあります。

RGBsprite+1 alphasprite astRGBbackground





OpenGLでは、これはミックス機能に対する次の変更に変換されます。



glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)



glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)







赤い十字を半ピクセルずらしてスプライトに戻りましょう。 Premultiplied Alphaモードの場合、双線形補間器は次の間の平均を探します。

$$ display $$ \ begin {bmatrix} \ color {#ff2c2c} {1} \\ \ color {#00c300} 0 \\ \ color {#2f9fff} {0} \\ 1 \\ \ end {bmatrix}および\ begin {bmatrix} \ color {#ff2c2c} {0} \\ \ color {#00c300} 0 \\ \ color {#2f9fff} {0} \\ 0 \\ \ end {bmatrix}、\; return \ begin {bmatrix} \ color {#ff2c2c} {0.5} \\ \ color {#00c300} 0 \\ \ color {#2f9fff} {0} \\ 0.5 \\ \ end {bmatrix} = \カラー{#7f0000}█\; \; ミキシング、\; \; 次に\; \ begin {bmatrix} \ color {#ff2c2c} {1} \\ \ color {#00c300} 0.5 \\ \ color {#2f9fff} {0.5} \\ \ end {bmatrix} = \ color {# ff7f7f}█$$ディスプレイ$$





これは、すべての問題を正しく、かなりよく解決します! 最終的な結果は、すべてのアーティファクトを削除したことを除いて、「伝統的なミキシング」で期待されるものとまったく同じです。 あらかじめ乗算されたアルファを使用する場合、完全に透明なピクセルのRGB値は常に黒であるため、スプライトの透明な領域に実際にあるものを心配する必要はありません。 あらかじめ乗算されたアルファは、MIPテクスチャのチェーンを生成し、いくつかの半透明のスプライトを上下に重ねるときに頭痛を避けます。



まとめると



元のトピックに戻ります: Limboロゴの問題は、RGB透明ピクセルのゴミによって本当に引き起こされたのですか?



調べる方法は1つしかないため、デモパッケージ/PS3_GAME/ICON0.PNG



からPNGファイルを抽出し/PS3_GAME/ICON0.PNG







一見、画像はきれいに見えますが、完全なRGB値をレンダリングするためにアルファチャネルを削除しましょう。



画像

オリジナル



画像

RGBのみ



そのため、文字「B」と「O」には、純色の白い色の代わりに、「漏れる」不適切なRGB値が含まれており、前に見たグラフィックバグが発生します。



これらのアーティファクトの問題は、検出が難しいことです。 Limboのロゴは、白い背景にレンダリングされるまで奇妙なことに気付きませんでした。 誰もがこの問題について知っているわけではないので、このトピックに精通していると役立ちます。



あなたが芸術家であるなら、あなたは最初の防衛線であり、透明なピクセルの内側にある色に注意を払ってください。 プログラマーである場合は、事前乗算されたアルファの使用を検討してください。



All Articles