Nanashi-softプログラマ専用DirectX11開発


◇DirectX11プログラミング -シェーダーって2つ実装できる?-

初期の色だけ付けるのと,テクスチャーを貼るのと,2種類のピクセルシェーダーを使いたい時はどうすればいいのか?

そう言えば,関数名をあちこちに指定していたよね?
2つ関数作れば識別できるんじゃない?('-'*)?
やってみます(このブログではなんでも思いついたことはやってみます)

・ピクセルシェーダー
//入力用
struct pixcelIn
{
float4 pos : SV_POSITION;
float4 col : COLOR;
float2 tex : TEXCOORD0;
};

Texture2D txDiffuse : register( t0 );
SamplerState samLinear : register( s0 );

//テクスチャーを貼る方
float4 ps_main(pixcelIn IN) : SV_Target
{
pixcelIn OUT;

OUT.col = txDiffuse.Sample(samLinear, IN.tex);

//なんか妙に明るくなるので,少し暗くする
OUT.col.r -= 0.3f;
OUT.col.g -= 0.3f;
OUT.col.b -= 0.3f;

return OUT.col;
}

//色パレットを使う方
float4 ps_main2(pixcelIn IN) : SV_Target
{
pixcelIn OUT;

//カラーをそのまま返す
OUT.col = IN.col;

return OUT.col;
}
コンパイルを,関数名を変えて2回実行します(同じバイナリに2つは入らないっぽかった)
fxc.exe ps.fx /T ps_4_0 /E ps_main /Fh ps.h
fxc.exe ps.fx /T ps_4_0 /E ps_main2 /Fh ps_2.h
この2つのファイルをインクルードします
#include "ps.h"	//Pixcel Shader
#include "ps_2.h" //Pixcel Shader 2
ピクセルシェーダー生成時に,2つ(変数名を変えて)作ります
ここでは,コンテキストに設定するのをやめます
	//ピクセルシェーダー生成
ID3D11PixelShader* hpPixelShader;
if(FAILED(hpDevice->CreatePixelShader(&g_ps_main, sizeof(g_ps_main), NULL, &hpPixelShader))){
MessageBoxW(hWnd, L"CreateVertexShader", L"Err", MB_ICONSTOP);
goto End;
}

//ピクセルシェーダー2生成
ID3D11PixelShader* hpPixelShader2;
if(FAILED(hpDevice->CreatePixelShader(&g_ps_main2, sizeof(g_ps_main2), NULL, &hpPixelShader2))){
MessageBoxW(hWnd, L"CreateVertexShader 2", L"Err", MB_ICONSTOP);
goto End;
}
メインループで,描画の直前に,別々のピクセルシェーダーをコンテキストに設定します
	//メインループ
MSG hMsg;
while(true){
while(PeekMessageW(&hMsg, NULL, 0, 0, PM_REMOVE)){
if(hMsg.message == WM_QUIT){
goto End;
}
TranslateMessage(&hMsg);
DispatchMessage(&hMsg);
}

//背景クリア
float ClearColor[] = {0.0f, 0.0f, 1.0f, 1.0f};
hpDeviceContext->ClearRenderTargetView(hpRenderTargetView, ClearColor);

//テクスチャー1をコンテキストに設定
hpDeviceContext->PSSetShaderResources(0, 1, hpShaderResourceViews);

//ワールド変換用行列を生成
XMMATRIX hWorld; //ワールド変換行列
//初期化
hWorld = XMMatrixIdentity();

XMMATRIX hRotate;
hRotate = XMMatrixTranslation(+0.5f, 0.0f, 0.5f);
hWorld = XMMatrixMultiply(hWorld, hRotate);

XMMATRIX hView; //ビュー変換行列
XMVECTOR hEye = XMVectorSet(0.0f, 0.0f, -2.0f, 0.0f); //カメラの位置
XMVECTOR hAt = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); //焦点の位置
XMVECTOR hUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
hView = XMMatrixLookAtLH(hEye, hAt, hUp);

