2024/04/01(月) [n年前の日記]
#1 [prog] 疑似3D道路を描画するスクリーンセーバをC++とOpenGLで書いた
ここ最近ずっと作っていた、C++ と OpenGL を使って疑似3D道路を描画するWindows用のスクリーンセーバを、github にアップロードしておいた。
_mieki256/ssp3droadgl: Screensaver for Windows that draws pseudo 3D roads, implemented in C++ and OpenGL.
実行バイナリファイルは以下の2つ。
_mieki256/ssp3droadgl: Screensaver for Windows that draws pseudo 3D roads, implemented in C++ and OpenGL.
実行バイナリファイルは以下の2つ。
- ssp3droadgl.scr : スクリーンセーバ
- ssp3droadglfw.exe : スクリーンセーバと同じ描画をするデモプログラム。
◎ 残っている問題点 :
このプログラム、メインPC上では何度試してもすんなりヌルヌルと動くのだけど、サブPCでは動く時と動かない時があって、どうもまだちょっとどこかしら怪しい部分が…。ちなみにPCのスペックは以下。
どうしてサブPC上ではすんなり動かないのだろう…。
- メインPC : AMD Ryzen 5 5600X + NVIDIA GeForce GTX 1060 6GB + RAM 16GB。Windows10 x64 22H2。画面解像度 1920x1080。
- サブPC : AMD Athlon 5350 + 内蔵GPU Radeon R3 + RAM 4GB。Windows10 x64 22H2。画面解像度 1920x1200。
どうしてサブPC上ではすんなり動かないのだろう…。
◎ リモートデスクトップソフトが絡んでないか :
サブPC上では、メインPCからLAN経由で操作できるように、リモートデスクトップソフト Brynhildr をサーバモードで常駐させていた。もしかしたらそのせいでOpenGLを使ったプログラムが、ちと動かしづらい状態になっていたのかもしれない。
管理者権限で brynhildr.exe を実行して、Service で「Delete」を選ぶことでサーバモードのサービスを無効にしてから Windows10 を再起動したら、今回作成したスクリーンセーバが起動できる確率がグンと上がったような気がする。
ただ、完全に問題が解消されたわけでもなく。スクリーンセーバが呼び出された際、最初の1〜2回の呼び出し時は何故か起動に失敗する…。3回目ぐらいでスクリーンセーバが起動するようになって、一度起動してしまえば、そこから先は何度も起動が成功するし、ずっと動き続けてくれるのだけど…。
また、スクリーンセーバ版ではなく、GLFWを使った版は、Brynhildr がサーバモードで動いていても問題無く起動するし、描画もしてくれる…。
やはりスクリーンセーバとして動かそうとした時だけ、何か妙なことが起きてるとしか思えない。でも、メインPC上なら毎回必ず起動してくれるのだよな…。何故サブPC上ではダメなのか…。
管理者権限で brynhildr.exe を実行して、Service で「Delete」を選ぶことでサーバモードのサービスを無効にしてから Windows10 を再起動したら、今回作成したスクリーンセーバが起動できる確率がグンと上がったような気がする。
ただ、完全に問題が解消されたわけでもなく。スクリーンセーバが呼び出された際、最初の1〜2回の呼び出し時は何故か起動に失敗する…。3回目ぐらいでスクリーンセーバが起動するようになって、一度起動してしまえば、そこから先は何度も起動が成功するし、ずっと動き続けてくれるのだけど…。
また、スクリーンセーバ版ではなく、GLFWを使った版は、Brynhildr がサーバモードで動いていても問題無く起動するし、描画もしてくれる…。
やはりスクリーンセーバとして動かそうとした時だけ、何か妙なことが起きてるとしか思えない。でも、メインPC上なら毎回必ず起動してくれるのだよな…。何故サブPC上ではダメなのか…。
◎ テクスチャが大き過ぎるのだろうか :
今回、ビルボード用テクスチャが 4096 x 4096 x 1枚、BG用テクスチャが 2048 x 1024 x 4枚と、結構巨大なサイズのテクスチャになってるあたりも不安要素。png や jpg をベタデータに展開する際に時間がかかってしまっているだろうし…。何より、そんなサイズでVRAMを占有してしまって大丈夫なのかどうか…。そのせいで動作が怪しくなっている可能性は…。
いや、それは違う気もする。もしテクスチャのサイズが巨大過ぎて問題が起きてるなら、GLFW版の動作も同様に怪しくならないとおかしい。しかしGLFW版はすんなり何度も確実に動いてしまっているわけだから…。テクスチャサイズはこれでも問題無いということなんだろう…。
いや、それは違う気もする。もしテクスチャのサイズが巨大過ぎて問題が起きてるなら、GLFW版の動作も同様に怪しくならないとおかしい。しかしGLFW版はすんなり何度も確実に動いてしまっているわけだから…。テクスチャサイズはこれでも問題無いということなんだろう…。
◎ 余談。ビルボードについての課題 :
今回、各ビルボードを、四角ポリゴン(GL_QUADS)でドーンと表示してるけど。コレをちゃんと作るなら、複数のポリゴンを組み合わせて一つのビルボードにしたほうがいいのかもしれない。大昔の2Dゲームだって、スプライトを複数枚組み合わせて1つのキャラを作る場面があったわけだし…。
例えば…。
しかし、そのあたりを考えていくと、いっそ3Dモデルを作って描画したほうがいいのでは…。どうせ今回OpenGLを使って描画しちゃってるわけだし。地面と道路は疑似3Dだけど、その上に載せる各オブジェクトが3Dモデルになっていても何ら問題は無いよな…。もしかすると、いかにもな3Dモデルじゃなく、Z軸方向に差がある状態で複数枚のスプライト相当を重ねてあるだけでも、視差効果/パララックスが得られるかもしれない。
もっとも、3Dモデルにしてしまうのはやり過ぎかも。元々、レトロな見た目が欲しくてわざわざ疑似3Dにしているのに、3Dに寄せ過ぎるのもどうなんだろう。だったら道路も含めて全部3Dにしてしまえばいいじゃん、という話にもなりそう。
まあ、OpenGLでモデルデータを描画するのも結構一苦労しそうなので、今回はこのままでいいかなと…。
例えば…。
- 横方向にずらりと並ぶ花畑的なビルボードを描画したいなら、横方向に異様に長いテクスチャを用意するより、小さい正方形のスプライトを横にいくつも並べたほうがテクスチャ領域が節約できる。
- 木のビルボードも、葉っぱと幹を分けて組み合わせて作れば、幹の脇の透過部分を描画しなくて済む。
- 道路の上をまたぐ橋っぽいビルボードも、柱部分と横に長い部分で分けて作れば、真ん中の透過部分を描画しなくて済む。
しかし、そのあたりを考えていくと、いっそ3Dモデルを作って描画したほうがいいのでは…。どうせ今回OpenGLを使って描画しちゃってるわけだし。地面と道路は疑似3Dだけど、その上に載せる各オブジェクトが3Dモデルになっていても何ら問題は無いよな…。もしかすると、いかにもな3Dモデルじゃなく、Z軸方向に差がある状態で複数枚のスプライト相当を重ねてあるだけでも、視差効果/パララックスが得られるかもしれない。
もっとも、3Dモデルにしてしまうのはやり過ぎかも。元々、レトロな見た目が欲しくてわざわざ疑似3Dにしているのに、3Dに寄せ過ぎるのもどうなんだろう。だったら道路も含めて全部3Dにしてしまえばいいじゃん、という話にもなりそう。
まあ、OpenGLでモデルデータを描画するのも結構一苦労しそうなので、今回はこのままでいいかなと…。
[ ツッコむ ]
以上、1 日分です。