9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

半透明の要素を描いたFBOを描画する際のハマりポイント

Last updated at Posted at 2018-08-31

TL;DR

不透明ピクセルに半透明ピクセルをアルファブレンディングした結果は半透明だから気をつけような!

現象

  1. FBOを背景色(不透明)でクリアする
  2. FBOに半透明の要素を描画する
  3. FBOをウィンドウに描画する
  4. ウィンドウ背景色が透過して見える

例:黒でクリアしたFBOに白い半透明の矩形を描き、赤背景のウィンドウに描画した結果
スクリーンショット 2018-08-31 11.49.00.png

何が問題なのか・どうなってほしいのか

FBOの背景色が不透明なのに、ウィンドウ背景色が見えているのが問題
ウィンドウ背景が透けてほしくない

例:こうなってほしい
スクリーンショット 2018-08-31 14.18.35.png

原因

__不透明要素の上に半透明要素をアルファブレンディングした結果が半透明__であること。
つまり__FBO内の半透明要素を描画した領域のアルファ値は1より小さくなる__こと。

アルファブレンディングの計算式(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)の場合)

out = src\cdot src_a+dst\cdot (1-src_a)\\
(src: 描画色, dst: 背景色, out: 結果)

アルファ値のみに着目すると

out_a = src_a\cdot src_a+dst_a\cdot (1-src_a)\\

つまり$dst_a$が1(背景が不透明)の場合、

out_a = src_a^2-src_a+1 \qquad (dst_a=1)\\
\therefore \left\{
\begin{array}{ll}
out_a \lt1 & (0\lt src_a\lt 1) \\
out_a = 1 & (src_a=\{0,1\})
\end{array}
\right.

となり、半透明要素を描画するとその結果が半透明となることがわかる。

ちなみに以下は背景色と描画色とから結果のアルファ値がわかるグラフ
https://www.desmos.com/calculator/azbx3o4tn9

対処

対処1 : アルファ値の計算に別の式を使う(OpenGL)

FBOに半透明要素を書き込む際に以下のどちらかを指定しておく。
不透明背景に描く場合はどちらでも結果は1になるので変わらない。

glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_SRC_ALPHA,GL_ONE);

glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_ONE,GL_ONE);

参考:
ofFbo上でのアルファブレンディング - ofxTips-JP
Alpha Blending の2種類の算出方法と使い分け – NEAREAL

対処2 : FBOをブレンディングなしで描画する

FBOの背面に何も描画しない場合はこちらがシンプル。

glDisable(GL_BLEND);
fbo.draw();
9
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?