OpenGL でデュアルソースブレンディングを使うと、出力先カラーバッファが1つになってしまう!という話を聞いて、「1つのカラーバッファに2色出力し、ブレンド設定でさらに演算」という場面ってどのくらいあるのだろうと疑問に思いました。(おそらくデスティネーション色と処理したいのでしょうが)。
そんな中、Multiple Render Target (MRT)で、各カラーバッファのブレンディング設定は独立に出来たはず、と思うことがあったので使い方を確認してみました。
ちなみに、DirectX11 ではカラーバッファのブレンディング設定の独立(個別)は簡単にできます。D3D11_BLEND_DESC構造体を見るとすぐに分かります。
結果としては、 OpenGL でもこのようにブレンディング設定を変えて描画できます。
前提条件
FBO でカラーバッファとして2つのテクスチャを描画先として設定します。
忘れがちなのですが、 FBO をバインドして使用する際には、glDrawBuffers 関数で、出力先をセットします。
// MRT を有効化. glBindFramebuffer(GL_FRAMEBUFFER, gRenderTarget.fbo); GLuint buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; glDrawBuffers(_countof(buffers), buffers);
フラグメントシェーダーの方も色の出力に関してセットしておくのを忘れないようにします。
layout 修飾設定をしておくか、 glBindFragDataLocation 関数で出力先バッファのインデックス値を設定しておきます。
MRT描画について
各ターゲットごとに独立なブレンディング設定にあたり、各カラーバッファのクリア色も変更したいと思います。
それには次のようにします。このとき、glClear を呼び出してしまうと、全カラーバッファに対して glClearColor で指定した色でクリアとなってしまいます。
// 各ターゲットごとにクリア色を変える. float clearColor1[] = { 0.30f, 0.6f, 1.0f, 0.0f }; float clearColor2[] = { 0.5f, 0.5f, 0.5f, 0.0f }; glClearBufferfv(GL_COLOR, 0, clearColor1); glClearBufferfv(GL_COLOR, 1, clearColor2); // デプスの場合. float clearDepth[] = { 1.0f }; glClearBufferfv(GL_DEPTH, 0, clearDepth);
ブレンディング設定を各ターゲットごとに変更するには次のようにします。
多くの場合ではブレンドの設定で glEnable や glBlendFuncSeparate を使っていたと思いますが、バッファのインデックスを指定できる glEnablei や glBlendFuncSeparatei を使用します。
// 各ターゲットごとのブレンディング設定を変える. glEnablei(GL_BLEND, 0); glEnablei(GL_BLEND, 1); glBlendFuncSeparatei(0, GL_ONE, GL_ZERO, GL_ONE, GL_ZERO); glBlendFuncSeparatei(1, GL_ONE, GL_SRC_COLOR, GL_ONE, GL_ZERO);
このようにして描画させてみたものがこのようになります。カラーバッファ2つとデプスバッファを確認用に表示させています。
まとめ・その他
OpenGL で Multiple Render Target を使い出したときに、ブレンディング設定を触ったときに関わってきそうな話題をやってみました。知ってさえいれば難しいポイントは何もないのですが、知らない場合には少し手間取るように思いました。
今回は glClearBuffer を使用しましたが、テクスチャが描画先となるので glClearTexImage も使えます。この場合には、直接テクスチャを指定出来るので、使用感としては DirectX11 に近くなる印象があります。
最初の話であったデュアルソースブレンディングについては、描画先からピクセル値を読み取ってシェーダー内で処理できれば、描画先1つの制約から逃れられる気がします。確か OpenGL に shader framebuffer fetch というキーワードで引っかかりそうな拡張が用意されていた気がするので、使えるかどうかそのうち実験してみたいと思います。
⇒この拡張はモバイル系のもののようで、デスクトップ機ではサポートが無いようですね。