シェーダーの作成~解放
-DirectX11編-
最終更新日:2020/02/25
DirectX11のシェーダーの作成から解放までを書いた記事です。
この記事は以下の内容を知りたい方に向けて書いています。
- DirectX11でシェーダーを作成したい
- DirectX11でシェーダーをコンパイルしたい
- DirectX11でシェーダーを設定したい
- DirectX11でシェーダーを解放したい
サンプル
サンプルはここからダウンロードでき、環境については以下の内容となっています。
開発環境
DirectXのバージョン |
DirectX11 |
VSのバージョン |
VisualStudio 2019 |
ファイル作成
シェーダの読み込みを行う前に、まずはシェーダファイルを作成をします。
シェーダファイルの作成はcppやhファイルを追加する時と同じ方法で行えます。
追加ファイルの選択画面ではHLSL項目を選び、頂点シェーダと
ピクセルシェーダを作成してください。
作成したファイルは、頂点シェーダは頂点座標のみが渡され、
それをそのまま返しています。
float4 main( float4 pos : POSITION ) : SV_POSITION
{
return pos;
}
ピクセルシェーダは何も受け取らず白色になるカラー値を返しています。
float4 main() : SV_TARGET
{
return float4(1.0f, 1.0f, 1.0f, 1.0f);
}
コンパイルする
作成したシェーダファイルはそのままでは使用することはできないので、
以下の方法でコンパイルする必要があります。
- VSに任せる
- D3DCompileFromFileを使う
VSに任せる
ソリューションにシェーダファイルを追加して、きちんとした設定をすれば、
ビルド時にVSがコンパイルを行ってくれます。
まず、対象のシェーダーファイルを右クリックしてプロパティを開いてください。
プロパティ画面の構成プロパティの全般でビルドから除外が「いいえ」、
項目の種類が「HLSLコンパイラ」になっていることを確認してください。
次にHLSLコンパイラの全般のエントリポイント、シェーダの種類、シェーダモデルの
確認も合わせて行ってください。
確認が完了後、ビルドを行うとDebugフォルダに「.cso」ファイルが作成されます。
このファイルがコンパイルされたシェーダファイルです。
あとは、このファイルを実行時にfopen_sなどで読み込めば
コンパイル後のデータとしてシェーダー作成時などで使用することができます。
// シェーダファイル読み込み
FILE *fp = nullptr;
fopen_s(&fp, file_name, "rb");
if (fp == nullptr)
{
return 0;
}
fseek(fp, 0, SEEK_END);
m_Size = ftell(fp);
fseek(fp, 0, SEEK_SET);
m_Data = new char[m_Size];
fread_s(m_Data, m_Size, m_Size, 1, fp);
fclose(fp);
シェーダーを作成する
ファイルの読み込みが完了したら、ID3D11Deviceの「CreateVertexShader」と
「CreatePixelShader」でシェーダの作成を行います。
// VertexShader作成
if (FAILED(device->CreateVertexShader(m_Data, m_Size, nullptr, &m_Interface)))
{
return false;
}
// PixelShader作成
if (FAILED(device->CreatePixelShader(m_Data, m_Size, nullptr, &m_Interface)))
{
return false;
}
設定する
作成したシェーダーはID3D11Deviceの設定関数である「VSSetShader」と
「PSSetShader」を使って、設定しないとレンダリングパイプラインで使われません。
// VertexShader設定
m_Context->VSSetShader( m_VertexShader->GetShaderInterface(), NULL, 0 );
// PixelShader設定
m_Context->PSSetShader( m_PixelShader->GetShaderInterface(), NULL, 0 );
解放する
シェーダを使い終わったらReleaseで解放します。
もし、シェーダーのファイルデータを動的確保しているようなら
こちらもきちんと解放してください。
// ファイルデータ解放
if (m_Data != nullptr)
{
delete[] m_Data;
}
// シェーダの解放
if (m_Interface != nullptr)
{
m_Interface->Release();
}