スペースハリアー風味の床描画(3)

スペースハリアー風味の床描画プログラムを手直ししてみました。

あんまり見た目は変わってないですが、影描画の処理の追加を行っています。

game_ss03 ありがちなポスト処理とか入れてみたり。

描画オブジェクトを Z ソートしていないため、前後関係があやしいですけど…

単純な半透明影を落としてしまうと同じ場所に落ちた影同士が段々と暗くなっていくため、影だけを描画するレンダーターゲットを用意して、最後に合成しています。(影の解像度が低く見えるのは、レンダーターゲットの解像度が低いからです。)

システム自体は Nebula Device 2 を使用している為、影の描画部分以外はシステム内蔵のシェーダーをそのまま使用しています。

 

スペースハリアー風味の床描画(2)

前記事のデータを使用して、実際の描画を行ってみました。

(描画には NebulaDevice2 を使用)

nngame02 こんな感じ。

nngame04 試しに天井を描画。

VGAでの描画を行っているため、テクスチャには 1024×512 のサイズを使用しています。

スペースハリアー(多分アウトランも)に搭載されているハードウェアは、同時に2面の処理が行えるようになっていたらしいのでですので、同じ様な実装をしてみました。縦方向にも伸ばせるようになっています。

特殊な実装は何もせずに、単純に1ラインを描画するテクスチャ付きポリゴンを力技で描いているだけです。

ちなみにジャギが見苦しいので少しフォグをかけてあります。

スペースハリアー風味の床描画(1)

ポリゴンによる 3D 空間の描画が出来なかった時代に、画面の奥に向かって進行するゲームを開発するには、いくつかの手法がありました。

そのひとつに水平同期割り込み時に VRAM の読み取り位置を書き換えることによる変形処理で擬似的な 3D 表示を行っているものがあり、自分がすぐに思い浮かぶのはスペースハリアーだったりします。

というわけで、スペースハリアーの床(ラスター処理に渡すための画像)を描画するプログラムを作成してみました。

PIL で線を引いているだけのプログラムなんですけどね。

実行すると以下のような画像が生成されます。

export_w0256_h0128

スペースハリアーは、 512×256 ドットのデータを内部に保持しているようですので、 IMAGE_W には 512 を指定すると、もっともそれっぽい[1. と、自分では思っている]データが作成されます。

このデータを使用して擬似 3D な空間を表現するには、ラインごとにポリゴンを分割しなければなりませんが、細長い画像にしてしまえば javascript なんかでも描画出来るかも。

[wpdm_file id=37]

NebulaDevice2 用のパッチ

どの程度の需要があるのかわかりませんけど、 NebulaDevice2 for Windows 用のパッチを作成しました。

Sourceforge で公開されている revision 3307 をベースにしています。

変更点

ビルドシステムに VisualStudio2008 を追加。

NebulaDevice2 に付属の buildsys3 では VisualStudio2005 までのソリューションとプロジェクトしか生成出来なかったのですが、新しく VisualStudio2008 の形式で出力されるようにしました。

DirectX SDK(June 2010) 以前の DXErr 表記を修正。

2軸以上のゲームパッドに対応。

具体的には PlayStation2 や XBOX360 のコントローラーが接続された際に認識されていなかったアナログスティックが認識されるようになります。

マウスホイールの入力に対応。

ホイールの回転を Z 軸として受け取る事が出来ます。

 ■

[wpdm_file id=17]

MacOSX 上で Nebula Device 2 の build に挑戦中(6)

そんなわけで build が通るようになりました。

変更点一覧(WebSVN)

とは言うものの、ビルドを通すためには細かい変更が必要となる箇所が残っています。

  • nebula2 / buildsys3 / config.mak
    • python を 2.5 以上に変更。
    • g++, gcc にオプションを追加。
      • -m32 -D GL_GLEXT_PROTOTYPES=1
    • 以下のライブラリについて include と lib のパスを追加。
      • libtheora
      • libogg
      • devil
  • nebula2 / code / contrib / nopengl / data /scripts /startup.tcl
    • /sys/servers/input が存在しないため、以下の二つの関数呼び出しを抑制。
      • OnViewerMapInput
      • OnMapInput
  • nebula2 / code / nebula2 / inc /tools / nviewerapp.h
  • nebula2 / code / nebula2 / inc /tools / nviewerapp.cc
    • 以下のモジュール呼び出しを抑制。
      • videoserver
      • audioserver
      • prefserver
      • inputserver

