Last-modified: Thu, 05 May 2016 13:13:40 JST
Counter:15760 Today:1 Yesterday:0 Online:7
このエントリーをはてなブックマークに追加

(注意) 記事を引っ越しました

AlphaBlendingの計算

About

 ほとんどメモ書きですが、ペイントソフトやCGゲームで扱われている様な、透過度を考慮した色の合成(アルファブレンディング)はどのように計算されているのか確認してみました。ゲームやCGと、ペイントソフトやDTPソフトとで算出方法が異なるんです。※環境によって計算方法は異なるので必ず正しい解ではありませんが、凡そ一般的だと思います。

計算方法の解説とその算出に当たって

 ゲームやCGプログラミングなどではRGBA値が0~1で扱われることがありますが、ここでは分かりやすさのために0~255とします。ただしAに関しては計算の都合上0~1の値へ戻してしまいます。よってAの値が0~255で与えられるとき、Aの値は「A/255」で求めることができます。A=0の時、完全に透過して、A=1の時に不透明です。

 計算とその表記にあたって次のことを定義しておきます。

  • C:(R,G,B)色成分をまとめて表す(Colorの略称)
  • A:透過値を表す(Alphaの略称)
    • 係数d:合成される色のパラメータであることを表す(Destinationの略称)
    • 係数s:合成する色のパラメータであることを表す(Sourceの略称)
    • 係数r:合成結果のパラメータであることを表す(Resultの略称)

例えば

  • 「Cr」は合成して得られた結果の(R,G,B)色成分を表します
  • 「Cd * 1」は「(Rd,Gd,Bd)*1」となり「(Rd*1,Gd*1,Bd*1)」となります

ゲームなどで用いられる手法(DirectX・XNAなど)

0.png

 ゲームなどで用いられるアルファブレンディングの計算式は一般的には次の様になっています。

Cr = Cd * (1 - As) + Cs * As

 上の図の様な、【赤】(Rd,Gd,Bd,Ad)=(255,0,0,255) + 【青】(Rs,Gs,Bs,As,)=(0,0,255,128)のアルファブレンディングは次の様に求められます。

Ad = 255/255 = 1 , As = 128/255 ≒ 0.5
Cd(255,0,0) * (1 - As) + Cs(0,0,255) * As
= (127,0,0) + (0,0,127) = (127,0,127,255)

 算出したは良いものの、Adの値が一切使われていない点に注意してください。DirectXやXNAなどのゲーム開発環境下で用いられる一般的なαブレンドは、描画元の色成分(d)に含まれるA(透過)値を考慮しません。また合成した結果得られる色のA値(Ar)は必ず1=255になります。所が例えばPowetPointやPhotoshopなどのペイントソフト等では、算出方法が異なり描画元の色成分(d)に含まれるA値を考慮します。これに関しては次の項目で解説します。

ペイントツールなどで用いられる手法

1.png

 ペイントツールなどでアルファブレンディングが行われる場合は、先に紹介した算出方法と異なります。2つの透過値をもった色が与えられる場合に、先の方法とは異なる結果を示すことに注意してください。図の左は"赤"の上に"青"が、図の右は"青"の上に"赤"が乗る形で合成されています。"赤"が70%透過(A=77)、"青"が50%透過(A=128)と、異なるA値を持っています。また中央の透過度は共通して65%(A=166,0.65)です。

 ペイントツールなどで用いられるアルファブレンディングの計算式は一般的には次の様になっています。

Ar = As + (1-As) * Ad,
Cr = ( (Cs * As) + (Cd * (1 - As) * Ad) ) / Ar

 上の図の様なパターンは次の様に計算されます。

Ad = 77/255 ≒ 0.3, As = 128/255 ≒ 0.5
Ar = 0.5 + (1 - 0.5) * 0.3 = 0.65
Cr = ( (0,0,255) * 0.5 + (255,0,0) * 0.5 * 0.3 ) / 0.65
= ( (0,0,128) + (38,0,0) ) / 0.65 = (58,0,197)
※(Rr,Gr,Br,Ar) = (58,0,197,0.65*255) = (58,0,197,166)

 この算出方法によって、先の「ゲームでの場合」と同じパターンを計算しても、合成結果が変わらないことも分かります。つまり描画元の色(d)のA値を考慮しないパターンでは、どちらの算出方法であっても結果が変わらないということです。

Ar = 0.5 + (1-0.5) * 1
Cr = ( (0,0,255) * 0.5 + (255,0,0) * 0.5 * 1) / 1
= (127,0,127,255)

考察

 ゲームなどで用いられる手法の方が、若干ながら計算コストが低いです(乗算除算の回数が異なりますから)。リアルタイムに計算しなければならない都合上、多少簡略化した方が都合がよいのでしょう。ゲームでは特にレンダリングする順序を考慮して実装するので、合成した結果のA値が1=255になる都合とA値を考慮しない合成はさして問題にならないハズです。逆に言うと、こういう知識を持っていなければ「透過しているはずなのに透過していない」となってしまうわけですが…。

References