XMMATRIX hProjection; //透視射影変換行列
hProjection = XMMatrixPerspectiveFovLH(D3DXToRadian(45.0f), 16.0f/9.0f, 0.0f, 1000.0f);

//それらをシェーダーに送る
struct ConstantBuffer
{
XMMATRIX mWorld;
XMMATRIX mView;
XMMATRIX mProjection;
};
//constantバッファ生成
ID3D11Buffer* hpConstantBuffer = NULL;
hBufferDesc.ByteWidth = sizeof(ConstantBuffer);
hBufferDesc.Usage = D3D11_USAGE_DEFAULT;
hBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
hBufferDesc.CPUAccessFlags = 0;
hBufferDesc.MiscFlags = 0;
hBufferDesc.StructureByteStride = sizeof(float);
if(FAILED(hpDevice->CreateBuffer(&hBufferDesc, NULL, &hpConstantBuffer))){
MessageBoxW(hWnd, L"Create ConstantBuffer", L"Err", MB_ICONSTOP);
goto End;
}

//ID3D11DeviceContext* g_pImmediateContext = NULL;
ConstantBuffer hConstantBuffer;
hConstantBuffer.mWorld = XMMatrixTranspose(hWorld);
hConstantBuffer.mView = XMMatrixTranspose(hView);
hConstantBuffer.mProjection = XMMatrixTranspose(hProjection);
hpDeviceContext->UpdateSubresource(hpConstantBuffer, 0, NULL, &hConstantBuffer, 0, 0);

hpDeviceContext->VSSetConstantBuffers(0, 1, &hpConstantBuffer);

//ピクセルシェーダーをコンテキストに設定
hpDeviceContext->PSSetShader(hpPixelShader, NULL, 0);

//描画
hpDeviceContext->Draw(TYOUTEN, 0);

//テクスチャー2をコンテキストに設定
hpDeviceContext->PSSetShaderResources(0, 1, hpShaderResourceViews2);

hWorld = XMMatrixIdentity();

hRotate = XMMatrixRotationZ(D3DXToRadian(-45.0f));
hWorld = XMMatrixMultiply(hWorld, hRotate);

hRotate = XMMatrixTranslation(-0.5f, 0.0f, 0.0f);
hWorld = XMMatrixMultiply(hWorld, hRotate);

hConstantBuffer.mWorld = XMMatrixTranspose(hWorld);
hpDeviceContext->UpdateSubresource(hpConstantBuffer, 0, NULL, &hConstantBuffer, 0, 0);
hpDeviceContext->VSSetConstantBuffers(0, 1, &hpConstantBuffer);

//ピクセルシェーダー2をコンテキストに設定
hpDeviceContext->PSSetShader(hpPixelShader2, NULL, 0);

//描画
hpDeviceContext->Draw(TYOUTEN, 0);

hpDXGISwpChain->Present(0, 0);
}
あと,頂点データに適当な色を送っておきます
	//頂点データ(四角ポリゴン1枚)
Vertex3D hVectorData[TYOUTEN] = {
//500x811
{ { -0.50f, +0.75f, +0.5f }, { 0.0f, 0.0f, 0.5f, 1.0f }, {0.0f, 0.0f} },
{ { +0.50f, +0.75f, +0.5f }, { 0.0f, 0.8f, 0.0f, 1.0f }, {1.0f, 0.0f} },
{ { -0.50f, -0.75f, +0.5f }, { 0.8f, 0.0f, 0.0f, 1.0f }, {0.0f, 1.0f} },
{ { +0.50f, -0.75f, +0.5f }, { 0.8f, 0.8f, 0.5f, 1.0f }, {1.0f, 1.0f} }
};
これを実行すると,2つのピクセルシェーダーを実行できました



TOPプログラマ専用DirectX11開発