FPSを作ってみる@wiki
09)
最終更新:
slice
-
view
(2013/09/30)
OpenSL
作る!と言った矢先でアレだけど、っていうか途中まで作ってしまったのだけど
OpenSLかOpenALにしようと思った。
OpenSLかOpenALにしようと思った。
何故か?
1. SDL2のアンドロイドポートはAPI Levelが10(android 2.3.3)以上
2. OpenSLはAPI Level9から使える筈なので当然内部でOpenSLを使っているだろうと踏んでいた
3. ところがソースを見てみるとJavaの部分でちゃっかりAudioTrackを使っている <= 折角Level10以上としてあるのに訳がわからない(これからって事?)
4. つまりどんなに頑張ってサウンド合成したとこで出力がAudioTrackでは(遅延の点で)台無し
2. OpenSLはAPI Level9から使える筈なので当然内部でOpenSLを使っているだろうと踏んでいた
3. ところがソースを見てみるとJavaの部分でちゃっかりAudioTrackを使っている <= 折角Level10以上としてあるのに訳がわからない(これからって事?)
4. つまりどんなに頑張ってサウンド合成したとこで出力がAudioTrackでは(遅延の点で)台無し
これだったら仮にPCとの兼ね合いでOpenALを使うとしても出力は同じAudioTrackなのでデメリットはないし
何ならOpenSLにすればベスト。そもそも何でLevel10以上なのかよくわからない。
Cメソッドを呼ぶには従来通りJNIで記述してあるし、NativeActivityを使ってる箇所も無いようだし・・
何ならOpenSLにすればベスト。そもそも何でLevel10以上なのかよくわからない。
Cメソッドを呼ぶには従来通りJNIで記述してあるし、NativeActivityを使ってる箇所も無いようだし・・
まぁそんな訳でAndroidで動かす事を思えば単に車輪の再発明なだけでなくJavaで書いた様な遅延もするという散々な結果に。
いや、自前で実装・・一度はしてみたかったんだけどねぇ。どうしようか。
いや、自前で実装・・一度はしてみたかったんだけどねぇ。どうしようか。
それで
うだうだしてても始まらないのでとりあえずOpenALを触り、その後OpenSLも触り、両者の違いを鑑みつつラッパークラスの作成。
という感じにしたい。
という感じにしたい。
(2013/09/29)
自作
やはりサウンドは自前で実装する事にした。
なんかこういうのGameboyAdvanceのプログラムを作った時以来かね、という感じだが。この際ちゃんと実装する。
要件はwaveとoggの再生とミキシング。oggについては事前にwave変換するタイプとストリーミング再生するタイプに分ける。
あとはサウンド再生開始と終了時のプチノイズ抑制。それとフェードイン、フェードアウト。
簡単なチャンネル管理も実装。
なんかこういうのGameboyAdvanceのプログラムを作った時以来かね、という感じだが。この際ちゃんと実装する。
要件はwaveとoggの再生とミキシング。oggについては事前にwave変換するタイプとストリーミング再生するタイプに分ける。
あとはサウンド再生開始と終了時のプチノイズ抑制。それとフェードイン、フェードアウト。
簡単なチャンネル管理も実装。
こんなとこかね。
出来ればスローダウンとかもやってみたいが、どうなることやら。
標準のSDL関数にサウンドフォーマット変換くらいはある様なのでコレを使わせてもらう予定。
出来ればスローダウンとかもやってみたいが、どうなることやら。
標準のSDL関数にサウンドフォーマット変換くらいはある様なのでコレを使わせてもらう予定。
(2013/09/25)
微妙なSDL_mixer
SDL_mixerの細かな仕様を調査中。
やはりmusicは1チャンネルしか無いようで、大抵のゲームならこれで事足りると思われるけど
もしダイナミックに再生する音楽を変えたい、つまり別の音楽とクロスフェードさせたい時は
効果音としてイントロだけのoggを別途用意してそれを再生しつつmusicを一旦フェードアウト、
で、再生位置を合わせて次の音楽を重ねるとか・・考えるだけで面倒そうだ。
SDL_AudioのAPI使って自分で組んだほうが話が早い気がした。
やはりmusicは1チャンネルしか無いようで、大抵のゲームならこれで事足りると思われるけど
もしダイナミックに再生する音楽を変えたい、つまり別の音楽とクロスフェードさせたい時は
効果音としてイントロだけのoggを別途用意してそれを再生しつつmusicを一旦フェードアウト、
で、再生位置を合わせて次の音楽を重ねるとか・・考えるだけで面倒そうだ。
SDL_AudioのAPI使って自分で組んだほうが話が早い気がした。
Oggならliboggでデコードしつつ定期的に波形を書き込み、フェードインとアウトを実装。
う〜む、だったら最初からSDL_mixerなんか要らないじゃないか。
SDL_mixerの利点といえば各種フォーマットに対応していて簡単に鳴らせる事だけど
同一のゲームにおいてある音楽はmp3で別の音楽はoggなんてしないだろうし、微妙かもしれない。
う〜む、だったら最初からSDL_mixerなんか要らないじゃないか。
SDL_mixerの利点といえば各種フォーマットに対応していて簡単に鳴らせる事だけど
同一のゲームにおいてある音楽はmp3で別の音楽はoggなんてしないだろうし、微妙かもしれない。
っていうかサウンドに関してはwaveとoggしか使わないしliboggも前に触ったから自作すればいいんじゃないの?
SDL_mixerは手軽さという点では優れてるけど
細かい所が微妙に使いにくいからムズムズしてきた訳で。
SDL_mixerの3Dサウンド(?)にしても角度と距離だけの簡易版だからこれも別に要らない。
SDL_Audioは素のままではwaveオンリーだけど周波数変換関数くらいはあるから再生周波数が違っても大丈夫そうだ。
SDL_mixerは手軽さという点では優れてるけど
細かい所が微妙に使いにくいからムズムズしてきた訳で。
SDL_mixerの3Dサウンド(?)にしても角度と距離だけの簡易版だからこれも別に要らない。
SDL_Audioは素のままではwaveオンリーだけど周波数変換関数くらいはあるから再生周波数が違っても大丈夫そうだ。
(2013/09/23)
windowsでの動作確認
w64なMinGWでコンパイルしたバイナリを実際にwindowsXPや8で動かしてみると、何やらsegmentation faultが。
原因は・・ちゃんと最後まで調べればわかるんだけど途中まで調べた結果ではコンパイルオプションを-O3にすると駄目で-O2なら動く。
つまり何処かでコンパイラやC++の規約を無視した記述をしてしまってる。
恐らく可変テンプレート引数の辺りかなとは思うけど-O2にすれば動くので、とりあえずいいや。
原因は・・ちゃんと最後まで調べればわかるんだけど途中まで調べた結果ではコンパイルオプションを-O3にすると駄目で-O2なら動く。
つまり何処かでコンパイラやC++の規約を無視した記述をしてしまってる。
恐らく可変テンプレート引数の辺りかなとは思うけど-O2にすれば動くので、とりあえずいいや。
サウンド
入力、描画がひと通り揃った所で次はサウンドを鳴らそうかという事でSDL_audioでサンプルを見ながら正弦波や矩形波を出力してみたり
SDL_mixerでOggの音楽を再生してみたりと勉強中。
とにかく音を鳴らすだけなら初めてでも10分かからず、エフェクト等組み込むにしても割と素直なAPIなのでこれも難しくない。
音楽(Music)と効果音(Chunk)用のAPIが分かれていてMusicは本当にBGMとしての使用だけを想定しているらしく1チャンネルしかないが
多分デカいファイルでもストリーミングで再生してくれるのだろう。
フォーマットはMusicがwaveをはじめogg, mp3, mod、midiやflacなど。
Chunkはwave, aiff, riff, ogg, vocとなっている。oggは両方使えるのがうれしい。
SDL_mixerでOggの音楽を再生してみたりと勉強中。
とにかく音を鳴らすだけなら初めてでも10分かからず、エフェクト等組み込むにしても割と素直なAPIなのでこれも難しくない。
音楽(Music)と効果音(Chunk)用のAPIが分かれていてMusicは本当にBGMとしての使用だけを想定しているらしく1チャンネルしかないが
多分デカいファイルでもストリーミングで再生してくれるのだろう。
フォーマットはMusicがwaveをはじめogg, mp3, mod、midiやflacなど。
Chunkはwave, aiff, riff, ogg, vocとなっている。oggは両方使えるのがうれしい。
todo
- SDLがAndroidでどの位動くのか調査
- SDLのサウンドラッパークラス作成
- 自前ライブラリがSSE使っててAndroidだと大多数動かないからSSE無しバージョンの実装
(2013/09/20)
グラフィック強化は何処へやら
MinGW
前にやった時はどっかのブログに書いてあった手順をそっくり真似て環境構築したし、
どのファイルをどこに置くなんかも全然わかんなくてあっちこっちコピーしまくってアレだった。
この際という事でMinGW(i686-w64-mingw32)でソースからコンパイルして再構築。
ついでにSDL2もMinGW用のをコンパイルしようとしたらXInput辺りでVARIANTという構造体のbstrValが無いとかでエラーになる。
VARIANTというのはwindowsで使われる、いわゆる何でも代入できる型だ。
で、内部でいろんな型として解釈できるようunionで定義してある筈で、実際ヘッダを見てもその通りだし、ちゃんとインクルードもされてるのに「そんなメンバーない」と。
かといって定義をコピペすると当然多重定義エラーになる。
どのファイルをどこに置くなんかも全然わかんなくてあっちこっちコピーしまくってアレだった。
この際という事でMinGW(i686-w64-mingw32)でソースからコンパイルして再構築。
ついでにSDL2もMinGW用のをコンパイルしようとしたらXInput辺りでVARIANTという構造体のbstrValが無いとかでエラーになる。
VARIANTというのはwindowsで使われる、いわゆる何でも代入できる型だ。
で、内部でいろんな型として解釈できるようunionで定義してある筈で、実際ヘッダを見てもその通りだし、ちゃんとインクルードもされてるのに「そんなメンバーない」と。
かといって定義をコピペすると当然多重定義エラーになる。
いくらか修正を試みたがよくわからんのでコンパイル済みのライブラリを導入。
ちなみにw64でないMinGWなら普通にコンパイルが通る。
ちなみにw64でないMinGWなら普通にコンパイルが通る。
メッセージ
エンジンのマルチスレッド化に従いスレッド間通信用のメッセージパッシング機構を作った。
これはフツーに書くとWin32APIみたいにメッセージのIDによってswitchで分岐する形となる。
これはフツーに書くとWin32APIみたいにメッセージのIDによってswitchで分岐する形となる。
Message* m = getMessage();
if(m) {
switch(m->type) {
case MSG_ANYTHING:
// キャストして変数にアクセス
std::cout << static_cast<float>(m->param[0]);
break;
case MSG_SOMETHING: ... break;
...
}
}
だがこれはハッキリ言って面倒である。
汎用型(intやvoid*)で格納したパラメータの何番がどんな型の値で、どんな意味をもっているかを別途把握してなきゃいけない。
汎用型(intやvoid*)で格納したパラメータの何番がどんな型の値で、どんな意味をもっているかを別途把握してなきゃいけない。
SDLだと内部にunionで各メッセージに対する構造体を持っていてアクセスしやすくはなっているが
それもシステムで用意されたメッセージだけだし、もうちょっとC++っぽくならないものか?と思ったので・・
それもシステムで用意されたメッセージだけだし、もうちょっとC++っぽくならないものか?と思ったので・・
if(boost::optional<Message&> m = getMessage()) {
if(msg::Anything p = m) {
// ドット演算子でメンバにアクセス
std::cout << p.any_value;
} else if(msg::Something p = m) {
std::cout << p.some_value;
}
}
こんな風に書けるようにした。詳細は後日ソースコードで。
(2013/09/17)
MinGWとstd::thread
やはりMinGWでstd::threadが使えるなら使いたいのでひたすらmingw-w64のコンパイル等。
途中の失敗も含め既に4回ほど
binutils -> mingw-w64-header -> gcc(core) -> mingw-w64-crt -> gcc
のセットでコンパイルしては確認、やっぱ駄目だったを繰り返している。流石に疲れた。
途中の失敗も含め既に4回ほど
binutils -> mingw-w64-header -> gcc(core) -> mingw-w64-crt -> gcc
のセットでコンパイルしては確認、やっぱ駄目だったを繰り返している。流石に疲れた。
結論。
mingw-w64は現時点でのリリースバージョン、test(beta?)バージョン、gitで取得した最新バージョン
いずれも標準ではスレッド関係のクラスに対応してない。
mingw-w64は現時点でのリリースバージョン、test(beta?)バージョン、gitで取得した最新バージョン
いずれも標準ではスレッド関係のクラスに対応してない。
http://mattn.kaoriya.net/software/lang/c/20110628161014.htm
を見つつ自分でソースを書き換えて対応させるか、あるいは
http://d.hatena.ne.jp/kikairoya/20120122/1327227689
のようなパッチを適用するか(ただし4.7.0のようだ)
http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/rubenvb/gcc-4.8-experimental-stdthread/
とかにあるパーソナルビルドなら動くらしい。こっちは試してない。
を見つつ自分でソースを書き換えて対応させるか、あるいは
http://d.hatena.ne.jp/kikairoya/20120122/1327227689
のようなパッチを適用するか(ただし4.7.0のようだ)
http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/rubenvb/gcc-4.8-experimental-stdthread/
とかにあるパーソナルビルドなら動くらしい。こっちは試してない。
boost::threadを使う手段については、少なくともubuntu上でクロスコンパイラを用いてライブラリをビルドしたら
きっちりthreadが省かれていたのでそのままじゃ駄目っぽい。
windows上でmsvcを使ってビルドすれば行けるのかな・・・?
きっちりthreadが省かれていたのでそのままじゃ駄目っぽい。
windows上でmsvcを使ってビルドすれば行けるのかな・・・?
ま、なんかよく分からんけどとりあえずいいか。SDLのthread, mutex, cond_valueラッパークラス作ってあるし。
(2013/09/17)
TLS
重い計算を範囲で振り分けて終わりの単純なマルチスレットプログラムでは単にメインスレッドでjoinとかしとけばいいんだけど
色々メッセージをやり取りしたいとなると何らかの機構が必要だ。
つまるところメッセージキューである。
色々メッセージをやり取りしたいとなると何らかの機構が必要だ。
つまるところメッセージキューである。
特定のスレッドにさせたい処理を構造体に格納しておいて、
そのスレッドが定期的にキューを見て処理を行う。それだけ。
マルチスレッドなプログラムならほとんどが備えていると思われる。
Androidもそうだし、windowsだってそうである。
そのスレッドが定期的にキューを見て処理を行う。それだけ。
マルチスレッドなプログラムならほとんどが備えていると思われる。
Androidもそうだし、windowsだってそうである。
で、ちょこっと作るまでは良かったが
clangでthread_localなstaticクラス変数かグローバル変数を作ると内部エラーが発生しダンプを吐いて落ちてしまう。
変数の型をintやdoubleなどの組み込み型にするとか、
自作のクラスでもメンバにSTLのコンテナが無ければ大丈夫っぽかったりはするが、条件はよくわからん。
最新版に更新しても変わらず。原因究明すれば偉くなれそうだったがあいにくそのような気力はない。
g++ 4.8.1なら普通にコンパイルが通るがclangの方がコンパイル時間が約半分で済むので極力こちらを使いたい。
なので車輪の再発明とわかりつつも当面はSDLのTLS関数を使った簡単なテンプレートクラスを作って代用。
clangでthread_localなstaticクラス変数かグローバル変数を作ると内部エラーが発生しダンプを吐いて落ちてしまう。
変数の型をintやdoubleなどの組み込み型にするとか、
自作のクラスでもメンバにSTLのコンテナが無ければ大丈夫っぽかったりはするが、条件はよくわからん。
最新版に更新しても変わらず。原因究明すれば偉くなれそうだったがあいにくそのような気力はない。
g++ 4.8.1なら普通にコンパイルが通るがclangの方がコンパイル時間が約半分で済むので極力こちらを使いたい。
なので車輪の再発明とわかりつつも当面はSDLのTLS関数を使った簡単なテンプレートクラスを作って代用。
再発明
そういえば・・
前にMinGWでstd::threadが使えない云々と書いたけど、あれは正確にはgccのビルドオプションでthread modelをwin32にすると
std::thread関連が無効にされてしまうという事だった。
gccはpthreadしか扱わない(扱えない?)ようで、そういう仕様らしい。
けどMinGW-w64を使えばwin32 threadをpthreadなインタフェースでラップしたwinpthreadsを内部で使ってstd::threadを動かせるようだ。
他にもboost::threadという手がある。
何が再発明なのかと言えばSDLのスレッド関数を使ってstd::thread風のクラスを作ってしまった事。
これはもう、ほんと無駄だね。少し実装の勉強にはなったものの。
前にMinGWでstd::threadが使えない云々と書いたけど、あれは正確にはgccのビルドオプションでthread modelをwin32にすると
std::thread関連が無効にされてしまうという事だった。
gccはpthreadしか扱わない(扱えない?)ようで、そういう仕様らしい。
けどMinGW-w64を使えばwin32 threadをpthreadなインタフェースでラップしたwinpthreadsを内部で使ってstd::threadを動かせるようだ。
他にもboost::threadという手がある。
何が再発明なのかと言えばSDLのスレッド関数を使ってstd::thread風のクラスを作ってしまった事。
これはもう、ほんと無駄だね。少し実装の勉強にはなったものの。
(2013/09/13)
インプットクラス・マネージャ
例のごとく入力クラスが結構大掛かりな感じに。でも大体完成。
前回書いたけどスマートフォンやタブレットに対応したいので当然ながらタッチパネルも考慮しなければならない。
SDLはMouseとKeyboardとJoypadはマニュアルでボタン状態の取得とイベント通知による取得の両方の手段が用意されていて
マニュアル取得のほうが自分の実装方式に合っていたのでそっちを使っていたら
なんと、Touchpanelはイベント通知オンリーらしい。
API的には複数のパネルに対応する雰囲気を醸し出しつつ、それでいてOpen系の関数は無い。多分これからなんだろうけど。
前回書いたけどスマートフォンやタブレットに対応したいので当然ながらタッチパネルも考慮しなければならない。
SDLはMouseとKeyboardとJoypadはマニュアルでボタン状態の取得とイベント通知による取得の両方の手段が用意されていて
マニュアル取得のほうが自分の実装方式に合っていたのでそっちを使っていたら
なんと、Touchpanelはイベント通知オンリーらしい。
API的には複数のパネルに対応する雰囲気を醸し出しつつ、それでいてOpen系の関数は無い。多分これからなんだろうけど。
ま、そんな訳で現状のSDLではタッチパネルはデフォルトで入力を受け付けるようになっていて
デフォルトの状態で特に何もしなくてもイベントが送られてくる。
イベント通知というのがこれまでのクラスと噛み合わなかったりして一部書き直し等。
デフォルトの状態で特に何もしなくてもイベントが送られてくる。
イベント通知というのがこれまでのクラスと噛み合わなかったりして一部書き直し等。
マウスカーソルの制限
マウスカーソルをウィンドウから出ないように制限したいのだけど
(カーソルの相対移動量を取るのではなく、ウィンドウの枠外に出ないようにする)
どうすれば良いのか微妙に分からん。
というのもSDLのカーソル位置取得関数はフォーカスを持っているウィンドウの相対位置しか取れず、更にカーソルが外に行くと
フォーカスが外れてしまう様で・・
どうせゲームだしウィンドウ1つしか出さないからグローバルにウィンドウ変数を持っておいて
フォーカスが外れていたら直前のフレームでのカーソル位置に戻せばいいのかね。
(カーソルの相対移動量を取るのではなく、ウィンドウの枠外に出ないようにする)
どうすれば良いのか微妙に分からん。
というのもSDLのカーソル位置取得関数はフォーカスを持っているウィンドウの相対位置しか取れず、更にカーソルが外に行くと
フォーカスが外れてしまう様で・・
どうせゲームだしウィンドウ1つしか出さないからグローバルにウィンドウ変数を持っておいて
フォーカスが外れていたら直前のフレームでのカーソル位置に戻せばいいのかね。
(2013/09/11)
インプットクラス
ゲームなんだから入力もちゃんと整えないとなあという事でキーボード、マウスとジョイパッド(ジョイスティック?)関連の
SDLラッパークラスをガリガリと書いている。
基本的にこれまでのDirectInput用の骨組みを流用なので特に書くことはない。
ただC++のインタフェースクラスでSDL用だろうがDirectInput用だろうが何でもかんでも対応というのは一見スマートだけど
それ以外の部分がスマートじゃなくなるのでこれは無し。
プラットフォーム依存クラスと共通クラスを分けて書いて組み合わせてコンパイルという形。
(SDLのJoystickの状態を更新する関数は全Joystick共通だったりとか。
各Joystickの値を更新する度に呼び出してもいいけど同じフレームで何回も呼ぶのはどうなの?という感じだし
現在時刻で呼ぶか決めるのもアレだし)
SDLラッパークラスをガリガリと書いている。
基本的にこれまでのDirectInput用の骨組みを流用なので特に書くことはない。
ただC++のインタフェースクラスでSDL用だろうがDirectInput用だろうが何でもかんでも対応というのは一見スマートだけど
それ以外の部分がスマートじゃなくなるのでこれは無し。
プラットフォーム依存クラスと共通クラスを分けて書いて組み合わせてコンパイルという形。
(SDLのJoystickの状態を更新する関数は全Joystick共通だったりとか。
各Joystickの値を更新する度に呼び出してもいいけど同じフレームで何回も呼ぶのはどうなの?という感じだし
現在時刻で呼ぶか決めるのもアレだし)
あとAndroidの為にタッチパッドにも対応しなきゃならんか。
こちらはジェスチャーの判定をどうするかで悩む。SDLに何かあるのかね?自作なら自作でいいけどまた少し時間掛かりそうなんで
当面は1点のタッチとドラッグのみ対応しようか。
こちらはジェスチャーの判定をどうするかで悩む。SDLに何かあるのかね?自作なら自作でいいけどまた少し時間掛かりそうなんで
当面は1点のタッチとドラッグのみ対応しようか。
(2013/09/08)
描画スレッド
今時スマートフォンでさえクアッドコアが普通だし、本格的にゲームを作るならばシングルコアしか使わないなんてのは論外なのである。
シングルコアであってもCPUがGPUに待たされるとかその逆が起こりうるので、やはり描画処理は分けるべきなのだ。
アイコンがくるくる回るローディング画面を作ると単純に格好いいという話もある。
シングルコアであってもCPUがGPUに待たされるとかその逆が起こりうるので、やはり描画処理は分けるべきなのだ。
アイコンがくるくる回るローディング画面を作ると単純に格好いいという話もある。
C++11にはatomicやthreadが備わっていてこれらを使いたい所だが先日述べたように
libstdc++はpthreadを前提としてあり、libc++はそもそもwindowsに対応してないので今のところは使えない。
かといってvisualc++を使う気も微妙にc++11の文法が使えないのもあって、無い。
libstdc++はpthreadを前提としてあり、libc++はそもそもwindowsに対応してないので今のところは使えない。
かといってvisualc++を使う気も微妙にc++11の文法が使えないのもあって、無い。
そんな訳でSDLのスレッドやmutexを使う事にした。ざっとヘルプを読んだ所、基本的にはpthreadと同じ要領で使えるようだ。
(2013/09/07)
そしてゲームへ
そもそも何故Qtを使っていたかといえば「ゲームのエディタが作れればいいな」という事であって、
これでゲームを作ろうとするとサウンドの多重再生、ストリーミングとかジョイパッドとかフルスクリーンとかは
手間と速度的にどうなん?という感じだし
そうでなくともランタイムからして大きすぎるのでゲーム用にOS依存のアレコレをやる手段が必要である。
これでゲームを作ろうとするとサウンドの多重再生、ストリーミングとかジョイパッドとかフルスクリーンとかは
手間と速度的にどうなん?という感じだし
そうでなくともランタイムからして大きすぎるのでゲーム用にOS依存のアレコレをやる手段が必要である。
最低限の対象はWindowsオンリー。WinAPIなら多少は覚えているし、ウィンドウ出してちょっとしたメッセージ処理なら直に行けそうだが
OpenGLはあくまでもグラフィックスだけ。
サウンドはOpenALがあるが、ここに来て入力にDirectInputなんぞ使おうものなら一体何のためにOpenGLにしたのかわからなくなる。
従って素直にライブラリを使う。クロスプラットフォームでOS依存の面倒なアレコレを引き受けてくれる代物。
OpenGLはあくまでもグラフィックスだけ。
サウンドはOpenALがあるが、ここに来て入力にDirectInputなんぞ使おうものなら一体何のためにOpenGLにしたのかわからなくなる。
従って素直にライブラリを使う。クロスプラットフォームでOS依存の面倒なアレコレを引き受けてくれる代物。
候補として挙がったのはSDLとGLFW。
GLFWはミニマムな感じがSDLより気に入ったものの、これもやはりグラフィックスだけなので
サウンドと入力と画像ファイルの読み込みなども対応しているSDLに決まった。
ライセンスはLGPLだけど、有名所のゲームも結構使ってるし良い事にする。
なにより嬉しいのはiOSやAndroid対応という点。素晴らしい。
GLFWはミニマムな感じがSDLより気に入ったものの、これもやはりグラフィックスだけなので
サウンドと入力と画像ファイルの読み込みなども対応しているSDLに決まった。
ライセンスはLGPLだけど、有名所のゲームも結構使ってるし良い事にする。
なにより嬉しいのはiOSやAndroid対応という点。素晴らしい。
早速
早速コンパイル & インストール。特に何のエラーもなく完了。
サンプルを見つつ、とりあえずウィンドウ出してOpenGLで画面を塗りつぶすプログラムを動かしてみる。
サンプルを見つつ、とりあえずウィンドウ出してOpenGLで画面を塗りつぶすプログラムを動かしてみる。
順調過ぎて逆にビビる。
Attributeの設定はEGLの引数に似ているなぁ・・
Attributeの設定はEGLの引数に似ているなぁ・・
強制的にライブラリ専用のクラスとか使わされて中身全然弄れないよーという事もなく、
100人が書いたら90人同じになるような面倒くさい部分だけを引き受けてくれる印象で気に入った。
SDLはC++ではなくCで書かれており、リファレンスをざっと眺めたらそんなに関数も多くない。
100人が書いたら90人同じになるような面倒くさい部分だけを引き受けてくれる印象で気に入った。
SDLはC++ではなくCで書かれており、リファレンスをざっと眺めたらそんなに関数も多くない。
(2013/09/06)
rigid2d-test_v0.0.3-1 (windows & ubuntu)公開
といっても例によって見た目はあまり変わっておらず、フォント描画とVSyncの切り替えとGPU処理時間の表示だけ。
リソースマネージャの内部でメモリ破壊エラーが起きていて、原因究明でかなり時間食ってしまった。
とりあえず片がついたのでさっさと3Dに行く所存。
imageプラグインエラー : ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (rigi2.png)
リソースマネージャの内部でメモリ破壊エラーが起きていて、原因究明でかなり時間食ってしまった。
とりあえず片がついたのでさっさと3Dに行く所存。
今回はWinXPのスクリーンショット。・・・と思いきや、ドライバのバージョンが取得できてない事に気づいたが面倒なので放置
Ubuntu版は、少なくとも自分の環境では大丈夫だ。
Ubuntu版は、少なくとも自分の環境では大丈夫だ。
あと、可変長テンプレート引数の順番を逆にする
boost::variant<int,float> value[4];
template <class FUNC, class... Ts>
void action(FUNC func, Ts...) const {
// valueのサイズがsizeof...(Ts)と同じ前提
const auto* ptr = value + sizeof...(Ts);
func(boost::get<Ts>(*(--ptr))...);
}
このようなコードを書いていたらgccとclangで順番が逆になってしまうのは何とかせねば。
いや、そもそもWarning出るから好ましくない記述なのはわかるが自分の力量じゃこれが精一杯
いや、そもそもWarning出るから好ましくない記述なのはわかるが自分の力量じゃこれが精一杯
(2013/09/03)
VirtualTexturingについて色々勘違いしていた。
普通VirtualTexturingというと地形を覆う馬鹿でかい一枚のテクスチャ(65536x65536など)を、
それじゃあ一枚で12Gbも食ってVRAMに到底収まり切らないから詳細度が必要な部分だけ
予めタイル分けしておいたテクスチャを随時VRAMに乗せて使いましょうという技術のようだ。
なのでシーン内のテクスチャを一枚に纏めるのは単にRAGEでやってる拡張みたいなものだろうか。
普通VirtualTexturingというと地形を覆う馬鹿でかい一枚のテクスチャ(65536x65536など)を、
それじゃあ一枚で12Gbも食ってVRAMに到底収まり切らないから詳細度が必要な部分だけ
予めタイル分けしておいたテクスチャを随時VRAMに乗せて使いましょうという技術のようだ。
なのでシーン内のテクスチャを一枚に纏めるのは単にRAGEでやってる拡張みたいなものだろうか。
テクスチャのキャッシュについても特に決まった方式は無いみたいで、例えば128x128の固定サイズなタイルが一般的みたい。
ぶっちゃければ前に書いたような2D矩形のサイズ別管理とか要らないと言えば要らない。隙間できちゃうし。
ぶっちゃければ前に書いたような2D矩形のサイズ別管理とか要らないと言えば要らない。隙間できちゃうし。
VirtualTexturing関係なく単純にシーン内で使ってるテクスチャ全部纏めたいというなら使えなくもないが。
それでどの位パフォーマンス改善されるかはやってみないとわからんし、
ミップマップの対策も含めたらどの道VirtualTexturingのQuadTreeテクスチャみたく
ワンクッション必要だろうから・・・
どうだろう。逆に遅くなる可能性もある。
それでどの位パフォーマンス改善されるかはやってみないとわからんし、
ミップマップの対策も含めたらどの道VirtualTexturingのQuadTreeテクスチャみたく
ワンクッション必要だろうから・・・
どうだろう。逆に遅くなる可能性もある。
微妙な雰囲気になった所でとりあえずさっさとシャドウ無しのプレーンな3D表示だけやろうか。
その前に、折角フォント表示を入れた事だしカード情報やフレームレートの表示
VSyncのOn/Offを入れたバージョンでも出そうか。
その前に、折角フォント表示を入れた事だしカード情報やフレームレートの表示
VSyncのOn/Offを入れたバージョンでも出そうか。
(2013/09/02)
メガテクスチャに使うアルゴリズムを練り直し。
要は2Dの矩形領域を管理で、これが中々一筋縄ではいかない。
単なるメモリアロケータであればアドレスは1次元なので前後だけ気にしてれば連続した空き領域の結合なんてのは簡単に出来た訳だが2次元となると。
とりあえずブロックのサイズは2のべき乗で最低サイズは8x8、また正方形と横が2倍の長方形のみサポート。
8x8, 16x8, 16x16...という様な感じで最大4096程度まで。縦長のテクスチャを確保したい場合は横長をUV値変えて対応する。
要は2Dの矩形領域を管理で、これが中々一筋縄ではいかない。
単なるメモリアロケータであればアドレスは1次元なので前後だけ気にしてれば連続した空き領域の結合なんてのは簡単に出来た訳だが2次元となると。
とりあえずブロックのサイズは2のべき乗で最低サイズは8x8、また正方形と横が2倍の長方形のみサポート。
8x8, 16x8, 16x16...という様な感じで最大4096程度まで。縦長のテクスチャを確保したい場合は横長をUV値変えて対応する。
最初は隣接領域のポインタをとっておいて領域がFreeになったり分割されたりする度に周囲に伝えて反映してって感じで考えていたら
途中で面倒が過ぎて投げた。
次の案は4分木と矩形の当たり判定を使って空き領域を結合すれば隣接情報は要らなくなるからどうか・・・と思ったがこれもボツ。
フラグメンテーションを抑えたいだけなのにいちいち探索して、結合して、ポインタを繋ぎ変えてってやったとこで
使用中の領域は動かしようがないのだった。広間の中央が使用中だったらどう頑張っても周囲の細切れしか使えない。
途中で面倒が過ぎて投げた。
次の案は4分木と矩形の当たり判定を使って空き領域を結合すれば隣接情報は要らなくなるからどうか・・・と思ったがこれもボツ。
フラグメンテーションを抑えたいだけなのにいちいち探索して、結合して、ポインタを繋ぎ変えてってやったとこで
使用中の領域は動かしようがないのだった。広間の中央が使用中だったらどう頑張っても周囲の細切れしか使えない。
という訳でポーズやカットシーンとかのタイミングでテクスチャを再配置する事を前提にして考える。もっとシンプルなものを。