2019/03/17(日) [n年前の日記]
#1 [gosu][ruby] gosu + opengl-bindingsを試していたり
せっかくだから、gosu + opengl の組み合わせだけではなく、gosu + opengl-bindings の組み合わせでもスクリプトが動くように修正作業をしているところ。
環境は以下。
とりあえず、以下のスクリプトは、どちらでも動くように修正できた。
_gosu_examples_mieki256/16_gosu_opengl_test1.rb
_gosu_examples_mieki256/17_gosu_opengl_test2.rb
_gosu_examples_mieki256/opengl_glut_only_test.rb
環境は以下。
- Windows10 x64 + Ruby 2.4.5 p335 mingw32 + gosu 0.14.5 + opengl 0.10.0
- Windows10 x64 + Ruby 2.5.3 p105 mingw32 + gosu 0.14.5 + opengl-bindings 1.6.8
- Ubuntu 18.04 + Ruby 2.5.1 p57 x86_64 + gosu 0.14.5 + opengl-bindings 1.6.8
とりあえず、以下のスクリプトは、どちらでも動くように修正できた。
_gosu_examples_mieki256/16_gosu_opengl_test1.rb
_gosu_examples_mieki256/17_gosu_opengl_test2.rb
_gosu_examples_mieki256/opengl_glut_only_test.rb
◎ opengl-bindingsに対応させる際の注意点。 :
opengl 用のスクリプトを、opengl-bindings に対応させる際のポイントを一応メモ。
まず、require や include の書き方が変わる。
opengl の場合。
opengl-bindings の場合。
また、glTranslate() や glRotate() も変わる。
opengl は glTranslate() や glRotate() と書けるけど。
opengl-bindings は glTranslatef() や glRotatef() と書かないといけない。
後者の書き方をすればどちらでも動くので、全部後者で統一しちゃってもいいのかもしれない。
また、opengl は配列をそのまま渡せるけれど。
opengl-bindings は、場合によっては pack() を使わないとダメらしい。
以下のやり取りで解説されてた。
_glLightfv fails - Issue #28 - vaiorabbit/ruby-opengl
ただ、試したところ、毎フレーム呼ばれる処理の中で pack() で変換していると、処理時間がかかってしまって、描画までおかしくなるようで。初期化処理等で、できるだけ事前に pack しておいて、毎フレーム呼ばれる処理の中では pack 済みのデータを指定する、といった工夫が必要になるようだなと。
まず、require や include の書き方が変わる。
opengl の場合。
# gem install opengl glu glut require 'gl' require "glu" require "glut" include Gl include Glu include Glut
opengl-bindings の場合。
# gem install opengl-bindings require 'opengl' require "glu" require "glut" OpenGL.load_lib GLU.load_lib GLUT.load_lib include OpenGL include GLU include GLUT
また、glTranslate() や glRotate() も変わる。
opengl は glTranslate() や glRotate() と書けるけど。
glTranslate(x, y, z) glRotate(angle, 0.0, 1.0, 0.0)
opengl-bindings は glTranslatef() や glRotatef() と書かないといけない。
glTranslatef(x, y, z) glRotatef(angle, 0.0, 1.0, 0.0)
後者の書き方をすればどちらでも動くので、全部後者で統一しちゃってもいいのかもしれない。
また、opengl は配列をそのまま渡せるけれど。
glLightfv(GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0])
opengl-bindings は、場合によっては pack() を使わないとダメらしい。
glLightfv(GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0].pack("f*"))
以下のやり取りで解説されてた。
_glLightfv fails - Issue #28 - vaiorabbit/ruby-opengl
ただ、試したところ、毎フレーム呼ばれる処理の中で pack() で変換していると、処理時間がかかってしまって、描画までおかしくなるようで。初期化処理等で、できるだけ事前に pack しておいて、毎フレーム呼ばれる処理の中では pack 済みのデータを指定する、といった工夫が必要になるようだなと。
◎ ライト設定でハマった。 :
以下のスクリプトを opengl-bindings に対応させようとして修正した際に、ライトの設定でハマったり。
_gosu_examples_mieki256/01_gosu_opengl_11.rb
_gosu_examples_mieki256/02_gosu_opengl_15.rb
スクリプトを実行するたびに、何故かオブジェクトが真っ暗になったり、明るくなったりする。動作が不定。条件が分からない。
色々ググってるうちに、なんとなく分かってきた。ライトの位置、もしくは方向を指定する際に、[x,y,z] を指定していたけど。最後に w も追加して [x,y,z,w] を指定しないと動作が不定になるっぽい。
おそらくだけど、OpenGL側は [x, y, z, w] の4つが指定されてることを前提にして動いてるのに、スクリプト側では [x, y, z] の3つしか渡してなかったから、最後の w は謎の領域から謎の値を読んで動作していたのではないかと。スクリプトを実行するたびに、謎領域のアドレスも値も変化してしまうから、明るくなったり暗くなったりしていたのかなと。
ちなみに、glLightfv(GL_LIGHT0, GL_POSITION, [x, y, z, w]) の w は、0.0 なら平行光源、それ以外なら点光源ということになってる模様。たぶん。
_光源の設定 - OpenGL de プログラミング
_OpenGL ライティング(Lighting)
_gosu_examples_mieki256/01_gosu_opengl_11.rb
_gosu_examples_mieki256/02_gosu_opengl_15.rb
スクリプトを実行するたびに、何故かオブジェクトが真っ暗になったり、明るくなったりする。動作が不定。条件が分からない。
色々ググってるうちに、なんとなく分かってきた。ライトの位置、もしくは方向を指定する際に、[x,y,z] を指定していたけど。最後に w も追加して [x,y,z,w] を指定しないと動作が不定になるっぽい。
# Light LIGHT_POS = [1.0, 2.0, 4.0] # 位置 LIGHT_AMBIENT = [0.5, 0.5, 0.5, 1.0] # 環境光 LIGHT_DIFFUSE = [1.0, 1.0, 1.0, 1.0] # 拡散光 LIGHT_SPECULAR = [1.0, 1.0, 1.0, 1.0] # 鏡面光 LIGHT_POS_PACK = LIGHT_POS.pack("f*") LIGHT_AMBIENT_PACK = LIGHT_AMBIENT.pack("f*") LIGHT_DIFFUSE_PACK = LIGHT_DIFFUSE.pack("f*") LIGHT_SPECULAR_PACK = LIGHT_SPECULAR.pack("f*") ... # opengl-bindings glLightfv(GL_LIGHT0, GL_AMBIENT, LIGHT_AMBIENT_PACK) glLightfv(GL_LIGHT0, GL_DIFFUSE, LIGHT_DIFFUSE_PACK) glLightfv(GL_LIGHT0, GL_SPECULAR, LIGHT_SPECULAR_PACK) glLightfv(GL_LIGHT0, GL_POSITION, LIGHT_POS_PACK) glEnable(GL_LIGHTING) # ライティングを有効化 glEnable(GL_LIGHT0) # GL_LIGHT0 を有効化
LIGHT_POS = [1.0, 2.0, 4.0] # 位置 ↓ LIGHT_POS = [1.0, 2.0, 4.0, 0.0] # 位置
おそらくだけど、OpenGL側は [x, y, z, w] の4つが指定されてることを前提にして動いてるのに、スクリプト側では [x, y, z] の3つしか渡してなかったから、最後の w は謎の領域から謎の値を読んで動作していたのではないかと。スクリプトを実行するたびに、謎領域のアドレスも値も変化してしまうから、明るくなったり暗くなったりしていたのかなと。
ちなみに、glLightfv(GL_LIGHT0, GL_POSITION, [x, y, z, w]) の w は、0.0 なら平行光源、それ以外なら点光源ということになってる模様。たぶん。
_光源の設定 - OpenGL de プログラミング
_OpenGL ライティング(Lighting)
◎ opengl-bindingsが落ちる。 :
Windows10 x64 + Ruby 2.5.3 p105 上で、以下のスクリプトを opengl-bindings で動かすと、数秒後に Segmentation fault で落ちてしまう。
_opengl_glut_only_test.rb
opengl + glu + glut で動かした場合は落ちないのだけどな。
なんでだろうな。
VMware Player 12 + Ubuntu 18.04 + Ruby 2.5.1 p57 + opengl-bindings 1.6.8 なら落ちない。Windows上でだけ落ちるということかなあ。
teapot をワイヤー表示するとすぐに落ちるけど、ソリッド表示にしたらちょっと落ちにくくなった気もした。でもまあ、結局は落ちるけど。
_opengl_glut_only_test.rb
opengl + glu + glut で動かした場合は落ちないのだけどな。
> ruby opengl_glut_only_test.rb load opengl-bindings D:/Ruby/Ruby25/lib/ruby/gems/2.5.0/gems/opengl-bindings-1.6.8/lib/glut.rb:421: [BUG] Segmentation fault ruby 2.5.3p105 (2018-10-18 revision 65156) [i386-mingw32] -- Control frame information ----------------------------------------------- c:0004 p:---- s:0016 e:000015 CFUNC :call c:0003 p:0021 s:0012 e:000011 METHOD D:/Ruby/Ruby25/lib/ruby/gems/2.5.0/gems/opengl-bindings-1.6.8/lib/ glut.rb:421 c:0002 p:0393 s:0006 e:000005 EVAL opengl_glut_only_test.rb:154 [FINISH] c:0001 p:0000 s:0003 E:000100 (none) [FINISH] -- Ruby level backtrace information ---------------------------------------- opengl_glut_only_test.rb:154:in `<main>' D:/Ruby/Ruby25/lib/ruby/gems/2.5.0/gems/opengl-bindings-1.6.8/lib/glut.rb:421:in `glutMainLoop' D:/Ruby/Ruby25/lib/ruby/gems/2.5.0/gems/opengl-bindings-1.6.8/lib/glut.rb:421:in `call' -- C level backtrace information ------------------------------------------- C:\WINDOWS\SYSTEM32\ntdll.dll(ZwWaitForSingleObject+0xc) [0x7796a8fc] C:\WINDOWS\System32\KERNELBASE.dll(WaitForSingleObject+0x12) [0x76d445f2] C:\Ruby\Ruby25\bin\msvcrt-ruby250.dll(rb_print_backtrace+0x40) [0x62a8b220] C:\WINDOWS\SYSTEM32\ntdll.dll(RtlCaptureStackContext+0x1e521) [0x7799da71] -- Other runtime information ----------------------------------------------- ..._全エラーメッセージ - error.txt
なんでだろうな。
VMware Player 12 + Ubuntu 18.04 + Ruby 2.5.1 p57 + opengl-bindings 1.6.8 なら落ちない。Windows上でだけ落ちるということかなあ。
teapot をワイヤー表示するとすぐに落ちるけど、ソリッド表示にしたらちょっと落ちにくくなった気もした。でもまあ、結局は落ちるけど。
[ ツッコむ ]
以上です。