ゲームエンジン班最終報告
200711210 澤田進平■開発動機
そもそも、今年度の開発する予定のものはゲームエンジンではなかった。1 学期に主張したこと は、「汎用的なノードグラフエディターの開発」であった。当時、必要に迫られていたのが開発動機 である。一応、夏休み中にある程度開発したものがこれである。 C#のコントロールとして提供され、ノードの値、画像等は外部から読み込める予定であった。 何故、開発を停止したかというと、単純に使う必要性が消滅し、使いもしないものを開発する意欲 が存在しなかったからである。それが2 学期後半であり、3 学期、急遽、個人のほうで開発を計画 していたゲームエンジンを近未来マルチメディアで開発しようというのが近未来マルチメディアでこ れを行う理由である。 そもそも、何故、ゲームエンジンを開発しようと思ったのは、2006 年より開発し、実際に使用して いたゲームエンジンが性能面で非常に問題があり、かつ拡張では既に対処できない状況に陥っ ていたからである。それで、今までに考えていた機能を盛り込み、新規に作ろうと思い立ったのが 今回、ゲームエンジンを開発しようとした理由である。
■設計と目標
・プラットフォームWindows、Linux、MacOSX、XBOX360 に対応可能にする。Windows では.net framework で動 作、Linux、MacOSX、は mono で動作、 XBOX360 では XNA で動作するようにする。
・プログラム言語 C・C++・IronPython で開発する。この3つの選択での理由としては、XNA は C#での開発なので 必然的にC#中心の開発になる。しかし、Windows、Linux、MacOSX での C#では描画自体はでき ないため、描画等、C#で記述できない部分に関しては C/C++を使用する。IronPython は C#で使 用できるスクリプト言語がいまだ限られているため、これを使用する。 ・描画
Windows では DirectX、Linux、MacOSX では OpenGL、XBOX360 では XNA を使用する。 ・その他 マルチコアのCPU が増えてきたこともあり、コア数が多ければ多いほど実行速度が速くなるよう 開発する。 また、最近はPC のスペックがあがってきたので、実行速度よりも可読性と保守性を重視する。 ・目標 当初は、各々の仕様をしっかり理解していない状態で、見切り発進をしてしまったためこのような いい加減かつ少ない方針で開発を開始することとなった。 目標としては、期間が3 ヶ月ほどしかなかったので 2 月までに 2D 描画を終了させる、と設定した。
■結果
・XNA の破棄 理由としては、まずXBOX では他の OS に対して完全な互換性が保てない点である。当初より、 完全な互換は無理だと分かっていたが、それ以上に互換性を捨てなければならない点が多かっ た。具体的には、IronPython は XBOX で動作しない、XNA ではリソースを配置する位置が固定さ れている、シェーダーを動的に生成ができない、などである。なお、私の調査不足で実際はできる かもしれない。次に、可読性とメンテナンス性の点である。XNA はゲームループまで固定されてお り、当初予定していた構造とあわせるには可読性の低いコードを書かざる得なかった。これらの理 由のため、XBOX360 で動くというメリットは大きかったが、これらのデメリットのため XBOX360 対 応はやめることにした。なお、XNA のバージョンがあがり、できることが増えれば再開する可能性 はある。・2D 表示 DirectX と OpenGL それぞれで同じように動作するものができた。ただ 2D 表示、本当に画像を 表示するだけなので特にスクリーンショット等は示さない。表示した以上にDirectX と Open GLの 差異に関する点で得られたものが多かったのでそれは後述する。 ・CtoC#コンバーター C で記述した DLL を読み込むためには、C#側でも特殊な記述をしたコードが必要である。手動 でやるとミスが発生する可能性がある、変更に対して弱い、単純作業なので人間がやるべき仕事 ではない、という点からC のヘッダパーサーとコンバーターを自作した。なお、これの開発は 「Swig」という海外発のプロジェクトで作られたソフトによって意味はなくなってしまう。 ・総評 おそらく、近未来マルチメディア至上、類を見ない2D 表示だけの結果であろう。既存のライブラ リを使うならば画像表示はおそらく数行で終わるものだと思われる。しかし、今回の開発で書いた コード行数は数千行と見た目からは想像できないものになっている。かなりのソースがDirectX と OpenGL を問題なく裂かれたものであり、単純に表示するだけならほんの短い行数で済むであろう。
■考察
今回はゲームエンジンという、基盤に当たる部分の開発だったので、開発以上に既存のものへ の認識が深まった。それゆえに問題点等が見えてきたので、主にそれらについて考察する。なお、 これらは知識不足より間違いが多分に含まれている可能性がある。 ・DirectX の問題点と今後 ・HLSL(DirectX9) セマンティクスの意義 DirectX のシェーダーでは、通常のプログラムからデータを渡す際にセマンティクスというものを 指定する。頂点データの配列で、どの部分がシェーダーでのどの値と対応するかを示すものであ り、「POSITION0」、「NORMAL0」、「COLOR0」、「COLOR1」・・・などとセマンティクス名は完全に 決まったものしか使用できない。また、そのセマンティクス名は過去のものと互換性により、3D の表 示であるような、座標、法線方向、色、などあたかもそのセマンティクスにはそれに対応したデータ を当てる必要があるような印象を覚える名前である。最近のシェーダーでは単純な頂点の処理だ けでなく、様々な値を頂点に格納することによって見栄えをよくすることが多々ある。この傾向は DirectX9 が開発された当初には分かっていたであろうことであり、DirectX8 から DirectX9 になっ た時点で、互換性を切って固定でなく、ユーザーが自由に指定できるようにするべきだったと思わ れる。ちなみにOpenGL で HLSL にあたる GLSL では初期バージョンからセマンティクスのような ものを自由に設定することが出来た。なお、私のコンピューターでは動かないので実際に実行はさ せていないが、現状の流れを受けてDirectX10 ではセマンティクス名は自由になったようである。・DirectX10 DirectX9 との大きな違いは固定描画機能が消滅したことである。これにより、DirectX10 では簡 単な2D 描画でもシェーダーを書かなければならなくなった。それに伴う関数の統廃合が行われ ている。また、シェーダー自体の機能もあがりセマンティクス名も自由になった。今回、PCのスペッ クの問題上、サンプルコードを読む程度しかできなかったが、わかりやすいほうに改善が行われて いる、といえるだろう。ただ、国内を見ても資料がほとんどなく、またシェーダー必須となったため、 これからDirectX に触ってみようという人にとっては難しくなったのではないだろうか? ・OpenGL の問題点と今後 ・OpenGL のバージョン管理問題 OpenGL には明確なバージョンというものが存在せず、拡張という形で追加機能を提供している。 そのため、互換性は保たれるが過去に追加された関数から最新の関数までが混在し、非常に理 解しにくい状況になっている。この件に関しては、OpenGL3.0 で一応の解決を試みている。 ・GLSL(OpenGL2.1)の使いにくさ 今回の開発はOpenGL2.1 で開発しているため、このバージョンにおける GLSL について記述す る。GLSL は HLSL に対して難解であり、使いづらいと私は思う。それは何故か? まず、GLSL の最適化機能である。HLSL と同じように、シェーダー内の変数名を指定して値を 渡すことができるのだが、GLSL ではその値が最適化により使用されていないと判断されると消滅 し、プログラム本体から値を渡そうとしても、渡す先が発見できなくなる。このときに表示されるエラー のメッセージは、その変数名を持つ変数が見つからない、であり、元々なかったのか、最適化で消 されたのかは明記されておらず、OpenGL の初心者は非常に混乱することであろう。また、変数に 値を渡すときは変数名で検索して取得した変数のIDを用いて値を渡すのだが、変数のIDはシェー ダーのソース内に記入した順で振られていくのだが、最適化でID が変わってしまう。そのため、プ ログラム本体でもシェーダーにどのような名称の変数があるか、予め記憶しておく必要がある。実 際メモリを大して使わなくとも、これは非常にメモリの無駄使いであると思われ、いい気分ではない。 次に、固定の変数名と過去の変数との互換性の問題である。OpenGL は固定描画機能を使って いた時代の機能や、結果の出力に対して予め定義されたグローバル変数を使用している。固定 描画時代は座標、色などそれぞれに対して、値を送信する関数があり、シェーダーではそれらを 決まった名前の変数に代入されているという形で受け取ることが出来る。その変数名を知らない限 り、値を受け取ることはできず初心者が扱うときの妨げとなる。 これらが、私がGLSL が HLSL に対して使いにくいと感じた点である。 ・OpenGL3.0 現状のOpenGL の最新版であり、今回私のPCの性能の都合上、使用できなかったものである。 このバージョンから遂に、今まで残っていた古い関数が非推奨扱いになっている。例えば 「glBegin」「glEnd」など、今までの OpenGL では描画に必須だった固定描画機能のほとんどが非 推奨となり、いずれは削除されることになっている。当然glsl も改良され、上記の予め定義された グローバル変数もほとんど非推奨になっている。これにより、非推奨を守れば上記のOpenGL 使 用時の問題がほとんど解決されることになる。DirectX と同じく、やはり固定描画時代のものから離 れシェーダー中心になるよう進んでいるようである。
・OpenGL と DirectX の比較
・DirectX9.0c と OpenGL2.1+拡張によるマルチプラットフォーム対応は難しいか?
OpenGL は拡張により Framebuffer Object に対応とする。この機能は画面に描画するのではなく、 別の内部のメモリに描画し、それをテクスチャとして使用可能にする機能である。これが無いとでき ないことも多いので使用する。また、DirectX と OpenGL は両方とも固定描画は使用せず、全て シェーダーで描画することにする。
文法面
DirectX は C++であり、OpenGL は C 言語である。そのため DirectX はクラスを中心に記述され ており、OpenGL は関数を中心に記述している。また、DirectX は確保したバッファなどはクラスが 保持するのに対し、OpenGL は ID をバインドすることで対処している。この、方針の違いは実際に やってみると、ラッパーを1 つ書くだけでよく、特に問題にはならなかった。 FramebufferObject DirectX では、描画先は画面も、画面以外も同じように扱われ、カラーと深度のテクスチャは別々 に扱うことができるが、OpenGL では、画面と画面以外の描画先は別の扱いであり、また、 FramebufferObject という、カラーと深度のテクスチャセットを扱う必要がある。ただ、 FramebufferObject で使用するカラーと深度のテクスチャは切り替えることができるので、DirectX のように扱えるようにOpenGL のラッパーを書かなければ問題はないだろう。DirectX を OpenGL のように振舞わせることは簡単だが、OpenGL を DirectX のように振舞わせるのは多少面倒である。 HLSL と GLSL HLSL と GLSL で記述できる内容は、ほぼ全くといっていいほど変わらない。むしろ問題となるの はプログラム本体とシェーダーを接続する部分である。前述したとおり、DirectX はセマンティクス を使用してバッファをシェーダーに結び付けており、OpenGL は変数名から取得した ID によって バッファとシェーダーを結び付けている。OpenGL は変数名を必ずプログラム側で知っている必要 がある。 また、DirectX では使用するテクスチャを直接シェーダーに渡すことができるが、OpenGL はテク スチャを決まった位置にバインドし、シェーダーにはバインドしている位置を渡して、テクスチャを 使用する。この点もOpenGL 側にあわせればなんら苦労はすることはないが、DirectX 側にあわせ ようとすると、多少苦労することになる。 総評 今回は見切り発進につき、設計をほとんどDirectX 側にあわせてしまったため、何点かの点で面 倒なところがでてきてしまった。しかし、実際のところは両方の仕様をしっかり理解していれば、ほ ぼ問題なく全ての機能に対してラッパーを作れると思われる。シェーダーになったおかげで座標 系やUVなどのOpenGL と DirectX の仕様の違いも関係なくなっており、固定描画機能時代よりも はるかに楽に実装できることであろう。
・DirectX10.0 と OpenGL3.0+拡張によるマルチプラットフォーム対応はどれくらい簡単になるか? 仕様を見る限り、両方とも固定機能の廃止、もしくは非推奨と、シェーダーの強化以外は大差は ない。DirectX のセマンティクスが自由になり OpenGL に近くなった点を除けば、DirectX9.0c と OpenGL2.1+拡張でのマルチプラットフォームと大差はないだろう。 ・DirectX と OpenGL の今後 今まで述べてきたように、固定機能が廃止されたことによって、非常に似通ってきている。もはや、 独自路線という時代ではなく、これからもその傾向が続くのではないだろうか?昔はそれぞれの立 場と使用される場面に差はあり、一度はFahrenheit というプロジェクトで統合という話がでたものの、 失敗した経緯がある。しかし、今ならば統合してもほとんど問題ないレベルまで似通っており、万が 一に、統合という話が再度浮上すれば問題なく統合されるのではないだろうか?