やっと基礎の描画アルゴリズムとSIMDを使ったルーチンの一次変更が完了しました。
後は速度を見ながら最適化を行えば前よりはかなりよくなったコードができるな~という感じです。
で、題名の件です。時々検索したくなる人もいると思いますのでちょっと書いてみます。
今時のグラフィックカードなら3Dのレンダリングを行えば勝手にやってくれる系のルーチンでもありますが、アドベンチャー系などでは自前で実装する必要が最も大きいルーチンでもあります。
まずは基本式から。レイヤーの合成なので、下側のレイヤーと上側のレイヤーは両方とも透過率を保持しているものと仮定します。
また、描画順序は下側から上側に向かって描画されていく時を考えます。上側から描画する場合はエネルギーの分配法を用いて計算しますが、
ゲームなどでは下から上に描画するパターンがほとんどだと思います。
基本式はこんな感じです。下側のレイヤーをsrc,上側のレイヤーをdstとして結果レイヤーをresとして計算します。
csはsrcの色成分、saはsrcの透過率(0.0~1.0、0.0が透明)、cdはdstの色成分、daはdstの透過率、cはresの色成分、caはresの透過率とします。
ca = sa + (da * (1 – sa))
c = (cs * (sa * (1 – da)) + cd * da) / ca
なお、描画ルーチンによっては上側のレイヤーをsrcとして描画を繰り返していくという場合もありますので、その場合はsrcとdstを逆にして下さい。
色成分はレイヤーの各色成分(RGBならR,G,Bそれぞれ、YUVならY,U,Vそれぞれという意味)すべてに演算を行います。
また、ca = 0になるとき(= sa = da = 0)は、下の式は0除算となり計算できませんが、その意味からcの値は色成分の範囲ならどんな値でも
次の演算には影響しないので適当に値を決めることができます。通常はc = cs、c = cd、c = 0のいずれかを使うと思います。
このルーチンですが、SIMD演算を使ったり、高速化を図る上でかなりじゃまな計算が含まれています。
それはcaでの除算です。除算は一般的にかなり遅い演算(整数でも浮動小数でも)であり、
かつSIMDの整数演算には除算がありません。(0除算での例外の問題のためと思われる。浮動小数なら無限大を使えるので命令はある)
そのため、この処理を行うためにいろいろと工夫を行う必要があります。それについては次回考えてみましょう。