mieki256's diary



2022/09/23(金) [n年前の日記]

#1 [python] OpenGLのGL_ALPHA_TESTについて動作を調べてた

Python + PyOpenGL を使ってOpenGLを勉強しているところ。ポリゴンに貼ったテクスチャ画像の透明部分について、妙な描画結果になることに気づいてしまって、そのあたりを少し調べてた。

環境は、Windows10 x64 21H2 + Python 3.9.13 + PyOpenGL 3.1.6。GPU/ビデオカードは、NVIDIA GeForce GTX 1060 6GB。

実験に使った画像は以下。
img_rgba2.png
_img_rgba2.png

実験に使ったソースは以下。

_06_draw_billboard_alpha_test_2.py

さて。アルファチャンネルを持ったテクスチャ画像をそのまま描画すると、以下のように、アレな見た目になってしまう。画面の右側は期待していた見た目になっているけれど、左側は、透明になってほしい部分の後ろにあるはずの色がちゃんと出てこない…。

ss_06_draw_billboard_alpha_test_2_01.png

ボールの向こう側にもボールがあるのだから、本来、透明部分には、奥側にあるボールの赤い色がそのまま出てほしいわけだけど…。実際は奥側のボールを素通りして、背景相当の緑の床が表示されてしまっている。

これはデプスバッファを使って描画する際に起きてしまう問題で、「一番手前にあるポリゴンの色だけをそこに描画すれば隠面消去ってできるよね」という考え方で描画するものだから、その奥にあるポリゴンの色は無視されて、こんな状態になってしまう、らしい。

左側では、まず、一番手前のポリゴンを描画して、そのポリゴンの奥行き情報がデプスバッファに書き込まれる。その後、奥にあるポリゴンを描画しようとしても、デプスバッファには一番手前のポリゴンの奥行き情報が既に書き込まれているので、「今から描こうとしてるポリゴンより手前になる奥行き情報がデプスバッファに書き込まれてるな。じゃあ、ここにはもう描かなくてええやろ」と無視されてしまうのだと思う。

GL_ALPHA_TEST を有効にすると、多少は改善されるけど。しかし、これもまだまだ問題が…。
        glEnable(GL_ALPHA_TEST)
        glAlphaFunc(GL_GREATER, 0.1)

ss_06_draw_billboard_alpha_test_2_02.png

この場合、アルファチャンネルの値を見て、0.1 より上か下かで、不透明もしくは透明に2値化してくれるはずだけど…。やはり奥側にあるボールの色が反映されず、床が見えてしまっている。


色々試してみたけれど、結局のところ、こういったテクスチャ画像を貼るポリゴンについては、奥行き情報でソートして、奥側から手前に向かって描画しないと解決しないようだなと分かってきた。その分、処理負荷が増えるだろうから、あまりやりたくはないのだけど…。

ss_06_draw_billboard_alpha_test_2_03.png


あるいは、テクスチャ画像そのものに対して、事前にアルファチャンネルを2値化しておくことでも解決できるだろうなと。実際、上記のボール群も、アルファチャンネルを2値化している下半分については、見た目で特に問題は無いわけで。もっとも、縁の部分でジャギが目立つだろうし、ぼんやり重ねた感じの表現ができなくなるから、見た目の品質は落ちてしまうのだろうけど、処理負荷については、おそらく軽く済むだろう…。

つまるところ、処理負荷を増やして見た目の品質を向上させるか、見た目を犠牲にして処理を軽くするか、トレードオフなのかもしれないなと…。

余談。このあたりの問題は、 _「opengl transparent artifacts」_「Order independent Transparency」 (OIT) でググるとそれらしいページが出てくる模様、とメモ。

以上です。

過去ログ表示

Prev - 2022/09 - Next
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project