こんにちは、even_ekoです。
今まで、ずっと解決できていない課題は透明な線を描くことです。これを解決するために色々と実験したので、その結果を書いていきます。この記事での透明な線とは濃度が一定でアルファ値が1以下の線のことを指します。
問題点
問題点は、上にも書いたように透明な線が描けないことです。正確にいうと透明な線は描けます。ただ、透明な線を描こうと設定を変更すると他の機能に悪影響を及ぼしてしまいます。
具体的に、透明な線が描けないとはどういうことなのかを画像を用いて説明します。下の画像を見て下さい。
アルファ値を用いて、透明な線を実現しようと考えています。画像をよく見ると、丸いテクスチャが連続していることが分かると思います。このアルゴリズムではイベントで取得された座標の間を、直線で補間しテクスチャを貼付けています。テクスチャ自体にアルファ値を設定してあるので、重なったところは透明ではなくなっていきます。
重なったところがどんどん濃くなってしまうので、透明な線を実現することができません。
ブレンディング処理
OpenGLの処理の中に、ブレンディング処理というのがあります。この処理は、現在の値と書き込もうとしている値を演算させる処理です。ブレンディング処理はカラーバッファにのみ作用します。設定により、足し算させたり引き算させたりと様々な演算ができます。
ブレンディング処理の設定を変更させることで、透明な線を描くことには成功しました。
glBlendEquationOESという関数を用いて、透明な線を描くことができました。この関数は、ブレンディングの仕方を設定する関数です。初期設定では足し算するようになっています。テクスチャどうしが重なっても、透明度が変化しないようにすれば、透明な線は実現できます。上の画像では最大値をとるようにすることで、重なっても透明度が変わらないようにしています。
ただし、この方法では以下のような2つの問題があります。
- 重ね書きしても濃くならない
- 色によっては、描けない
これらの問題を解決する方法として、
- UIViewを重ねる
- オフスクリーンフレームバッファを使う
というアプローチを試してみます。
UIViewを重ねる
UIViewを重ねることで、描画する領域と保存しておく領域を分けることができます。これにより、透明な線が描けるうえに、重ね書きしても色が濃くならないことや特定の色では描けなくなるという問題を解決できます。
実際の画像が下になります。
これで、透明な線が描けるようになりました。
と、思いきやこの方法には問題がありました。それは、メモリです。
この方法では、UIView毎に各種バッファを持たせています。そのため、20回ほど描き込むと動作が重くなります。そして50回ほど描くと、とうとう描けなくなります。
考えついてる解決策としては、フレームバッファをまとめてUIViewの枚数を減らす方法です。しかし、他のUIviewにどうやってフレームバッファを持っていけばいいのか分からずに悩んでいます。