ゲームプログラミング技術集 
ひっと

ピクセルシェーダ

ピクセルシェーダの実装例を紹介しています。サンプルコードあります。

Direct3Dのピクセルシェーダについて

ピクセルシェーダではDirect3Dでレンダリングされた画面の各ピクセルを出力直前で操作することができます。
ピクセルの色をプログラミングで自由に操作でき、計算処理をグラフィックボードのGPUが行うので高速でより高度なCG表現が可能になりました。

ピクセルシェーダのサンプルプログラム

ピクセルシェーダを使って画像をモノクロ表示するプログラムです。
一定時間でピクセルシェーダのOnOffが切り替わります。


プログラムとソースコードをダウンロード

使用ツール:VC++2008 ExpressEdition
C(C++)言語とDirectX+Win32APIでプログラミングしています。

ピクセルシェーダの用途

・モノクロ、セピア調などの画面の色操作
・Zバッファを活用した遠いほどかすむフォグ

ほかにも、頂点シェーダと組み合わせて多彩なエフェクトが可能です。

ピクセルシェーダ実装の流れ

本来は上位レベルシェーダ言語(HLSL)を使ってピクセルシェーダをプログラミングしますが、今回はアセンブルで実装してみます。

ピクセルシェーダが使えるかチェックする

古かったりゲーム用途でない安価なグラフィックボードにはピクセルシェーダの機能が無いものもあります。
また、ピクセルシェーダにはいくつかバージョンがありバージョンによって使える機能が異なります。
ピクセルシェーダが有効かどうかは次の方法で確認します。


    LPDIRECT3DDEVICE9 device;

    D3DCAPS9 caps;
    device->GetDeviceCaps(&caps);

    if ( caps.PixelShaderVersion < D3DPS_VERSION(1,1) ) {
	::MessageBox(NULL,_T("ピクセルシェーダに対応していません。"),_T("エラー"),MB_OK);
    }

シェーダプログラムを記述したファイルを準備

ファイルはテキスト形式です。拡張子は何でもいいです。

モノクロ表示をするシェーダプログラム記述例

    ps_1_1;ピクセルシェーダのバージョンを宣言

    def c0, 0.298912f, 0.586611f, 0.114478f, 0.0f	;モノクロ化にするときのRGBの分担割合
    tex t0			;現在処理中のテクスチャのピクセル
    dp3 r0, t0, c0		;t0とc0を内積してr0(最終的に表示される色)に書き込む
    mov r0.a, t0.a		;RGBA全てが同じ値になるのでアルファ値だけは元のテクスチャのままに戻す

ピクセルシェーダオブジェクトの作成

シェーダプログラムを読み込んでDirect3Dのピクセルシェーダオブジェクトを作成します。

 LPDIRECT3DDEVICE9 device;

 LPDIRECT3DPIXELSHADER9 LoadPixelShader( LPCWSTR path ) {

    LPDIRECT3DPIXELSHADER9 shader = NULL;
    HRESULT hr;

    //シェーダプログラムの読み込み
    LPD3DXBUFFER pShaderSource;
    LPD3DXBUFFER pErrMessage = NULL;
    hr = D3DXAssembleShaderFromFile(path, NULL, NULL, 0, &pShaderSource, &pErrMessage );
    if ( FAILED(hr) ) {
        //エラーメッセージ表示 文字コードはANSIでした
        ::MessageBoxA(NULL,(LPCSTR)(pErrMessage->GetBufferPointer()),"エラー",MB_OK);
        pErrMessage->Release();
        return NULL;
    }

    //ピクセルシェーダ作成
    hr = device->CreatePixelShader((DWORD*)pShaderSource->GetBufferPointer(), &shader );
    if ( FAILED(hr) ) {
        return NULL;
    }

    //ピクセルシェーダを作ったらソースは解放して良い
    pShaderSource->Release();

    return shader;
 }

ピクセルシェーダの適用

IDIRECT3DDEVICE9::SetPixelShader()でピクセルシェーダを使うことができます。
また、SetPixelShaderの引数をNULLにすることでピクセルシェーダを解除できます。


    LPDIRECT3DDEVICE9      device;
    LPDIRECT3DPIXELSHADER9 pPixelShader;
    device->SetPixelShader(pPixelShader);

      次へ

Direct3Dグラフィック - シェーダプログラミング