メタセコのプラグインをgithubへ
http://d.hatena.ne.jp/kataho/20071009/p1
ここの関連で。
プロバイダの利用を止めたので消えたコンテンツがいろいろありますが、メタセコのプラグインについてはコメントもあり、githubで公開すればタダで置けるしということで移動しました。
ここにあります。
https://github.com/kataho/N-Move-Metasequoia-Plugin
https://github.com/kataho/UVPressExpand-Metasequoia-Plugin
Downloadsのでっかいボタンででてくるダイアログの中のDownloadPackagesの項の下にzipアーカイブへのリンクがあります。
シャドウマップの解像度問題関連の諸技術について
シャドウマップのaliasing problemというのがある。光源方向と面の角度が近い部分に生じる影の例のギザギザであるが、これはカメラ近傍でバッファの解像度が足りないために起こる。一般的にカメラの視野は奥が広くなった錘台なのに対して、光源からの視野は平行光源なので直方体である。これで視錘台全体を単純に収めようとすると多くの無駄な部分が生じてしまうし、カメラの近傍が最も解像度が必要なのにも関わらず遠方と比べて小さな解像度しか確保されない。そこで、視野の錘台に対して光源の視錘台を様々にゆがませる手法が提案されてきた。
Perspactive Shadow Maps (PSM):
http://www-sop.inria.fr/reves/Marc.Stamminger/psm/
あらかじめカメラ方向からのprojection変換まですませたモデル(カメラから遠くが小さく近くが大きくなってる)をライト方向から見てZを描画する。無限遠光源のprojection変換はカメラ側で先に行われたprojection変換によってperspectiveなものに変更される。カメラとライトの角度が小さい場合、projection変換による変形は相殺され、いつもの扁平なシャドウバッファが描かれる。
Trapezoidal Shadow Maps (TSM):
http://www.comp.nus.edu.sg/~tants/tsm.html
PSMではカメラの動きが直接シャドウバッファの内容に大きな変化を与えるため、影が安定しなかった。(continuity problem)これを解決するため、カメラの視錘台を台形の断面をライトへ向けた柱体に近似するというのがTSM。これまたライトの向きがカメラに近づくと台形が描けなくなり意味がなくなる。
Light Space Shadow Maps (LiSPSM):
台形を求めるのが面倒くさいのでライト方向から見て90度の角度を向く錘台で近似する。ライト方向からはこの錘台の横っ面をいつも見ることになる。相変わらずカメラの向きとライトの向きの間の角度が小さくなると意味がなくなるし、カメラやライトがお互いの近くを移動すると錘台の角度が急激に変動しシャドウバッファの内容が大きく変わる。
シャドウバッファの内容を連続的にゆがませるのは限界が見えている。PSM以降のものはPSMの問題を根本から解決しているわけでなく、PSMでカメラとライトの角度に比例して解像度が落ちていくcontinuity problemを別の錘台を近似させることである程度角度が小さくなりきるまで破綻を抑制しているだけである。FPSならいいのだが、斜め見下ろしサードパーソンの場合、光源方向とカメラ方向の角度がほとんど重なってしまう場面が頻発するため、PSM系は全く使えないとしても言いすぎでない。また、モデルの一部分におけるシャドウバッファ上の解像度は一定に定まらないためシャドウマップをぼかして行うソフトシャドウ手法を併せて実装できないというのも個人的には欠点だ。このソフトシャドウが大好きなので。
Cascading Shadow Maps (CSM):
http://appsrv.cse.cuhk.edu.hk/~fzhang/pssm_vrcia/index.html
CSMは視錘台を複数に輪切りに切り分けて平坦なシャドウバッファを複数描く方法である。PSMの系譜に無いまったく別個のアイデア。ある程度の重なる部分をもたせてカメラからの距離によって視錘台を分割、これらにライトからの視野をピッタリ合わせてライトからのZを描画する。参照するときは複数のバッファのすべてをフェッチして、結果をピクセルシェーダ上でフェードしながら表示する必要がある。カメラからの距離を境界前後でclampしたものをフェードのパラメータとして用いる。3分割するのが一般的なようだが、2分割でも十分な性能を発揮する。ゲームの内容によっては、コストのかかるオブジェクトは近傍のバッファにしか描かないようにしてパフォーマンスを稼ぐなど細かな調整をすることもかんがえられるし、可能性は無限大。
もうPSM系はめんどいから黙ってCascading Shadow Mapsを使えばいいと思うよ。
http://videogameprogramming.blogspot.com/2006/03/cascading-shadow-maps.html
C++インスタンス関数を呼び出すSquirrelインスタンス関数(マイフェイバリットな)
SQPlusはC++のインスタンスをinstanceupへ、関数ポインタをfunctionのfree variableへいれてる。free variable分はいらなくないか?と思ったので。自分はこんなふうに書いた。テンプレートってホント融通きくなあ。
inline static void mysq_register_function(HSQUIRRELVM v, const char* name, SQFUNCTION func, int numparams, const char* paramtype, SQBool bstatic = SQFalse) { sq_pushstring(v,name,-1); sq_newclosure(v,func,0); if(paramtype) sq_setparamscheck(v,numparams,paramtype); sq_setnativeclosurename(v,-1,name); sq_newslot(v,-3,bstatic); } template <typename T, int(T::*FUNC)(HSQUIRRELVM)> static int _mysq_instance_nativeclosure(HSQUIRRELVM v) { T* g = (T*)_instance(stack_get(v,1))->_userpointer; return (g->*FUNC)(v); } #define MYSQ_REG_INSTANCE_LINKED_FUNCTION(VM,CLASS,FUNCNAME,PNUM,FORMAT) \ mysq_register_function(VM,#FUNCNAME,_mysq_instance_nativeclosure<CLASS,&CLASS::FUNCNAME>,PNUM,FORMAT)
で、こんな風に使える。
SQObjectPtr sqclass; _table(v->_roottable)->Get(SQObjectPtr(SQString::Create(_ss(v),"Agent")),sqclass); sq_pushobject(v,sqclass); MYSQ_REG_INSTANCE_LINKED_FUNCTION(v,MobBotWithAI,WalkTo, 2, ".x"); MYSQ_REG_INSTANCE_LINKED_FUNCTION(v,MobBotWithAI,Attack, 0, ".ix"); MYSQ_REG_INSTANCE_LINKED_FUNCTION(v,MobBotWithAI,Track, 2, ".x"); sq_poptop(v);
Squirrelのインスタンスをつくるときは紐付けるC++のインスタンスをsq_setinstanceupすることを忘れずに
mysq_call(v,true,-1,"Agent"); m_sqagent = stack_get(v,-1); // C++ -> Squirrel の参照 _instance(m_sqagent)->_userpointer = this; // C++ <- Squirrel の参照
最近はできるだけスタックを使わないのがマイブーム。
なんかおいしくないな〜
と思ったが画面更新の間のたりない部分を補間してるだけだからそりゃものがあるべき様にみえるだけでおいしい演出とは違うよな。つまりこれを仮に全画面的に適用したとしても「おおおおお〜」とはならないということだ。「いつも見てる通りじゃん?それが何か?」ってなる。間違いない。
パーティクルへのモーションブラー
実際の環境ではオブジェクトの移動によって像が乱れてノイズが入ることはなく単位時間で一点から反射して目に入ってくる光の量が移動によって広範囲に分散して一点においては減少するだけだ。つまり移動量に応じて像が伸びて伸びた分透過するようになるだけ。透明度alpha = 物自体の移動方向の長さ/(物自体の移動方向の長さ+移動距離)という仮説を実装してみた。ただ3Dオブジェクトだと頂点を毎回ロックして計算しなくてはならないのであきらめ。いつもどの向きへ動いても長さが一定な円いパーティクルだけに実装してみた。移動した方向へ回転させても問題ないし、像を延ばすのも2面を間に加えるだけなので簡単軽量である。
モーションブラーというより光の線型補間のようなものかもしれん。ブラーしてないし。
SQCAGE_VERTEX tex_v_default[] = { {D3DXVECTOR3(-0.5f, -0.5f, 0), 0xffffffff, 0.0f, 0.0f }, {D3DXVECTOR3(-0.5f, 0.5f, 0), 0xffffffff, 0.0f, 0.0f }, {D3DXVECTOR3(0.5f, 0.5f, 0), 0xffffffff, 0.0f, 0.0f }, {D3DXVECTOR3(0.5f, -0.5f, 0), 0xffffffff, 0.0f, 0.0f }, };
m = mscale * mbillboard; const D3DXMATRIX currentworldviewproj = COMPTRANS(D3DXMATRIX(IDENTITYMATRIX),arg.pos) * viewproj; const D3DXVECTOR2 currentprojpos(currentworldviewproj._41,currentworldviewproj._42); map<int,D3DXMATRIX>::iterator found = m_lastworldviewprojmap.find(arg.id); const D3DXMATRIX lastworldviewproj = (found == m_lastworldviewprojmap.end()) ? currentworldviewproj : found->second; const D3DXVECTOR2 lastprojpos(lastworldviewproj._41,lastworldviewproj._42); D3DXVECTOR2 vmotion(currentprojpos - lastprojpos); float vmotionlen = D3DXVec2Length(vmotion); // 透明度を算出 float size = arg.scale; color.a *= size / (size + vmotionlen); if(vmotionlen > 0) vmotion /= vmotionlen; // normalize D3DXMATRIX mboardrot; // get rotation matrix D3DXMatrixRotationZ(&mboardrot, (vmotion.y<0?1.0f:-1.0f) * acosf(-vmotion.x /*(-1,0)との内積*/) ); m = mboardrot * m; // 移動方向への回転を適用 D3DXMATRIX mlast = m * lastworldviewproj; D3DXMATRIX mcurrent = m * currentworldviewproj; D3DXVec3TransformCoordArray((D3DXVECTOR3*)v,sizeof(SQCAGE_VERTEX),(D3DXVECTOR3*)tex_v_default,sizeof(SQCAGE_VERTEX),&mcurrent,2); D3DXVec3TransformCoordArray((D3DXVECTOR3*)(v+2),sizeof(SQCAGE_VERTEX),(D3DXVECTOR3*)(tex_v_default+2),sizeof(SQCAGE_VERTEX),&mlast,2); v[0].color = v[1].color = v[2].color = v[3].color = (DWORD)color; v[0].tu = v[1].tu = arg.texgeom[0]; v[1].tv = v[2].tv = arg.texgeom[1]; v[2].tu = v[3].tu = arg.texgeom[0] + arg.texgeom[2]; v[0].tv = v[3].tv = arg.texgeom[1] + arg.texgeom[3]; memcpy(&v[4],&v[0],sizeof(SQCAGE_VERTEX)); memcpy(&v[5],&v[2],sizeof(SQCAGE_VERTEX)); m_lastworldviewprojmap[arg.id] = currentworldviewproj;