【DirectXプログラミング】シェーダを使った描画について
Posted: 2010年9月12日(日) 12:15
いつもお世話になります。
今回はシェーダを使った描画について質問があります。
色々なDirectXの入門サイトや書籍を見たのですが、シェーダを使った描画では
D3DデバイスのDrawPrimitiveメソッドを使って描画をしているものしかありませんでした。
そこで、D3DデバイスのDrawPrimitiveUPメソッドを使った場合のシェーダの描画の方法を
知りたくて質問させていただきました。
まず、下記のソースは通常の頂点バッファを作成し、DrawPrimitiveメソッドで描画している
ソースです。
当然頂点バッファを使っているので、SetStreamSourceで頂点データを渡してから描画をしています。
=====================================描画部分のコード=========================================
// 頂点のフォーマット宣言
D3DVERTEXELEMENT9 m_vertexElements[/url] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};
pD3DDevice->CreateVertexDeclaration(m_vertexElements, &m_pVertexDecl);
// オブジェクトの頂点バッファを生成
if( FAILED( pD3DDevice->CreateVertexBuffer( 4*sizeof(MY_VERTEX_POS),
D3DUSAGE_WRITEONLY,
0,
D3DPOOL_MANAGED, &m_pVB_POS, NULL ))){
return E_FAIL;
}
//頂点バッファの中身を埋める
MY_VERTEX_POS* v0;
m_pVB_POS->Lock( 0, 0, (void**)&v0, 0 );
// 各頂点の位置
v0[0].p = D3DXVECTOR3(-1.0f, 1.0f, 0.0f );
v0[1].p = D3DXVECTOR3( 1.0f, 1.0f, 0.0f );
v0[2].p = D3DXVECTOR3(-1.0f, -1.0f, 0.0f );
v0[3].p = D3DXVECTOR3( 1.0f, -1.0f, 0.0f );
m_pVB_POS->Unlock();
// オブジェクトの頂点バッファ(テクスチャ座標)を生成
if( FAILED( pD3DDevice->CreateVertexBuffer( 4*sizeof(MY_VERTEX_TEX),D3DUSAGE_WRITEONLY,0,D3DPOOL_MANAGED, &m_pVB_TEX, NULL ))){
return E_FAIL;
}
//頂点バッファの中身を埋める
MY_VERTEX_TEX* v1;
m_pVB_TEX->Lock( 0, 0, (void**)&v1, 0 );
// 各頂点のテクスチャ座標
v1[0].tex = D3DXVECTOR2( 0.0, 0.0f);
v1[1].tex = D3DXVECTOR2( 1.0f, 0.0f);
v1[2].tex = D3DXVECTOR2( 0.0f, 1.0f);
v1[3].tex = D3DXVECTOR2( 1.0f, 1.0f);
m_pVB_TEX->Unlock();
D3DXCreateEffectFromFile(pD3DDevice, TEXT("test.fx"), 0, 0, D3DXSHADER_DEBUG, 0, &m_pFX, &errors);
if( errors){
return E_FAIL;
}
// シェーダプログラムへテクニックへのハンドルの取得
m_hTech = m_pFX->GetTechniqueByName("BasicTech");
// シェーダープログラムのグローバル変数のハンドルの取得
m_hWvp = m_pFX->GetParameterByName(0, "wvp");
m_hColor = m_pFX->GetParameterByName(0, "color");
m_hTexture = m_pFX->GetParameterByName(0, "texh");
// テクスチャ画像の読み込み
D3DXCreateTextureFromFile(pD3DDevice, TEXT("tex.bmp"), &m_pTexture);
// 頂点のデクラレーションの設定
pD3DDevice->SetVertexDeclaration(m_pVertexDecl);
// ストリームとして頂点バッファを設定
pD3DDevice->SetStreamSource( 0, m_pVB_POS, 0, sizeof(MY_VERTEX_POS) );
pD3DDevice->SetStreamSource( 1, m_pVB_TEX, 0, sizeof(MY_VERTEX_TEX) );
// 色を設定→白
D3DXVECTOR4 tmpColor;
tmpColor.x = 1.0f;
tmpColor.y = 1.0f;
tmpColor.z = 1.0f;
tmpColor.w = 1.0f;
// テクニックの設定(シェーダプログラムの設定)
m_pFX->SetTechnique(m_hTech);
// シェーダーのグローバル変数の値の設定
m_pFX->SetMatrix(m_hWvp, &(m_view*m_proj));
m_pFX->SetVector(m_hColor, &tmpColor);
m_pFX->SetTexture(m_hTexture, m_pTexture);
m_pFX->CommitChanges();
// シェーダプログラムの開始宣言
m_pFX->Begin(0, 0);
m_pFX->BeginPass(0);
// 三角形の描画処理
pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2);
// シェーダプログラムの終了宣言
m_pFX->EndPass();
m_pFX->End();
}
================================================ココまで========================================
ですが、DrawPrimitiveUPメソッドでは、そのメソッドの引数に頂点データの配列の先頭ポインタを渡して
描画しているので、SetStreamSourceは使いません。
そうなると、DrawPrimitiveUPの時はSetVectorやSetTextureなどでデータをGPUに渡すタイミングはいつなのかや呼ぶ必要はあるのかなどが具体的にわかりません。
頂点データの配列にディフューズ色などを含める場合などや、もしそうした場合シェーダー側(HLSL)の
プログラムはどうなるのかなどもよく分かりません。
どなたか、上記のソースをDrawPrimitiveUP用の置き換えて説明してくださる方がいらっしゃれば、
ご説明願います。
シェーダを使った描画でDrawPrimitiveUPを使った参考サイトがあれば、そのURLを貼っていただくだけでも
構いません。
よろしくお願い致します。
下記にHLSL(シェーダ)のコードも貼っておきます。
===================================ココから下はHLSLのコード============================
float4x4 wvp;
float4 color;
texture texh;
sampler TextureSampler =
sampler_state
{
Texture = <texh>;
};
void BasicVS(float3 pos : POSITION,
float2 tex : TEXCOORD0,
out float4 outpos : POSITION,
out float4 vcol : COLOR0,
out float2 outtex : TEXCOORD0)
{
outpos=mul(float4(pos,1.0f),wvp);
vcol = color;
outtex=tex;
}
void BasicPS(float4 ptex : TEXCOORD0,
out float4 outcolor : COLOR0)
{
outcolor = tex2D(TextureSampler,ptex);
}
technique BasicTech
{
pass P0
{
vertexshader = compile vs_3_0 BasicVS();
pixelshader = compile ps_3_0 BasicPS();
}
}
=========================================================================
今回はシェーダを使った描画について質問があります。
色々なDirectXの入門サイトや書籍を見たのですが、シェーダを使った描画では
D3DデバイスのDrawPrimitiveメソッドを使って描画をしているものしかありませんでした。
そこで、D3DデバイスのDrawPrimitiveUPメソッドを使った場合のシェーダの描画の方法を
知りたくて質問させていただきました。
まず、下記のソースは通常の頂点バッファを作成し、DrawPrimitiveメソッドで描画している
ソースです。
当然頂点バッファを使っているので、SetStreamSourceで頂点データを渡してから描画をしています。
=====================================描画部分のコード=========================================
// 頂点のフォーマット宣言
D3DVERTEXELEMENT9 m_vertexElements[/url] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};
pD3DDevice->CreateVertexDeclaration(m_vertexElements, &m_pVertexDecl);
// オブジェクトの頂点バッファを生成
if( FAILED( pD3DDevice->CreateVertexBuffer( 4*sizeof(MY_VERTEX_POS),
D3DUSAGE_WRITEONLY,
0,
D3DPOOL_MANAGED, &m_pVB_POS, NULL ))){
return E_FAIL;
}
//頂点バッファの中身を埋める
MY_VERTEX_POS* v0;
m_pVB_POS->Lock( 0, 0, (void**)&v0, 0 );
// 各頂点の位置
v0[0].p = D3DXVECTOR3(-1.0f, 1.0f, 0.0f );
v0[1].p = D3DXVECTOR3( 1.0f, 1.0f, 0.0f );
v0[2].p = D3DXVECTOR3(-1.0f, -1.0f, 0.0f );
v0[3].p = D3DXVECTOR3( 1.0f, -1.0f, 0.0f );
m_pVB_POS->Unlock();
// オブジェクトの頂点バッファ(テクスチャ座標)を生成
if( FAILED( pD3DDevice->CreateVertexBuffer( 4*sizeof(MY_VERTEX_TEX),D3DUSAGE_WRITEONLY,0,D3DPOOL_MANAGED, &m_pVB_TEX, NULL ))){
return E_FAIL;
}
//頂点バッファの中身を埋める
MY_VERTEX_TEX* v1;
m_pVB_TEX->Lock( 0, 0, (void**)&v1, 0 );
// 各頂点のテクスチャ座標
v1[0].tex = D3DXVECTOR2( 0.0, 0.0f);
v1[1].tex = D3DXVECTOR2( 1.0f, 0.0f);
v1[2].tex = D3DXVECTOR2( 0.0f, 1.0f);
v1[3].tex = D3DXVECTOR2( 1.0f, 1.0f);
m_pVB_TEX->Unlock();
D3DXCreateEffectFromFile(pD3DDevice, TEXT("test.fx"), 0, 0, D3DXSHADER_DEBUG, 0, &m_pFX, &errors);
if( errors){
return E_FAIL;
}
// シェーダプログラムへテクニックへのハンドルの取得
m_hTech = m_pFX->GetTechniqueByName("BasicTech");
// シェーダープログラムのグローバル変数のハンドルの取得
m_hWvp = m_pFX->GetParameterByName(0, "wvp");
m_hColor = m_pFX->GetParameterByName(0, "color");
m_hTexture = m_pFX->GetParameterByName(0, "texh");
// テクスチャ画像の読み込み
D3DXCreateTextureFromFile(pD3DDevice, TEXT("tex.bmp"), &m_pTexture);
// 頂点のデクラレーションの設定
pD3DDevice->SetVertexDeclaration(m_pVertexDecl);
// ストリームとして頂点バッファを設定
pD3DDevice->SetStreamSource( 0, m_pVB_POS, 0, sizeof(MY_VERTEX_POS) );
pD3DDevice->SetStreamSource( 1, m_pVB_TEX, 0, sizeof(MY_VERTEX_TEX) );
// 色を設定→白
D3DXVECTOR4 tmpColor;
tmpColor.x = 1.0f;
tmpColor.y = 1.0f;
tmpColor.z = 1.0f;
tmpColor.w = 1.0f;
// テクニックの設定(シェーダプログラムの設定)
m_pFX->SetTechnique(m_hTech);
// シェーダーのグローバル変数の値の設定
m_pFX->SetMatrix(m_hWvp, &(m_view*m_proj));
m_pFX->SetVector(m_hColor, &tmpColor);
m_pFX->SetTexture(m_hTexture, m_pTexture);
m_pFX->CommitChanges();
// シェーダプログラムの開始宣言
m_pFX->Begin(0, 0);
m_pFX->BeginPass(0);
// 三角形の描画処理
pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2);
// シェーダプログラムの終了宣言
m_pFX->EndPass();
m_pFX->End();
}
================================================ココまで========================================
ですが、DrawPrimitiveUPメソッドでは、そのメソッドの引数に頂点データの配列の先頭ポインタを渡して
描画しているので、SetStreamSourceは使いません。
そうなると、DrawPrimitiveUPの時はSetVectorやSetTextureなどでデータをGPUに渡すタイミングはいつなのかや呼ぶ必要はあるのかなどが具体的にわかりません。
頂点データの配列にディフューズ色などを含める場合などや、もしそうした場合シェーダー側(HLSL)の
プログラムはどうなるのかなどもよく分かりません。
どなたか、上記のソースをDrawPrimitiveUP用の置き換えて説明してくださる方がいらっしゃれば、
ご説明願います。
シェーダを使った描画でDrawPrimitiveUPを使った参考サイトがあれば、そのURLを貼っていただくだけでも
構いません。
よろしくお願い致します。
下記にHLSL(シェーダ)のコードも貼っておきます。
===================================ココから下はHLSLのコード============================
float4x4 wvp;
float4 color;
texture texh;
sampler TextureSampler =
sampler_state
{
Texture = <texh>;
};
void BasicVS(float3 pos : POSITION,
float2 tex : TEXCOORD0,
out float4 outpos : POSITION,
out float4 vcol : COLOR0,
out float2 outtex : TEXCOORD0)
{
outpos=mul(float4(pos,1.0f),wvp);
vcol = color;
outtex=tex;
}
void BasicPS(float4 ptex : TEXCOORD0,
out float4 outcolor : COLOR0)
{
outcolor = tex2D(TextureSampler,ptex);
}
technique BasicTech
{
pass P0
{
vertexshader = compile vs_3_0 BasicVS();
pixelshader = compile ps_3_0 BasicPS();
}
}
=========================================================================