ピクセルシェーダー

頂点シェーダーの次はピクセルシェーダーです。
前回と同じく黄色の四角形を表示するプログラムですが、
頂点シェーダーによって赤色に、そしてピクセルシェーダーによって
最終的に白色に変換されて表示されます。

shader.cpp

#include <d3dx9.h>
#define WINDOW_WIDTH  640 //ウインドウの幅
#define WINDOW_HEIGHT  480 //ウインドウの高さ
#define SAFE_RELEASE(x) if(x){x->Release();} 

LPDIRECT3D9             g_pD3D       = NULL;//Direct3D9
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL;//レンダリングデバイス

//-------------------------------------------------------------
// 頂点フォーマット
//-------------------------------------------------------------
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)

struct CUSTOMVERTEX{
    FLOAT x, y, z;    // スクリーン座標での位置
 DWORD color;
};
LPDIRECT3DVERTEXBUFFER9 g_pVB        = NULL;//頂点バッファ

// ★ ピクセルシェーダ
    LPDIRECT3DPIXELSHADER9 m_pPixelShader;  // ピクセルシェーダ
// ★ 頂点シェーダ
    LPDIRECT3DVERTEXSHADER9 m_pVertexShader=NULL;     // ★ 頂点シェーダ
    LPDIRECT3DVERTEXDECLARATION9 m_pVertexDeclaration;  // ★ 頂点宣言

