ブレンドについて


blendFunc

今回作った空では、背景、雲、マスク、太陽、の4枚の画像を重ねています。
それぞれの画像の重なり方は下図のとおりです。

no image

実際の描画の際には、一番後ろの画像から順にブレンド処理されていきます。
この例の場合では

(背景+雲)→ +マスク → +太陽

の順で処理されます。
背景と太陽の順番は固定されていて変えることはできませんが
雲とマスクの順序はシェーダーの記述の仕方で変えることができます。
ブロック{ ・・・ }の記述の順序を入れ替えるだけです。

ブレンド処理を制御しているのは blendFunc という命令です。
blendFunc の詳細については Q3Map2マニュアルの blendFunc の項を読んで下さい。
マニュアルでは、下にある画像(先に処理された結果)を destination
その上にのせる画像を source と表現しています。
blendFuncは一般的には

blendFunc sourceパラメータ destinationパラメータ

という形をしています。
省略形として、blendFunc add, blendFunc blend, blendFunc filter などの表現が使われることもあります。

背景+雲

雲には blendFunc の記述がありません。
したがって背景画像の上に雲画像がそのまま上書きされます。

マスク

マスクには blendFunc blend を指定しています。
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA と指定しても同じです。

これはαチャンネルの情報を使って画像を透過させる最も一般的な方法で、αチャンネルの情報は先の画像(destination)と新たに上乗せする画像(source)との合成比率を決定します。
式で書くと

合成結果=source.color×α + destination.color×(1−α)

となります。
例えば、α=1ならばdestination情報は消え、sourceの情報で上書きされます。
実際はα=1でも完全な上書きにはならず、先の画像が薄く見える状態になりますが。
α=0.5ならば、destination と source が半々でブレンドされます。

太陽

太陽には blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_COLOR を指定しています。
式で書くと

合成結果=source.color×α + destination.color×(1−source.color)

となります。
何やらサッパリわかりませんが..

実際、blend指定を使った場合と比較してみると blend指定だと太陽に雲が重なったときに(雲の明るさがプラスされて)太陽が明るく輝いてしまいますが、この指定をするとそういうことはなくなります。

本当は雲がかぶさると暗くなるようにしたかったのですが、それを実現するためには別の方法を考えないといけないでしょう。

Villageの空の場合

Village の背景とマスクの合成方法には blend GL_ONE GL_ONE を指定しています。
式で書くと

合成結果=source.color×1 + destination.color×1

となります。
単純な足し算ですね。
αチャンネルの情報は使われません(つまりαはなくても良い)。
blendFunc add を指定しても同じ結果が得られます。
合成された画像は(当然だけど)かなり明るくなります。

普通のテクスチャの場合

空や蛍光灯などのそれ自身がライトではない
いわゆる普通のテクスチャはライトマップ画像とのブレンドが行われます。
ライトマップ画像とは陰影情報のみを持った画像で q3map2 を -light オプションをつけてコンパイルすると作成されます。

この場合のブレンドパラメータには
GL_DST_COLOR GL_ZERO または GL_ZERO GL_SRC_COLOR を指定します。
式で書くと

合成結果=source.color×destination.color

となります。
単純な掛け算ですね。合成された画像は当然暗くなります。
blendFunc filter を指定しても同じ結果が得られます。

たとえばカスタムテクスチャのページで作ったキンチョウの看板のシェーダーを見てみると

textures/test/kincho { qer_editorimage textures/test/test_kincho.jpg surfaceparm metalsteps { map $lightmap // ライトマップ画像 rgbGen identity } { map textures/test/test_kincho.jpg blendFunc GL_DST_COLOR GL_ZERO // filterブレンド指定 rgbGen identity } }

map $lightmap はライトマップ画像の呼び出しです。
確かに blendFunc が使われてますね。
この処理をすることで、ブラシ表面に張られたテクスチャに陰影がつくわけです。

ブレンドパラメーターの指定はとても頭が痛い話で、マニュアルを読んで理屈を理解できてもいまいち結果をイメージをしづらいものがあります。重なる順序を変えたり、パラメータを試行錯誤しながら実際にやってみるしかないでしょう。