スポンサーサイト

--年--月--日 --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

シェーダー開発ツール 4

2006年10月21日 21:56

昨日実装した処理をツールに組み込むため、UIを作って実際に使えるような形にしてみました。

shaderedit4.jpg


実際は、リストビューとかから右クリックで呼び出すだろうけど、
シェーダー定数管理リストウィンドウとかまだ用意して無いのでツールバーにボタン追加して呼び出してます('A`)

なんかやること結構おおいなぁ。。
大変だけど、ちょっとずつ作っていきますよ( ・`ω・´)

blog_rank
スポンサーサイト

動的にシェーダー定数をプログラム

2006年10月20日 16:12

ってことで、上記タイトルの機能を あるけ が趣味で作ってるシェーダー編集エディターに追加しました。

既存のシェーダーの開発ツールとしては nVidia の FX Composer や ATI の RenderMonkey があります。
どっちのツールも定数レジスタを設定することは出来るけどプログラムすることは出来ませんでした。
射影行列を作ったり、ライトの位置を簡単な円運動させたり、そういうことは出来なかったわけです。

もちろん、定数を設定するだけなら出来ます。
たとえば、HDRの閾値を入力したり。

しかし、実際にゲームで使う場合、定数レジスタに設定する値は複雑な演算を行ったり、
計算で求めたベクトル同士の内積の値を突っ込んだりします。
そういう細かな定数レジスタの設定は、出来ませんでした。

あるけ はプログラマなので、別にスライダーなどで定数レジスタが弄れなくても、簡易的なプログラムが書け、それで定数レジスタを制御できる方がうれしいです。


・・・ってことで、Closure の機能をバリバリ使ってタイトルの機能を追加しました。
アプリケーションの中でプログラムを入力すると、構文解析を行い、エラーが無ければプログラムを構築します。

どんなことが出来るか?というと、、、


char pProgram[] = "\
 VEC vTest  = init(1,0,0); \
 MAT mtTest  = rotY( rad(cnt()) ); \
  \
 return vTest * mtTest;\
"
;



こんな感じのプログラムがあるとします。
cnt() っていうのは1フレームに1ずつ増えるカウンタを返す関数、rad() は与えられたパラメーターを Degree から Radian にする関数、init() はベクトルの初期化関数、rotY() はY軸回転の行列を返す関数です。

このテキストをほいさーって感じに Closure のジェネレーターに突っ込んでやると、これを評価する Closure が返ってきます。
後は、値が欲しい時に Closure を評価してやれば、この Closure が計算し、「Y軸周りに回転するベクトル」を取得することが出来るわけです。


Closure を使ってるので、他のプログラムの中でこのプログラムを呼び出すことも可能です。
スクリプトに見えますが、インタプリタで動いてるわけでなく、式を保存しているので Closure を評価するだけで式の実行を行います。

関数型プログラムの悪い欠点で、あまり長いプログラムはスタック食いつぶすだろうから書けないけどねw
シェーダー開発ツールはこの機能を入れてもうちょっと機能を追加したら、公開しようかな?って思ってます。


ためしに作ったようなものだけど、他のゲーム会社とかでも使われたら最高だね~w


blog_rank

日本の借金

2006年10月12日 16:50

よく言われる件に「日本の借金は1000兆円近くある!」っていうのがあります。

日本は多額の債務国でもありますが、逆に多額の債権国でもあります。また日本の債務は内需で行われてることも考慮しておく必要があります。
いざとなったらインフレ率の調整でなんとかなるわけです(円建ての債務なので)
対外債務自体はきわめて少ないです。

だからといって、急激なインフレが起こると国債の信用付けも円の価値も紙切れ同然になりアルゼンチンのような状態になりますが、、、。

また、日本の対外資産は1.8兆ドルあります。
日本円で換算すると200兆円ほどです。
もちろん、全部が日本政府の持ち物ではありませんが、世界一の対外資産を保有している国です。


しかし、だからといって安泰か?と言われるとやはり借金は少ない方がいいに決まってます。


危機を声高に叫ぶだけではダメです。
「何が危ないのか?」をはっきり明確にしないといけません。
仕事と同じですね。

そのためにも特別会計の一般財源化を行い透明な歳入と歳出にし、パチンコ・パチスロ税の導入、バランスシートの改善などを行えば大分変わります。
もっとも、抵抗勢力(多くは利権議員)が強い部分ばかりですが。。。
(特に利権が少ない警察族は絶対にパチンコ・パチスロ業界を守ろうとするでしょう)

日本人の悪い癖は無関心もそうですが表面上でしか物を語らないというところもあると思います。
ワイドショウ型と申しましょうか。。。
政治に無関心なのも自分の立ち位置さえも判らない人が多いのが原因ではないでしょうか?

真に考えてる人が多数いる日本なら利権議員をのさばらせるようなことにはならないはずです。
たった1票かもしれないけど政治に参加するということの大切さをもっと教えて欲しいです。


blog_rank

静的なキャストを利用したテンプレート

2006年10月10日 16:29

Closure のこと書きたいんだけど、書くのが長くなりそうであまり気が進みません('A`)

ってことで、微妙に近いようで遠いい C++ 言語のトリックのこと書こうと思ってます。
トリックって言っても、テンプレートのトリックなんだけどね(・∀・)


んで、今日書くことは、「テンプレートで静的にスーパークラスへのキャストを行い、静的に呼び出す関数などを置換しちゃう方法」です。


・・・まぁ、上の一文で判っちゃう天才はいないと思うので具体的に例を挙げましょう。
通常、あるクラスのポインタを引数とする関数を呼ぶ時に、そのクラスから派生したクラスを渡すことも可能です。
(仮想継承や多重継承は除く)
たとえば、、、



class A
{
  ・・・
};


class B : public A
{
  ・・・
};


void TestFunc( A * )
{
}


・・・

B *p = new B();
TestFunc( p );  ← キャストしなくてもOK暗黙のキャストが適応される




ってことです。

TestFunc を呼ぶとき、引数として渡す値は A の派生クラスの実体なら別にAにキャストしなくてもOKなワケです。


しかし、特殊化したテンプレートで似たようなことをすると、キャストは明示的に行わないとダメです。

たとえば、、、



template< typename ReturnType >
struct TCFunctor
{
  virtual ReturnType operator()() const PURE;
};


template< typename ReturnType >
struct TCFuncA : public TCFunctor< ReturnType >
{
  virtual ReturnType operator()() const
  { return -1;  }
};



template< typename ReturnType >
struct TCFuncB : public TCFunctor< ReturnType >
{
  virtual ReturnType operator()() const
  {  return 1;  }
};


template< typename ReturnType >
struct PatternTest
{
  template< typename T >
  struct Absorber
  {
    static ReturnType Execute( const T &t )
    {  return 0;  }
  };


  template< typename T >
  struct Absorber< TCFunctor< T > >
  {
    static ReturnType Execute( const TCFunctor< T > &t )
    {  return t();  }
  };


  template< typename T >
  static ReturnType Test( const T &t )
  {  return Absorber< T >::Execute( t ); }
};


・・・

TCFuncA< int >  HogeA;
TCFuncB< int >  HogeB;

printf( "%d\n", PatternTest< int >::Test(HogeA) );
printf( "%d\n", PatternTest< int >::Test(HogeB) );



これを実行した時、表示されるのは


0
0



となります。

TCFuncA と TCFuncB で実装した operator () を呼んで欲しいのですが呼ばれていません。
明示的にキャストしていないため、TCFunctor< T > に特殊化した PatternTest::Absorber の方の Execute を呼んでくれないためです。


さて、ではどうするか?

一番簡単な答えは、 TCFuncA、TCFuncB それぞれの PatternTest::Absorber の特殊化を用意することです。
これなら間違いなく、それぞれが実装した operator () を呼んでくれます。


しかし、これだと TCFunctor の派生クラスが増えるごとに PatternTest クラスに特殊化を記述しないといけません。
これだとはっきり言って面倒な上、万が一追加し忘れた場合、バグの原因にもなりかねません。


実は呼ぶ方法自体はあります。



template< typename T >
static ReturnType Test( const T &t )
{  return Absorber< T >::Execute( (const < TCFunctor< ReturnType > &)t ); }


  
または


printf( "%d\n", PatternTest< int >::Test((TCFunctor< int > &)HogeA) );
printf( "%d\n", PatternTest< int >::Test((TCFunctor< int > &)HogeB) );



などのようにキャストしてやればOKです。
しかしそれぞれに問題点があります。

まず、上の方法では TCFunctor から派生したクラス以外の「型」が来た時、間違いなくエラーが起きます。
当たり前ですね。違う型のポインタを強引にキャストしてるんですもん。

下の方法は特に問題はありませんけど、いちいち明示的にキャストしてやらないといけなくなり面倒です。
また、キャストの記述を忘れちゃうとこれまた予想外の処理にまわされる可能性があります。
そんなわかりきったものは暗黙的で安全にやってもらったほうがいいに決まってます。


ってことで、暗黙的に(実際は明示的にやるしか方法はないんだけど、プログラマーが触る辞典では暗黙のうちに)処理される方法を書きます。


結局、明示的にキャストしてやるしか方法はありませんので、これを応用します。
要するに、実際に渡されたクラスが TCFunctor から派生されたのかどうか判別できればいい訳です。

C# とかと違って、普通は出来ないんですけどね。
(C# は確か super っていう this みたいなヤツあるよね?)
ここでトリックを使うと出来ちゃいます。
・・・ちょっと制約食らうけど('A`)


さてやり方は、、、



template< class TDST, class TSRC >
class CastCheck
{
private:
  typedef char (&yes)[1];
  typedef char (&no) [2];

  static yes isCast(TDST *);
  static no  isCast(...);

public:
  enum
  {  value = sizeof( isCast( (TSRC *)NULL ) ) == sizeof(yes)   };
};





こんなクラスを用意します。
あるけ が自作したクラスです('A`)

sizeof で出来るかどうかをチェックしてるところがポイントです。
sizeof で関数を呼び出すことにより、存在するかしないかをチェックしてるわけです。
sizeof はコンパイラが処理するので関数の実体が呼ばれることがないためです。


効果は、そのものズバリ!「キャストできるかどうかチェックするクラス」です。

ためしに


struct A
{
};


struct B : public A
{
};


struct C
{
};


・・・

printf( "%d\n", CastCheck< A, B >::value );
printf( "%d\n", CastCheck< A, C >::value );



ってやってみてください。


1
0


と表示されると思います。


このクラスを利用すれば「TCFunctor から派生したかどうか?」をチェックすることが出来ます。

あと、もう一つ、「フラグをみて静的に2つの型のうち1つを選択する」機能も必要ですね。
TCFunctor の派生クラスじゃ無い場合はそのまま T を渡して欲しい時に使用するためです。

このクラスは Boost などでもおなじみの Select テンプレートを使用します。


template < bool flag, typename T, typename U >
struct Select
{
private:
  template< bool >
  struct In
  { typedef T Result; };

  template< >
  struct In< false >
  { typedef U Result; };

public:
  typedef typename In< flag >::Result Result;
};




これで、上手く処理できそうです。
それじゃ本題に戻って、上手く動作するように変更してみましょう。




template< typename ReturnType >
struct PatternTest
{
  ・・・
  
  template< typename T >
  static ReturnType Test( const T &t )
  {  return Absorber
      <
        typename Select< CastCheck< TCFunctor< ReturnType >, T >::value, TCFunctor< ReturnType >, T >::Result
      >::Execute
      (
        (const typename Select< CastCheck< TCFunctor< ReturnType >, T >::value, TCFunctor< ReturnType >, T >::Result &)t
      );
  }
};




さて、上の部分を修正して実行してみましょう。
見事


-1
1



と表示されると思います。



blog_rank

球面調和関数

2006年10月05日 16:06

今回は最新技術に関する情報のメモでも。

表題の通り、球面調和関数によるモデルの近似についてです。
http://journal.mycom.co.jp/articles/2006/09/23/cedec4/
球面調和関数って言うのは2次元のフーリエ変換みたいなもんらしい。
これ使えばモデルの形状を計算しやすい形で保持することが可能ですね。

そうすればアンビエントオクルージョンだったりレイトレーシングだったりコリジョンだったりテンソル計算にだったり使えそう。
なんか期待できそうな技術だ(・∀・)

blog_rank

スキル寄せ集め

2006年10月03日 23:24

まとめ!

なわけで、パララックス+セルフシャドウ+HDRなサンプルを作成しました。

Indicator.jpg



モデルはデザイナの友人から借りましたw

ファーもいれたかったんだけど、とりあえず保留。。
やることあるし('A`)

さて決戦の準備は整いましたよ!


blog_rank

MoMA Online Store

2006年10月03日 14:59

たまには仕事関係以外のことも。
そんなわけで、ずいぶん久々だけどインテリアのこと話します。

っていっても、今日はオンラインストアの紹介だけ。
紹介するお店はここ。

MoMA Online Store Japan

NYMoMA.jpg



MoMA といえば、Monument of Modern Art
日本語訳すれば近代美術館です。
ニューヨークのが有名ですね。

このオンラインストア、そのニューヨーク近代美術館に展示されている工業製品を売っているお店です。
たとえば、柳宗理のカトラリーだったりイームズの椅子だったりバントンのファニチャーだったり、、、。

そんなステキアイテムをオンラインで買えちゃうお店なのです。
ちょっと値段は張りますが、おしゃれなインテリアを目指すならゼヒ色々そろえてみましょう♪


blog_rank

Parallax Map

2006年10月02日 23:09

ってことで、今日も3Dのお勉強。

視差マップ。パララックスマッピングっていうやつですね。

Parallax.jpg


高さ情報+法線マップで行います。
高さ分だけ(デカールも法線も)フェッチするUV値をずらすだけっていうお手軽なワリに擬似的な立体感を与えてくれるお得な技術です。
考えた人すごいねー。



blog_rank


最近の記事


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。