FPSを作ってみる@wiki
06)
最終更新:
slice
-
view
(2014/06/22)
左下に軸表示するとモデラーぽくて格好良いね
とはいえ、まだそんな事やってるのかという・・
いつも通りgit履歴を見ながら書く。
テクスチャ表示はオマケ。こんなんチャッチャとやればパッと出るわみたいな。
いつも通りgit履歴を見ながら書く。
テクスチャ表示はオマケ。こんなんチャッチャとやればパッと出るわみたいな。
OpenGL APIのラップ
OpenGLの関数を読み込んでそれをラップしたクラス経由でAPIを呼び出す仕様なのだが
Debug版では自動的にglGetErrorによるエラーチェックを挟み、何かエラーがあればコンソールに出力するようになっている。
(勿論glGetError自体はチェックしない)
OpenGLを真っ当に使うならそれで問題無さそうだし
「もし問題あっても、コンソールに出力されるだけだからいいよな・・・」と放置していた。
例えばGLSLシェーダーに特定のuniform変数が存在するかをチェックする場合
仮に無かったからと言ってエラーにはならない。
Debug版では自動的にglGetErrorによるエラーチェックを挟み、何かエラーがあればコンソールに出力するようになっている。
(勿論glGetError自体はチェックしない)
OpenGLを真っ当に使うならそれで問題無さそうだし
「もし問題あっても、コンソールに出力されるだけだからいいよな・・・」と放置していた。
例えばGLSLシェーダーに特定のuniform変数が存在するかをチェックする場合
仮に無かったからと言ってエラーにはならない。
が、先日とある箇所のデバッグをしていたらその「何でも無い」警告がエラー出力を埋め尽くしてしまい
バグに直結するようなエラーやログが検索しないとわからない、見通しが悪い、
1フレームに何百個も発生していたらさすがに遅い等の問題に遭遇した。
当たり前っちゃあ当たり前だ。
バグに直結するようなエラーやログが検索しないとわからない、見通しが悪い、
1フレームに何百個も発生していたらさすがに遅い等の問題に遭遇した。
当たり前っちゃあ当たり前だ。
そんな訳でどうするか考えた結果、Debug時でもエラーチェックをしないバージョンのラップ関数を用意する事で落ち着いた。
glGetUniformLocation() という関数なら glGetUniformLocation_NC()みたいな感じ。
勿論Release時はどちらを呼んでも同じ動作にした。
glGetUniformLocation() という関数なら glGetUniformLocation_NC()みたいな感じ。
勿論Release時はどちらを呼んでも同じ動作にした。
AMDのドライバにハマる
AMDのドライバがクソと言われる所以が少し、わかったような。
結論を先に書くとAMDドライバではGLSLに整数を渡す時にglVertexAttribIPointer()を使わないと値が化ける。
更にGLSL側でfloatで受けたりしても駄目、逆にfloat -> intも駄目。
Nvidiaとかだと普通に動きそうな気がする。
更にGLSL側でfloatで受けたりしても駄目、逆にfloat -> intも駄目。
Nvidiaとかだと普通に動きそうな気がする。
GLSLのattribute変数(頂点入力変数)にソースを渡す時は
VertexBufferObjectを使うかによらず大体、glVertexAttribPointer()を使うと思うのだけど
これが曲者で。
VertexBufferObjectを使うかによらず大体、glVertexAttribPointer()を使うと思うのだけど
これが曲者で。
APIの公式リファレンスを見るとglVertexAttribPointer()以外にも
整数専用のglVertexAttribIPointer()や64bit浮動少数点数用のglVertexAttribLPointer()なんてのがあったりするが
glVertexAttribPointer()にはGL_INTも渡せると書いてある。
公式に書いてあるし、そもそもOpenGL ES2にはIPointerの方は無いのでglVertexAttribPointer()だけで組んでいたら
整数を渡すと値が化ける事に気づき・・
整数専用のglVertexAttribIPointer()や64bit浮動少数点数用のglVertexAttribLPointer()なんてのがあったりするが
glVertexAttribPointer()にはGL_INTも渡せると書いてある。
公式に書いてあるし、そもそもOpenGL ES2にはIPointerの方は無いのでglVertexAttribPointer()だけで組んでいたら
整数を渡すと値が化ける事に気づき・・
かなり時間食った。
その他
自作ライブラリの細々としたバグ修正など。
あと、最近プログラミングや3DCG以外に取り組んでる事があるとだけ。
(2014/06/12)
例のごとくまた放置してしまった。
相変わらずプレビュー表示で止まってる訳だけど、まぁ進んでいると言えば進んでる。
相変わらずプレビュー表示で止まってる訳だけど、まぁ進んでいると言えば進んでる。
見た目の変化といえばグリッドに色がついてノードの軸表示が出来ただけっていう。
前回から何をしたかなんて忘れてしまったのでgitのログで振り返ると
前回から何をしたかなんて忘れてしまったのでgitのログで振り返ると
- コンパイル環境をC++11からC++14に移行
- 階層構造を持ったモデルを描画する為の機構
- 上と関連してスキンメッシュ描画の色々
- ベクトルの初期化と代入のstd::initializer_list対応
- Uniform変数配列に対応
- システムUniform変数を管理するクラス
- 更新フラグ管理のクラス
- Actorクラス
こんなとこである。
コンパイル環境をC++11からC++14に移行
新しい規格という感じもあまりしなくなったし、もうそろそろ使ってもいいんじゃないかと思ったので。
主に汎用ラムダキャプチャ、ジェネリックラムダ、関数の戻り値推定など。
他にも色々機能が追加されてるようだが自分は上記が目当て。
主に汎用ラムダキャプチャ、ジェネリックラムダ、関数の戻り値推定など。
他にも色々機能が追加されてるようだが自分は上記が目当て。
階層構造を持ったモデルの描画
モデルから関節ノードを読み込んでそれぞれの角度や位置を描画時に反映してって
要するにキャラクターを描画するってだけで。スキンメッシュも対応はしてあるがまだテストしてない。
要するにキャラクターを描画するってだけで。スキンメッシュも対応はしてあるがまだテストしてない。
ベクトルの初期化と代入のstd::initializer_list対応
ベクトルの初期化は今までVec3 v(1,2,3) としか出来なかったのをVec3 v = {1,2,3}と記述できるようにし、
関数の引数にもAddVector({0,1,0}, {1,0,0})といった感じで直接書けるようにした。行列も同様。
なんで今までやってなかったんだろうというレベル。
関数の引数にもAddVector({0,1,0}, {1,0,0})といった感じで直接書けるようにした。行列も同様。
なんで今までやってなかったんだろうというレベル。
Uniform変数配列に対応
これもなんで今まで(略
システムUniform変数を管理するクラス
World、View、Projection、Transform行列(World*View*Projection)や、
EyePosition, EyeDirectionベクトルなんかのよく使うuniform変数は
ライブラリ側で名前を決めてしまったほうが管理が楽そうだと思ったのでそうした。
World行列が更新されたらWorldの逆行列やTransformは計算し直しする等のフラグ管理なんて
アプリケーションごとに何度も書きたくないし。
EyePosition, EyeDirectionベクトルなんかのよく使うuniform変数は
ライブラリ側で名前を決めてしまったほうが管理が楽そうだと思ったのでそうした。
World行列が更新されたらWorldの逆行列やTransformは計算し直しする等のフラグ管理なんて
アプリケーションごとに何度も書きたくないし。
更新フラグ管理のクラス
変数同士の依存関係をマクロで記述したら後はフラグ管理を
自動でやってくれるようなテンプレートクラスも作ったりした。
マクロというのが若干格好悪いがいつもキャッシュ変数を持ったクラスを書く時のモヤモヤが解消したので良しとする。
ソースコードはGitHubにあるのだが簡単に説明すると
自動でやってくれるようなテンプレートクラスも作ったりした。
マクロというのが若干格好悪いがいつもキャッシュ変数を持ったクラスを書く時のモヤモヤが解消したので良しとする。
ソースコードはGitHubにあるのだが簡単に説明すると
boost::preprocessorのsequenceを使って
(キャッシュ名)(変数型)(依存キャッシュ名0)(依存キャッシュ名1)...
という形で依存関係を記述する
(キャッシュ名)(変数型)(依存キャッシュ名0)(依存キャッシュ名1)...
という形で依存関係を記述する
上記の行列であれば
(World)(Mat44)
(View)(Mat44)
(Projection)(Mat44)
(WorldInv)(Mat44)(World)
(Transform)(World)(View)(Projection)
こんな感じになる。
World, View, Projectionは4x4行列変数で、他の何にも依存しておらず
WorldInvはWorldに依存し、TransformはWorldとViewとProjectionに依存している。
(World)(Mat44)
(View)(Mat44)
(Projection)(Mat44)
(WorldInv)(Mat44)(World)
(Transform)(World)(View)(Projection)
こんな感じになる。
World, View, Projectionは4x4行列変数で、他の何にも依存しておらず
WorldInvはWorldに依存し、TransformはWorldとViewとProjectionに依存している。
各変数は、これまたマクロで自動記述されたgetXXX()という関数で取得するようになっていて戻り値がconst参照である。
getWorld()を呼ぶと何もチェックをせずそのままconst Mat44& (中身はWorld) が返り、
getWorldInv()はWorld変数が更新されていれば別途ユーザーが記述した
関数refresh(Mat44& mWorldInv, World*)の内部でgetWorld()を使って再計算した上でconst Mat44& (中身はWorldInv)を返す。
といった具合。
getWorldInv()はWorld変数が更新されていれば別途ユーザーが記述した
関数refresh(Mat44& mWorldInv, World*)の内部でgetWorld()を使って再計算した上でconst Mat44& (中身はWorldInv)を返す。
といった具合。
Actorクラス
名前からしてありがちで説明の必要も無いんじゃないかという程だが一応。
モデルと関節ポーズを内部に持ち、draw関数でポーズを適用しつつ描画する物。
このクラスもそうだがFBXローダーもまだまだ作成途中なのでGitHubに上げてない。
モデルと関節ポーズを内部に持ち、draw関数でポーズを適用しつつ描画する物。
このクラスもそうだがFBXローダーもまだまだ作成途中なのでGitHubに上げてない。
予定
引き続きFBXローダー。
以上
以上