ShaderLabの構文メモ

構文
 Shader "name" { [Properties] Subshaders [Fallback] }

■Shader
 1ファイルに一つだけ。XMLのrootみたいなもん。
■Properties
 ここに書いたやつはマテリアルのインスペクタに表示されるようになる。色だったり、テクスチャだったり。
■Subshaders
 シェーダーは複数のSubshadersから構成される。少なくとも一つ必要。
 複数Subshadersがある場合、シェーダーロード時に実行環境でサポートされる一番最初のシェーダーを使用する。
 サポートのチェックは上から順番に行う。
 もし、サポートされるシェーダーが無ければFallbackシェーダーの利用を試みる。

ID3DX10ThreadPump メモ

非同期にテクスチャなどのロードが行えるID3DX10ThreadPumpというものを知ったのでそれのメモ。
データローダーとデータプロセッサーというクラスを独自に作成することでいろいろなフォーマットのロードに対応できます。
参考URL
http://msdn.microsoft.com/ja-jp/library/ee420231
http://www.gamedev.net/blog/272/entry-1790507-id3dx10threadpump-how-to/

とりあえずためしに作ってみたデータプロセッサ。 そのまま通りませんがとりあえず雰囲気だけでも。

/**
 * @file ASyncMemLoadProcessor.h
 * @brief ThreadPumpで使用するデータプロセッサ。ただのメモリ読み込み
 */
class ASyncMemLoadProcessor : public ID3DX10DataProcessor
{
public:

	/**
	 * @brief バッファ情報。メモリ読込先バッファ以外に読み込みが完了しているかのフラグを持つ。
	 */
	class BufInfo
	{
		friend ASyncMemLoadProcessor;
	public:
		BufInfo();
		/**
		 * @param bufSize バッファサイズ
		 * @param buf 読み込みバッファ
		 */
		BufInfo( u32 bufSize, void* buf );
		void init( u32 bufSize, void* buf );

		bool valid() const { return (_buf != NULL); }
		bool isReady() const { return (valid() && _ready); }

		// アクセサ
		const void* getBuf() const { return _buf; }
		void*	  getBuf()        { return _buf; }
		void*&	   getBufRef()     { return _buf; }
		u32	   getSize() const { return _bufSize; }
	private:
		void setReady() { _ready = true; }
		void* _buf;	//! バッファ
		u32 _bufSize;	//! バッファサイズ
		bool _ready;	//! 準備完了フラグ
	};

         // これらの関数を独自に定義する
	COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE CreateDeviceObject( void **ppDataObject );
	COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE Destroy();
	COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE Process( void *pData, SIZE_T cBytes );

	/**
	 * @brief 生成関数
	 * @param bufInfo バッファ情報
	 */
	static ASyncMemLoadProcessor* Create( BufInfo& bufInfo ) { assert( bufInfo.valid() ); return new ASyncMemLoadProcessor( bufInfo ); }
private:
	ASyncMemLoadProcessor( BufInfo& bufInfo );
	ASyncMemLoadProcessor(const ASyncMemLoadProcessor& obj) {} 
	~ASyncMemLoadProcessor(){}

	BufInfo* _bufInfo; 	//! 処理対象のバッファ情報
	void* _bufCur;	//! 現在のバッファ処理位置
};
/**
 * @file ASyncMemLoadProcessor.cpp
 */
COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE ASyncMemLoadProcessor::CreateDeviceObject( void **ppDataObject )	
{
	_bufInfo->setReady();
	return S_OK;
}

COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE ASyncMemLoadProcessor::Destroy()
{	
	delete this;
	return S_OK;
}

COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE ASyncMemLoadProcessor::Process( void *pData, SIZE_T cBytes )
{
	memcpy( _bufCur, pData, cBytes );
	_bufCur = (u8*)_bufCur + cBytes;
	return S_OK;
}

クラスがごちゃごちゃしていますが、最低限必要なことは上の3つの関数を定義です。
CreateDeviceObject,Destroy,Process の3つの関数を独自に定義することで様々な処理が行えます。

実際に使ってみる。

/*
 * @file testThreadPump.cpp
 * @brief ID3DX10ThreadPumpのテスト
 */ 
class testThreadPump : public Task
{
public:
	testThreadPump( void );
	virtual ~testThreadPump( void );
	virtual void func( void );

	ASyncMemLoadProcessor::BufInfo _bufInfo;
	ID3DX10ThreadPump* _pPump;
	void* _dat;	
};

testThreadPump::testThreadPump( void )
{
	// スレッドポンプの作成
	// 引数を0にするとハードウェアに最適なスレッド数で作ってくれる
	DTrace( D3DX10CreateThreadPump( 0, 0, &_pPump ) );

	// コピー元とコピー先作成
	u32 datSize = 1024 * 1024 * 250;
	_dat = myAlc( datSize );
	void* buf = myAlc( datSize );
	_bufInfo.init( datSize, buf );

	// ローダー作成
	ID3DX10DataLoader* memLoader;
	HRESULT hr = D3DX10CreateAsyncMemoryLoader( _dat, datSize, &memLoader );
	DTrace( hr );

	// プロセッサの作成
	ASyncMemLoadProcessor* pProcs = ASyncMemLoadProcessor::Create( _bufInfo );

	// スレッドポンプに作業を追加
	_pPump->AddWorkItem( memLoader, pProcs, NULL, NULL );
}

testThreadPump::~testThreadPump( void )
{
	SAFE_RELEASE( _pPump );
	SAFE_FREE( _bufInfo.getBufRef() );
	SAFE_FREE( _dat );
}

// 毎フレーム実行される処理
void testThreadPump::func( void )
{
	_pPump->ProcessDeviceWorkItems(1);	
	gFont.add( _bufInfo.isReady() ? _T("true") : _T("false") ); // デバッグ表示
}

GDC報告会

4月16日に行われたGDC報告会に行ってきました。
どの話も非常に面白く、密度が濃く、とても充実した1日でした。
特に面白いなと思ったのは「Crysis2のキャラクターモーション制御」という講演。
Parametric Blendingというモーションブレンディングのお話でした。
ザックリ言ってしまうとゲーム中のパラメータ(速度や移動方向などなど)からブレンディングウェイトを計算して最終的なモーションデータを作ろうという考え方。
GDC Vaultで実際に発表で使用されたスライドのダウンロードが可能だったのでスライドをDLして復習中です。
どうやらGDCに参加した人はGDCVaultでビデオコンテンツも見れる模様。うらやましい....

あと、今回の報告会に参加して「英語ってやっぱ必要だなぁ」と思いました。
英語ができる、できないでは情報入手のスピードに大きな差が生まれてしまうのでなんとか英語は身につけたい。
会話はできなくてもいいのでリスニングと技術書は読めるようになりたい。