閉じる

AlphaBlendによる透過

描画に使うのは GUID_WICPixelFormat32bppBGRAとして認識される透過情報付き PNGファイル。
これを WICを使って読み込んだ。
素直に AlphaBlend APIを使って描画を行うと…なんだか変だね?

調べてみると、以下のような記事にあたる。

書き殴り雑記
AlphaBlend API では foreground(Src) にアルファ係数を掛けやがらない仕様のようなんです。何故かは分かりません。信念でしょうか?宗教でしょうか?ただの馬鹿なんでしょうか?

確かに BLENDFUNCTION structureを見ると件の記事の通りの動作であることが書いてある。

試しに期待される合成方法を手動で書いてみると期待通りの結果が得られるのでデータ自体は間違っていない。

では手動で書いたのを採用するか?否。

DirectXを触ったことがあると、「透過情報が適用済みのフォーマット」というのを聞いたことがあるはず。
そう、転送元のデータに対する透過情報の処理ってのは転送毎に行う必然性って無いんだよね。
「事前に行えることは事前に行う」ってのは最適化の基本であり、空間的デメリットを伴わないなら適用を迷うことはない。
というわけで、WICに読み込んだデータに対して、事前に透過情報を反映してやることで AlphaBlendが期待通りに動作するようになった。

2973-0.cpp
for(...){
for(...){
Pixel->rgbBlue=Pixel->rgbBlue*Pixel->rgbReserved/255;
Pixel->rgbGreen=Pixel->rgbGreen*Pixel->rgbReserved/255;
Pixel->rgbRed=Pixel->rgbRed*Pixel->rgbReserved/255;
}
}

BLENDFUNCTION blend;
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags=0;
blend.SourceConstantAlpha = 0xff;
blend.AlphaFormat = AC_SRC_ALPHA;
AlphaBlend(...);

まぁ そういうことなんでしょう。

ちなみに BLENDFUNCTION structureのCommunity Content欄には2010/09/19の日付で以下のような投稿がある。

Why premultiplication is a good idea

There is a good reason why it uses premultiplied alpha. It is just not efficient to multiply the source color by the source alpha every time for every pixel. It has to be done only once, since the color and alpha values are correlated. It is usually done during the creation of the image (PNG, for instance, uses premultiplied alpha), and will save a very costly multiplication for every pixel for every draw.

要は「ソース色に対する透過率の演算を転送毎に行うのは馬鹿にならないリソースを食うので、事前に一度だけ行った方が良いよ。」という事。

AlphaBlendによる透過」への1件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。必須項目には印がついています *

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)