VGBlendModeがよく分からない

Blendの概念がよく分からなかったので、丁寧に計算したメモ。


Alpha compositing - WikipediaとOpenVG仕様書を参考に
Porter-Duffによるブレンドを行う。
よく分からないので、実際に適当に計算してみる。


前提条件
不透過の背景(dst)に半透過で色を重ねる(src)。
色は青の背景に黄色で色を重ねることにする。

→srcα = 0.5, dstα = 1.0
→srcC = (1, 1, 0), dstC = (0, 0, 1)

最初に、色に対してαを乗算しておく。
OpenVGの仕様書ではpremultiplyとかかれている。
(premultiplyしない方法も書かれている)
srcC' = (0.5, 0.5, 0), dstC' = (0, 0, 1)


1.VG_BLEND_SRC_OVER:

outαは以下の式で求められる。
1 * srcα + (1-srcα) * dstα = 0.5 + 0.5 = 1

Alpha合成を行う。
outC = 1 * srcC' + (1-srcα) * dstC'
= (0.5, 0.5, 0) + (0, 0, 0.5)
= (0.5, 0.5, 0.5)

複数合成の順序を変えても成り立つようにするため、最後にoutαで割る。
outC / outα = (0.5, 0.5, 0.5)

灰色になりました。


2. VG_BLEND_SRC_IN:

outαは以下の式で求められる。
dstα * srcα + 0 * dstα = 0.5 + 0 = 0.5

Alpha合成を行う。
outC = dstα * srcC' + 0 * dstC'
= (0.5, 0.5, 0) + (0, 0, 0)
= (0.5, 0.5, 0)

合成の順番を変えても成り立つようにするため、最後にoutαで割る。
outC / outα = (1.0, 1.0, 0)

黄色になりました。重ねた色そのものです。


3.VG_BLEND_MULTIPLY

outαは以下の式で求められる。(Src overと一緒)
1 * srcα + (1-srcα) * dstα = 0.5 + 0.5 = 1

outCは以下の式で求められる。
outC = srcC' * (1 - dstα) + dstC' * (1 - srcα) + srcC'*dstC'
= (0, 0, 0) + (0, 0, 0.5) + ( 0, 0, 0 ) // 第3項は内積
= (0, 0, 0.5)

暗い青になりました。乗算で暗くなる。


4.VG_BLEND_SCREEN

outαは以下の式で求められる。(Src overと一緒)
1 * srcα + (1-srcα) * dstα = 0.5 + 0.5 = 1

outCは以下の式で求められる。
outC = srcC' + dstC' - srcC'*dstC'
=(0.5, 0.5, 0) + (0, 0, 1) - (0, 0, 0)
=(0.5, 0.5, 1)

明るい青になりました。乗算の逆ですね。


5.VG_BLEND_DST_OVER

1の逆です。outαは以下の式で求められる。
(1-dstα) * srcα + 1 * dstα = 0 + 1 = 1

Alpha合成を行う。
outC = (1-dstα) * srcC' + 1 * dstC'
= (0, 0, 0) + (0, 0, 1)
= (0, 0, 1)

複数合成の順序を変えても成り立つようにするため、最後にoutαで割る。
outC / outα = (0, 0, 1)

やっぱり青です。


6.VG_BLEND_DARKEN/VG_BLEND_LIGHTEN

src overとdst overの暗い方/明るい方をとるとの事。
src over=(0.5, 0.5, 0.5)
dst over=(0, 0, 1)

ということで、
DARKEN=(0, 0, 0.5) 暗い青
LIGHTEN=(0.5, 0.5, 1)


7.VG_BLEND_ADDITIVE

単なる足し算です。1を超えたら1にします。

outα=min(srcα+dstα, 1)=min(1.5, 1)=1
outC=min(srcC'+dstC', 1)
=min((1.5, 1.5, 1), 1)
=(1, 1, 1)
最後にoutαで割りますが、結局白です。

画像で表示するとこんな感じ。
Imagination TechnologyのSDKを使用してます。