HWND hwnd;
HRESULT Init()
{
 HRESULT hr;
 LPD3DXBUFFER pCode;
 // ---------------------------------------------------------
 // ★ ピクセルシェーダの作成
    // ---------------------------------------------------------
    if( FAILED( hr = D3DXAssembleShaderFromFileA(
      "PixelShader.psh",
      NULL, NULL, 0, &pCode, NULL ) ) ){
        return hr;
 }
    SAFE_RELEASE( m_pPixelShader );
    if (FAILED( hr = g_pd3dDevice->CreatePixelShader(
      (DWORD*)pCode->GetBufferPointer(),
      &m_pPixelShader ) ) )
        return hr;
    SAFE_RELEASE( pCode );
   
    // ---------------------------------------------------------
    // ★ 頂点シェーダの作成
    // ---------------------------------------------------------

    // 頂点宣言オブジェクトの生成
    D3DVERTEXELEMENT9 decl[] = {
        { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
                 D3DDECLUSAGE_POSITION, 0 },
        D3DDECL_END()
    };
   
    if( FAILED( hr = g_pd3dDevice->CreateVertexDeclaration( decl, &m_pVertexDeclaration ) ) ) {
        return hr;
    }

    // シェーダを読み込む
    if( FAILED( hr = D3DXAssembleShaderFromFileA(
                        "VertexShader.vsh", NULL, NULL, 0, &pCode, NULL ))) {
        return hr;
    }

    // 頂点シェーダの生成
    hr = g_pd3dDevice->CreateVertexShader(
                          (DWORD*)pCode->GetBufferPointer(),
                          &m_pVertexShader );
    pCode->Release();

 // 頂点と色情報
    CUSTOMVERTEX vertices[] = {
        //   x,     y,      z, 
        {-0.5f, +0.5f, 0, 0xffffff00,},
        {+0.5f, +0.5f, 0, 0xffffff00,},
        {-0.5f, -0.5f, 0, 0xffffff00,},
        {+0.5f, -0.5f, 0, 0xffffff00,},
    };
   
    // 頂点バッファを生成する
    if( FAILED( g_pd3dDevice->CreateVertexBuffer(
                4*sizeof(CUSTOMVERTEX),        // 頂点バッファのサイズ
                0, D3DFVF_CUSTOMVERTEX,        // 使用法、頂点フォーマット
                D3DPOOL_DEFAULT,            // メモリクラス
                &g_pVB, NULL )))            // 頂点バッファリソース 予約済
        return E_FAIL;

    // 頂点バッファに情報を格納する
    VOID* pVertices;
    if(FAILED( g_pVB->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
        return E_FAIL;
    memcpy( pVertices, vertices, sizeof(vertices) );
    g_pVB->Unlock();
 

 return true;
}
void FrameUpDate()
{
 D3DXMATRIXA16 mat,matView,matProj;
 // ビュー行列の設定
    D3DXVECTOR3 vEye = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
    D3DXVECTOR3 vAt  = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
    D3DXVECTOR3 vUp  = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
    D3DXMatrixLookAtRH( &matView, &vEye, &vAt, &vUp );

    // 射影行列の生成
    D3DXMatrixPerspectiveFovRH( &matProj, D3DXToRadian(60.0f),
                                1.4f, 0.1f, 1000.0f );
 D3DXMatrixMultiply( &mat, &matView, &matProj );
 // ★ 座標変換の定数レジスタの設定
    D3DXMatrixMultiply( &mat, &matView, &matProj );
    D3DXMatrixTranspose( &mat, &mat );// 転置行列の作成
    g_pd3dDevice->SetVertexShaderConstantF(0, (float*)&mat, 4);

 // ★ 頂点色の定数レジスタの設定
    float color[] = {1.0f, 0.0f, 0.0f, 1.0f};// 赤色
    g_pd3dDevice->SetVertexShaderConstantF(4, (float*)&color, 1);

}
void ScreenDraw()
{

// 画面をクリアする
    g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
                         0x000000ff, 1.0f, 0L );
    //シーンの開始
    if(SUCCEEDED(g_pd3dDevice->BeginScene()))
    {

  // ★ ピクセルシェーダの設定
  g_pd3dDevice->SetPixelShader( m_pPixelShader );
  // ★頂点シェーダの設定
        g_pd3dDevice->SetVertexDeclaration(m_pVertexDeclaration);
        g_pd3dDevice->SetVertexShader( m_pVertexShader );
  //ストリームソースのセット
  g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
  //FVFのセット
  g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
  g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

  
        //シーンの終了
        g_pd3dDevice->EndScene();
    }

    //バックバッファを表画面に反映させる
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

 

}
void GetFPS()
{
  FrameUpDate();
  ScreenDraw();
  Sleep(16);
}
DWORD WINAPI MainLoop(LPVOID vdParam)
{
 while(TRUE){
  GetFPS();
 }
 return 0;
}
HRESULT InitD3D( HWND hWnd )
{
 if(NULL==(g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))){return E_FAIL;}

    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof(d3dpp) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
    d3dpp.BackBufferCount = 1;
    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
    d3dpp.MultiSampleQuality = 0;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.Flags = 0;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ;

    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))){
        if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))){
   return(E_FAIL);
        }
    }


 Init();
    return S_OK;
}
LRESULT CALLBACK MsgProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
 switch (msg) {
  case WM_DESTROY:
   PostQuitMessage(0);
   return 0;
 }
 return DefWindowProc(hwnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,PSTR lpCmdLine , int nCmdShow )
{
 MSG msg;
 DWORD dwID;


    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                      L"Window1", NULL };
    RegisterClassEx( &wc );

 RECT rect;
 SetRect(&rect,0,0,WINDOW_WIDTH,WINDOW_HEIGHT);
 AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
 SetRect(&rect,0,0,rect.right-rect.left,rect.bottom-rect.top);

    hwnd = CreateWindow( L"Window1", L"Shader",
    WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, rect.right, rect.bottom,
                              NULL, NULL, wc.hInstance, NULL );

 if (hwnd == NULL) return 0;

  timeBeginPeriod(1);

 if(SUCCEEDED(InitD3D(hwnd))){
  ShowWindow(hwnd,SW_SHOWDEFAULT);
        UpdateWindow(hwnd);

  CreateThread(NULL , 0 , MainLoop , (LPVOID)hwnd , 0 , &dwID);
  while (GetMessage(&msg , NULL , 0 , 0 )) {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }

 }
 UnregisterClass(L"Window1",wc.hInstance);
 timeEndPeriod(1);

 // ★ 頂点シェーダの開放
 SAFE_RELEASE( m_pVertexShader );
    SAFE_RELEASE( m_pVertexDeclaration );
 SAFE_RELEASE(g_pVB);
 SAFE_RELEASE(g_pd3dDevice);
    SAFE_RELEASE(g_pD3D);
 return 0;
}

VertexShader.vsh

vs_1_1              // バージョン命令

dcl_position v0     // 座標頂点宣言

m4x4 oPos, v0, c0   // 座標変換をする
mov oD0, c4         // 定数色を読み込む

PixelShader.psh

ps_1_1
def   c0, 0.2989f, 0.5866f, 0.1145f, 0.0f
tex   t0
dp3   r0, t0, c0
mov   r1, r0.a
lrp   r0, c1, t0, r1
最終更新:2009年05月20日 19:29
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。
添付ファイル