::: <<Prev(002) | List | Next(004)>>

Tips 003
空中アルファブレンディング

痒いところに手が届くとも思えない方法


空中アルファブレンディング?

ゲーム制作だとかをちょっとでもかじった事がある人なら、アルファブレンディングはご存じでしょう。 「半透明合成」と聞けば、あまり詳しくない方でも想像はつくとは思います。 要は、色ガラスやセロハンのような向こう側が透けて見えるものを描画するときに必要になるものです。

しかし、どこの解説サイトを見ても透ける事のない背景が存在し、その上に半透明画像を描画するという手順ばかりが紹介されています。 そこでちょっと半透明画像の上に半透明画像を描画したらどんな色になるのか気になり、立式・コーディングをしてみました。

で、このやり方をとりあえず一時的に空中アルファブレンディングと名付けさせていただきました。こらそこ、厨っぽいとか言わない!

立式してみよう

α画像1( X1, a1 )を合成した後、α画像2( X2, a2 )を合成する

各画像の色をX、α値をaとします。それぞれの色は (X, a) のベクトルで表せます。とりあえず普通に合成してみましょう。

まず、@の合成を行います。アルファブレンディングの公式は有名です。

a1X1 + (1 - a1)Xb

よって、@での合成で、 ( 0, a1X1 + (1 - a1)Xb )という色になります。

次に、この新しい背景色を使用してAの合成を行うと、合成結果の色はこうなります。

(0, a2X2 + (1 - a2)(a1X1 + (1 - a1)Xb)

さて、この値をちょっと変形します。

・・・ここ書くのめんどくさい(ぉぃぉぃ

これを、(0, a'X' + (1 - a')Xb)の形と見比べます。これは@の合成の式とほぼ一緒です。すると、以下のように求める値が定まります。

この式で良さそうです。

ソースコード

以上をふまえると、こんなコードになります。コードはC#ですが、適当に読み替えてください。

// Color構造体を使用する
using System.Drawing;

static class MidairBlend{
  public static Color Blend(Color colorUpper,Color colorLower ) {

    // 一時変数を利用してアクセス数を減らしている(つもり。効果のほどは知らない)
    int a, a1 = colorUpper.A, a2 = colorLower.A, a12 = a1 * 255, a22 = a2 * 255;
    a = a12 + a22 - a1 * a2;
    Color c = new Color();

    c.A = a / 255;
    c.R = (a12 * colorUpper.R + a22 * colorLower.R - a1 * a2 * colorLower.R) / a;
    c.G = (a12 * colorUpper.G + a22 * colorLower.G - a1 * a2 * colorLower.G) / a;
    c.B = (a12 * colorUpper.B + a22 * colorLower.B - a1 * a2 * colorLower.B) / a;

    return c;
  }
}

こんな感じです。割り算が入ってくるところがちょっとスマートではありませんが、仕方ないでしょう。

ちなみに、C#(というか、.NET Framework)の色構造体である Color 型は、ARGB各成分が0〜255の値をとるため、所々に255という数字が出現しています。

で?

実用的価値は……。断言します。ありません!

こんな事前ブレンドは、ほとんど利用価値はないでしょう。描画順を調節してDirectXなり何なりに任せた方がいいです。あるとすれば、せいぜいペイントソフトの半透明レイヤーとか?

あと、なんか途中から数式とかすっごく見づらくなってますが、仕様とさせていただきます。

この記事にコメントをする

::: <<Prev(002) | List | Next(004)>>