nviewer あたりは別に用意した方が良いような気もするけど、一旦ここで終了かなぁ…

MacOSX 上で Nebula Device 2 の build に挑戦中(5)

やっとそれらしい表示になってきました。

nb2 glDrawElements も無事表示。

わかってみればどうという問題ではなくて、 glEnableClientState(GL_TEXTURE_COORD_ARRAY) だと bus error となっていました。glDisableClientState(GL_TEXTURE_COORD_ARRAY) を指定する事で、描画されるようになりました。(Texture 指定がないため、これはこれで正常ではないのですけど…)

頂点指定[1. glVertexPointer]が正しく設定されてないだけだったようです。

ところで、最新の Nebula Device 2 の trunk は、

  • wgl[1. Windows 用の OpenGL 拡張] の使用が前提。
  • MacOS版はビッグエンディアンを前提として書かれている。
  • メモリモデルが 32bit でなければポインタ <-> ユニークID の変換に問題が生じる。

といった具合に、実質 Windows 専用となってしまっているため、XQuartz 版として分離してしまっても良いかも。

 

MacOSX 上で Nebula Device 2 の build に挑戦中(4)

相変わらずの bus error 10

どうもテクスチャを有効にすると bus error 10 が出てしまうみたいなので、 shaders と renderpass を簡単な物に変更してみました。

ここまで単純にすれば動作するかな?と思いきや、やっぱり bus error 10 …

nMesh2 が怪しそう…

デバッグを続けていくと、どうやら nGLServer2::DrawIndexedNS あたりに原因がありそうなことがわかりました。

nGLServer2::DrawIndexedNS は、名前のようにインデックスバッファを指定して、プリミティブ(nMesh2)の描画)を行う関数なのですが、どうも glDrawElements を呼び出すとおかしくなるようです。

無理矢理な動作確認…

そんなわけで、直接ポリゴンを描画してみたらどうだろうか?というわけで、またもや無理矢理シェーダー設定を追加してみました。

tex 表示されました。(色がおかしいけど…)

どうやら、 nMesh2 関係が正しく動作していないみたい。

Nebula Device 2 の描画順序について

SceneNode内でソートしないようにするにはどうすれば良いのかと以前から気にしていたのですが、偶然見つけたのでメモ。

場所は nsceneserver_main.cc 内でした。

Nebula Device 2 は、描画順序に以下の様なルールで処理されます。

描画は XML で定義された render path 順に処理される。

使用するシェーダーによっては、レンダリングされた結果を読み取りたい場合があったり、デバッグ用のメニュー表示を行うために、 render path の順番はとても重要です。

ひとつの path は、その中で定義されたシェーダー順で描画される。

アルファ値を使用した描画をZ値を参照しながら描画をするときに前後関係によってはおかしくなる時があります。ですので、ひとつの path に列挙された順に描画されます。

SceneNodeはプライオリティが高いものほど手前に描画される。

表現方法によっては、本来みえないはずのものが見えた方が望ましい場合があります。(例えば、壁の向こう側が透けて見えるとか)そういった本来の前後関係をどうしても無視したい場合は、プライオリティの値を大きくすることで一時的に手前にする事が出来ます。

同じプライオリティの場合はカメラからの距離に応じて描画順序が並び替えられる。

不透明な物の後ろに配置された物は見えなくなります。描画される空間がどんなに広くても、それをディスプレイ越しに見る限りは、結局は見えている物がすべてとなります。

そこで

  • 全く見えないのはそもそも描画しない。
  • 一部分しか見えない物は、見えている部分だけを描画する。

といった方法で、必要な物だけを描画します。

手前のものから描くことで、そこに隠れているもの自体を描画しないようにします。

説明が長くなってしまいましたが、こんな感じで便利な機能が内蔵されているのですが、 2D の描画を行う際にはこの処理が問題となります。

Nebula Device 2 では nRpPhase に None, FrontToBack, BackToFront というのが選べるのですが、一時的にソートしないようにするにはどこをいじれば良いのかわからなかったので…

MacOSX 上で Nebula Device 2 の build に挑戦中(2)

nglviewer の build までは漕ぎ着けたけど、 OpenGL の初期化をしていないため「 OpenGL の関数が使用できない」という状態です。

