テクスチャーの管理クラス
テクスチャーを読み込んで使用するために、先ずはTextureクラスを作成していきます。
今回のクラスでは下記の機能を実装いていきます。
- 画像データの読み込み
- シェーダリソースの作成
- サンプラーステートの作成
サンプラーステートは別途管理した方がいい場合もありますが、今回はまとめて実装していきます。
Texture.h
// テクスチャークラス
class Texture
{
public:
Texture();
// 初期化、解放
bool Initialize(DirectX11& directX11, const char* pFilename);
void Finalize();
ID3D11ShaderResourceView* GetResourceView() {
return m_pShaderResourceView.Get();
}
ID3D11SamplerState* GetSamplerState() {
return m_pSamplerState.Get();
}
UINT GetWidth() { return m_Width; }
UINT GetHeight() { return m_Height; }
private:
// サンプラーステートの作成
bool CreateSampler(DirectX11& directX11);
private:
ComPtr<ID3D11ShaderResourceView> m_pShaderResourceView;
ComPtr<ID3D11SamplerState> m_pSamplerState;
DXGI_FORMAT m_Format;
UINT m_Width;
UINT m_Height;
};
今回は、テクスチャークラスの管理にComPtrを使用しています。
これはスマートポインタと呼ばれるものでCOMオブジェクトの生存管理をしてくれます。
DirectXはCOMオブジェクトとして実装されています。
なのでComPtrを使用することで管理を楽にすることができます。
使い方は簡単です。
#include <wrl.h>
using namespace Microsoft::WRL;
上記のようにwrl.hのインクルードとネームスペースを省略するためのusingを書けば完了です。
ではこの調子でクラスの実装部分も見ていきましょう。
Texture.cpp
#include "Texture.h"
#include <DirectXTex/DirectXTex.h>
// DirectXTexのライブラリをリンク
#if _DEBUG
#pragma comment(lib, "DirectXTex/x64/Debug/DirectXTex.lib")
#else
#pragma comment(lib, "DirectXTex/x64/Release/DirectXTex.lib")
#endif
using namespace DirectX;
Texture::Texture()
: m_Width(0)
, m_Height(0)
{}
bool Texture::Initialize(DirectX11& directX11, const char* pFilename)
{
auto pDevice = directX11.GetDevice();
Finalize();
const char* pExtension = "";
for (size_t i = strlen(pFilename); i != 0; i--)
{
if (pFilename[i-1] == '.')
{
pExtension = &pFilename[i];
}
}
WCHAR path[256];
size_t len = 0;
mbstowcs_s(&len, path, 256, pFilename, _TRUNCATE);
TexMetadata metadata;
ScratchImage image;
HRESULT hr;
// DDSファイルの読み込み
if (strcmp(pExtension, "dds") == 0)
{
hr = LoadFromDDSFile(path, DDS_FLAGS::DDS_FLAGS_NONE, &metadata, image);
}
// TGAファイルの読み込み
else if (strcmp(pExtension, "tga") == 0)
{
hr = LoadFromTGAFile(path, &metadata, image);
}
// WICファイル(bmp, jpg, png等)の読み込み
else
{
hr = LoadFromWICFile(path, WIC_FLAGS::WIC_FLAGS_NONE, &metadata, image);
}
if (FAILED(hr))
{
return false;
}
ComPtr<ID3D11ShaderResourceView> pView;
// 画像からシェーダリソースViewの作成
hr = CreateShaderResourceView(pDevice, image.GetImages(), image.GetImageCount(), metadata, &pView);
if (FAILED(hr)) {
return false;
}
if (!CreateSampler(directX11)) {
return false;
}
m_Format = metadata.format;
m_Width = static_cast<UINT>(metadata.width);
m_Height = static_cast<UINT>(metadata.height);
m_pShaderResourceView.Swap(pView);
return true;
}
void Texture::Finalize()
{
m_pShaderResourceView.Reset();
m_pSamplerState.Reset();
}
bool Texture::CreateSampler(DirectX11& directX11)
{
auto pDevice = directX11.GetDevice();
// SamplerState作成
D3D11_SAMPLER_DESC sampDesc{};
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
sampDesc.MinLOD = 0;
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
ComPtr<ID3D11SamplerState> pSamplerState;
HRESULT hr = pDevice->CreateSamplerState(&sampDesc, &pSamplerState);
if (FAILED(hr)) {
return false;
}
m_pSamplerState.Swap(pSamplerState);
return true;
}
一気に記述していきましたが、これでテクスチャーの管理が行えます。
ComPtrを使用しているのでFinalizeは無くても解放はされます。
ただ解放タイミングの制御するためにはあった方が無難です。
対応しているファイルはbmp, png, jpgなどからddsやtga辺りまで対応しています。