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


◇DirectX11プログラミング -グレースケールシェーダー-

一瞬にしてグレースケールにする方法がある事に気がついた('-'*)
ピクセルシェーダーにカラーパレットが来るので,それをいぢったらできる
3D知識に関係なくできるところなので,何でもできるよ
(注意:そういうことをしても良いのかどうかはわかりません)

ピクセルシェーダーを差し替えるわけですが,既にマテリアル用(頂点カラーを使ったもの)とテクスチャー用があって,
しかも,ps_main,ps_main2とか,どっちがどっちかわからないような状態です
これからも増えていく事を考えて,もっとわかりやすい名称に変えます

・ピクセルシェーダー(ps.fx)
//入力用
struct pixcelIn
{
float4 pos : SV_POSITION;
float4 col : COLOR;
float2 tex : TEXCOORD0;
float4 col2: COL2;
};

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

//テクスチャー
float4 ps_tex(pixcelIn IN) : SV_Target
{
pixcelIn OUT;

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

return OUT.col;
}

//マテリアル
float4 ps_mat(pixcelIn IN) : SV_Target
{
pixcelIn OUT;

OUT.col = saturate(IN.col2) * IN.col;

return OUT.col;
}

//テクスチャー・グレースケール
float4 ps_texgray(pixcelIn IN) : SV_Target
{
pixcelIn OUT;

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

float Y = OUT.col.r * 0.29891f + OUT.col.g * 0.58661f + OUT.col.b * 0.11448f;
OUT.col.r = Y;
OUT.col.g = Y;
OUT.col.b = Y;

return OUT.col;
}

//マテリアル・グレースケール
float4 ps_matgray(pixcelIn IN) : SV_Target
{
pixcelIn OUT;

OUT.col = saturate(IN.col2) * IN.col;

float Y = OUT.col.r * 0.29891f + OUT.col.g * 0.58661f + OUT.col.b * 0.11448f;
OUT.col.r = Y;
OUT.col.g = Y;
OUT.col.b = Y;

return OUT.col;
}
ps_tex:テクスチャー
ps_mat:マテリアル
ps_texgray:テクスチャー・グレースケール
ps_matgray:マテリアル・グレースケール

それぞれをコンパイルしてヘッダーを生成します
"C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x64\fxc.exe" ps.fx /T ps_4_0 /E ps_mat /Fh ps_mat.h
"C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x64\fxc.exe" ps.fx /T ps_4_0 /E ps_tex /Fh ps_tex.h
"C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x64\fxc.exe" ps.fx /T ps_4_0 /E ps_matgray /Fh ps_matgray.h
"C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x64\fxc.exe" ps.fx /T ps_4_0 /E ps_texgray /Fh ps_texgray.h

これをメインプログラムに追加します
main.cppにヘッダーを追加する
#include "ps_mat.h"		//Pixcel Shader Material
#include "ps_tex.h" //Pixcel Shader Texture
#include "ps_matgray.h" //Pixcel Shader Material Grayscale
#include "ps_texgray.h" //Pixcel Shader Texture Grayscale
識別する指標を定義する
#define PS_MAT 1
#define PS_TEX 2
#define PS_MATGRAY 3
#define PS_TEXGRAY 4
その4つのシェーダー生成をおこなう
	//ピクセルシェーダー生成・マテリアル描画用
ID3D11PixelShader* hpPixelShader_mat;
if(FAILED(hpDevice->CreatePixelShader(&g_ps_mat, sizeof(g_ps_mat), NULL, &hpPixelShader_mat))){
MessageBoxW(hWnd, L"CreatePixelShader ps_mat", L"Err", MB_ICONSTOP);
goto End;
}
//ピクセルシェーダー生成・テクスチャー描画用
ID3D11PixelShader* hpPixelShader_tex;
if(FAILED(hpDevice->CreatePixelShader(&g_ps_tex, sizeof(g_ps_tex), NULL, &hpPixelShader_tex))){
MessageBoxW(hWnd, L"CreatePixelShader ps_tex", L"Err", MB_ICONSTOP);
goto End;
}
//ピクセルシェーダー生成・マテリアル・グレースケール描画用
ID3D11PixelShader* hpPixelShader_matgray;
if(FAILED(hpDevice->CreatePixelShader(&g_ps_matgray, sizeof(g_ps_matgray), NULL, &hpPixelShader_matgray))){
MessageBoxW(hWnd, L"CreatePixelShader ps_matgray", L"Err", MB_ICONSTOP);
goto End;
}
//ピクセルシェーダー生成・テクスチャー・グレースケール描画用
ID3D11PixelShader* hpPixelShader_texgray;
if(FAILED(hpDevice->CreatePixelShader(&g_ps_texgray, sizeof(g_ps_texgray), NULL, &hpPixelShader_texgray))){
MessageBoxW(hWnd, L"CreatePixelShader ps_texgray", L"Err", MB_ICONSTOP);
goto End;
}
メインループのシェーダー切り替え部分を4つに書き換える
				//ピクセルシェーダー切り替え
if(hModelData->getPsNum(mdcnt) == PS_MAT){
hpDeviceContext->PSSetShader(hpPixelShader_mat, NULL, 0);
}else if(hModelData->getPsNum(mdcnt) == PS_TEX){
hpDeviceContext->PSSetShader(hpPixelShader_tex, NULL, 0);
}else if(hModelData->getPsNum(mdcnt) == PS_MATGRAY){
hpDeviceContext->PSSetShader(hpPixelShader_matgray, NULL, 0);
}else if(hModelData->getPsNum(mdcnt) == PS_TEXGRAY){
hpDeviceContext->PSSetShader(hpPixelShader_texgray, NULL, 0);
}
modeldataクラスにピクセルシェーダーをセットする部分を,指標を使ったものに変更する
				//テクスチャー情報をセット
hModelData->setTexCnt(hModelId, 1);
hModelData->setTexSta(hModelId, hTexSta);
hModelData->setPsNum(hModelId, PS_TEX); //PSにテクスチャー描画をセット
}else{
hModelData->setPsNum(hModelId, PS_MAT); //PSにマテリアル描画をセット
}
実際にグレースケール表示する部分をmain.cppに追加します
		//グレースケールにシェーダーを切り替える
for(int mdcnt=0; mdcnt < hModelData->getMaxModelId(); mdcnt++){
if(hModelData->getPsNum(mdcnt) == PS_TEX){
hModelData->setPsNum(mdcnt, PS_TEXGRAY); //PSにテクスチャー描画をセット
}else if(hModelData->getPsNum(mdcnt) == PS_MAT){
hModelData->setPsNum(mdcnt, PS_MATGRAY); //PSにマテリアル描画をセット
}
}
どこでも良いはずです
シェーダーを切り替えた瞬間からグレースケール化します


カラーパレットを使用したフィルターは何でもできるでしょう
ただし,場所を指定する事はできません。モデルデータ単位になります

こんな感じに,カラーとモノクロを混在させることは可能です(やる意味があるかは別として)


シェーダーの種類を増やしていけば,色々な表現ができるようになりそうです


TOPプログラマ専用DirectX11開発