そもそも glGetString 自体が動作していないという事から、ディスプレイの初期化すら出来ていない状態です。

ディスプレイの初期化が出来ると、ハードウェアの情報が取得出来るので、

GL_VENDOR … ATI Technologies Inc.
GL_RENDERER … ATI Radeon HD 4670 OpenGL Engine
GL_VERSION … 2.1 ATI-8.0.61

といった情報が取得出来るはずです。(これはうちの環境が iMac 21.5-inch, Late 2009 だからです。)

nOpenGL 部分が win32 向けに用意されているのと、自分が X11 上で OpenGL アプリケーションを開発したことがないため、 windows から X11 への差し替えをどうやればいいのか判断出来ない状態となりました。

irrlicht でも参考にしてみるかな。

 

MacOSX 上で Nebula Device 2 の build に挑戦中(1)

Nebula Device 2 は update.py を使用してビルド環境を生成する仕組みになっています。

例えば、

という指定をする事で、 makefile を使用するビルド環境を用意する事が出来ます。

Nebula Device 2 の描画システムは標準で DirectX9 を使用するのですが、gfx2 ライブラリを自分で用意することで他のシステム上に移植することが出来るようになっています。

幸いなことに OpenGL 用のモジュールが nebula2/code/contrib/nopengl に含まれているので、これを使用することで MacOSX 上でも Nebula Device 2 が動くようになりそうです。

実を言うと update.py で生成する Makefile に OSTYPE=darwin と指定する事で、 MacOS 上でのビルドが行えるようになっているのですが、 Nebula Device 2 自体が古いため、想定されているシステムは darwin8.0 ( MacOSX 10.4 ) までとなります。

ここは頑張らずに linux ( X11 + OpenGL ) の環境で build に挑戦してみることにします。

ソースコードの入手

まずは SourceForge からソースコードを入手します。

あとは build するだけ…というわけにはいかず、依存するライブラリも用意する必要があります。

必要なものは以下のものとなります。

  • libogg
  • libvorbis
  • libtheora
  • sqlite
  • XQuartz

というわけで、まずはこれらを build する必要があります。

それぞれの build に関しては、以下のように -m32 を指定しておきます。( Nebula Device 2 内に 32bit 環境前提のコードが含まれている為。)

…先は長そう。

Nebula Device 2 のビルド方法 (win32)

The Nebula Device 2 というゲーム開発用ライブラリがあります。かなり古いライブラリで更新がとまっている[1. 後継ライブラリとして http://code.google.com/p/nebuladevice/ があります。]のですが、内部仕様が好みで使っています。

自分用のメモとして以下にビルド方法を記述してみたりして。

以下のソフトウェアをインストール

  • VisualStudio 2008
  • DirectX SDK June 2010
  • Python 2.7
  • wxPython
  • ドキュメントの生成を行う場合は、追加で以下も必要です。
    • doxygen
    • HTMLHELP Workshop

SourceForge からソースをチェックアウト

svn co https://nebuladevice.svn.sourceforge.net/svnroot/nebuladevice/trunk

依存するファイルを追加でダウンロード

Nebula Device 2 は幾つか依存するライブラリ[1. ogg と sqlite3]があります。自前で持ってきても良いのですが、SourceForge から以下の名前でダウンロードする事が出来ます。

  • nebula-vc8-deps-20070409.zip
  • mangalore が必要な場合は、追加で以下も必要です。
    • mangalore-vc8-deps-20070407.zip

nebula2/buildsys3/generators に vstudio9 用の設定を追加する。

_WIN32_WINNT=WINVER; を vcproj に書き出さないようにするためと、Visual Studio 2008 でも build が行える様に、以下の Python コードを追加で配置します。

[wpdm_file id=12]

update.py を実行

python update.py

みたいな感じで実行すると、 Nebula 2 Build System が立ち上がりますので、 vstudio9 を選択した後に、ビルドしたいものにチェックを入れます。

基本部分だけなら nebula2libs, nebula2tools のみにチェックを入れてから、 RUN ボタンを押します。

VisualStudio に DirectX SDK のパスを追加

  • #include <dxerr9.h> の箇所を #include <dxerr.h> に変更。
  • DXGetErrorString9 を DXGetErrorString に変更。

ソリューションを開いてビルド

正常にビルドが完了していれば、 build/vstudio9/inter フォルダにライブラリが生成され、 bin フォルダに実行ファイルが生成されます。