DirectX11入門編 #2　テクスチャ

#はじめに
[#1](3ae4de5fe7fb19847152.md)
 #2 ここ
 #3 執筆中

３か月も経ってしまいましたが続編です。
内容はかなり薄めです。
Projectをgithubに上げています。動く状態で置いているつもりですので
照らし合わせながら見てほしいです。
[github](https://github.com/harayuu9/DirectX11DefferdQiita/tree/Part1)

#DirectXTex
古いバージョンではD3DX系の関数でテクスチャの読み込みも簡単に出来たのですが消されてしまったので外部ライブラリ（MS製）を使います。ライブラリを使わずに自分でpng等の読み込みをすることも可能です。DirectXTexを使えば様々な形式をDirectX11で使えるShaderResourceView(SRV)に変換することが簡単に出来ます。

##ライブラリの追加方法
追加方法にはgithubから最新の物を直接持ってくるかNuGetを使う方法があります。
githubから持ってきてやる方法が紹介されてる記事が多いですがNuGetを使った方が簡単ですので今回はNuGetで追加します。
githubから持ってきたい方はリポジトリは[こちら](https://github.com/microsoft/DirectXTex)になります。

###NuGetとは
NuGetとはフリー・アンド・オープンソースのパッケージマネージャです。リンクの追加やincludeディレクトリの設定を自動でしてくれるのでかなり楽です。Burst等のライブラリも追加出来るので便利です。

###追加
VisualStudioの
ツール→NuGetパッケージマネージャー→ソリューションのNuGetパッケージの管理
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163136/85835606-c60b-78a2-d395-939cf9678f21.png)

左上の参照を選択したうえで検索ボックスに「DirectXTex」と入力して検索してください。
出てきた項目の中で自分の環境にあったDirectXTexを入れます。
自分と同じ環境(windows10 visualstudio2019)でやってる方は「directxtex_desktop_win10」で大丈夫です。
選択したうえで右側で追加するプロジェクトを選択したうえでインストールをクリックしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163136/fedc553f-da04-94da-088d-bb08d1ebd9b9.png)

###include
この状態でDirectXTex.hをincludeすると機能を使うことが出来ます。

###TGAとWIC
よく使う読み込み形式としてTGAとWIC（png,jpg)に対応します。

```C++:DirectX11Manager.cpp
ID3D11ShaderResourceView* DirectX11Manager::CreateTextureFromFile(const wchar_t* filename)
{
	ID3D11ShaderResourceView* ShaderResView;

	char ms[100];
	setlocale(LC_CTYPE, "jpn");
	wcstombs(ms, filename, 100);
	char* extension = strstr(ms, ".");

	if (extension == NULL)
		return nullptr;

	if (strcmp(extension, ".tga") == 0 || strcmp(extension, ".TGA") == 0) {
		TexMetadata meta;
		GetMetadataFromTGAFile(filename, meta);

		std::unique_ptr<ScratchImage> image(new ScratchImage);
		HRESULT hr = LoadFromTGAFile(filename, &meta, *image);
		if (FAILED(hr))
			return nullptr;
		hr = CreateShaderResourceView(m_pDevice.Get(), image->GetImages(), image->GetImageCount(), meta, &ShaderResView);
		if (FAILED(hr))
			return nullptr;
		return ShaderResView;
	}
	else
	{
		TexMetadata meta;
		GetMetadataFromWICFile(filename, 0, meta);

		std::unique_ptr<ScratchImage> image(new ScratchImage);
		HRESULT hr = LoadFromWICFile(filename, 0, &meta, *image);
		if (FAILED(hr))
			return nullptr;
		hr = CreateShaderResourceView(m_pDevice.Get(), image->GetImages(), image->GetImageCount(), meta, &ShaderResView);
		if (FAILED(hr))
			return nullptr;
		return ShaderResView;
	}
}
```
GetMetadataFrom○○Fileでメタデータ（ファイル情報)を取得します。
そのうえでLoadFrom○○Fileでファイル情報からImageを読み込みます。
CreateShaderResourceViewを使ってImageからSRVを作成します。

###使用例
`C++:main.cpp
	//頂点情報を設定
	struct Vertex
	{
		XMFLOAT3 pos;
		XMFLOAT4 col;
		XMFLOAT2 uv;
	};

	//テクスチャの作成
	ComPtr<ID3D11ShaderResourceView> texture;
	texture.Attach(g_DX11Manager.CreateTextureFromFile("Assets/Textures/testMask.png"));
`
まず頂点情報にUV値を加えましょう。その後先ほどの関数を使ってテクスチャの生成を行います。
後は描画前にこのテクスチャをPixelShaderにセットしてPixelShader側で使うように書き換えていきます。

```C++:DirectX11Manager.cpp
void DirectX11Manager::SetTexture2D(UINT RegisterNo, ID3D11ShaderResourceView* Texture)
{
	m_pImContext->PSSetShaderResources(RegisterNo, 1, &Texture);
}
```
Managerの方でテクスチャのセットをラップしておきます

```C++:main.cpp
		g_DX11Manager.SetTexture2D(0, texture.Get());
```
描画前にこのようにセットします。

```3DPipeLine.hlsl
SamplerState samLinear : register(s0);

Texture2D Diffuse : register(t0);

cbuffer ConstBuff : register(b0)
{
	matrix mtxWorld;
	matrix mtxView;
	matrix mtxProj;
}

struct VS_INPUT
{
	float3 Pos : POSITION;
	float4 Col : COLOR;
	float2 Tex : TEXCOORD;
};

struct PS_INPUT
{
	float4 Pos : SV_POSITION;
	float4 Col : COL;
	float2 Tex : TEXCOORD;
};

PS_INPUT vsMain(VS_INPUT pos)
{
	PS_INPUT o = (PS_INPUT)0;
	o.Pos = mul(float4(pos.Pos, 1),mtxWorld);
	o.Pos = mul(o.Pos, mtxView);
	o.Pos = mul(o.Pos, mtxProj);
	o.Col = pos.Col;
	o.Tex = pos.Tex;
	return o;
}

float4 psMain(PS_INPUT input) : SV_TARGET
{
	float4 result = 0;
	result = Diffuse.Sample(samLinear, input.Tex) * input.Col;
	return result;
}
```
PixelShaderの中のDiffuse.Sampleでテクスチャのサンプリングをしています。UV通りにSampleする至って簡単な作りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163136/57df7ab9-a4be-3b46-d629-0f1a1a86244e.png)

#まとめ
今回はかなりシンプルな内容になっています。
テクスチャの扱い方はそれだけでそれなりに需要があるかなと思ったので一つに分けました。