DirectX11 리소스 관리 클래스
| 클래스 | 역할 |
|---|
| Texture | 텍스처 이미지 로드 및 ShaderResourceView 생성 |
| ConstantBuffer | CPU → GPU로 전달되는 상수(Uniform) 데이터 버퍼 |
| Shader / VertexShader / PixelShader | HLSL 셰이더 로드 및 컴파일 관리 |
1. Texture
- GPU에서 사용할 이미지 리소스
- 파일로 부터 텍스처 이미지를 읽어 DirectX11용 Shader Resource View (SRV)를 생성
- 쉐이더에서 Texture2D로 접근할 수 있도록 연결
- 내부적으로 WIC(Windows Imaging Component)와 DirectXTex를 사용
#pragma once
class Texture
{
public:
Texture(ComPtr<ID3D11Device> device);
~Texture();
ComPtr<ID3D11ShaderResourceView> GetComPtr() const { return _shaderResourceView; }
void Create(const wstring& path);
private:
ComPtr<ID3D11Device> _device;
ComPtr<ID3D11ShaderResourceView> _shaderResourceView;
};
#include "pch.h"
#include "Texture.h"
Texture::Texture(ComPtr<ID3D11Device> device)
: _device(device)
{
}
Texture::~Texture()
{
}
void Texture::Create(const wstring& path)
{
DirectX::TexMetadata md;
DirectX::ScratchImage img;
HRESULT hr = ::LoadFromWICFile(path.c_str(), WIC_FLAGS_NONE, &md, img);
CHECK(hr);
hr = ::CreateShaderResourceView(_device.Get(), img.GetImages(), img.GetImageCount(), md, _shaderResourceView.GetAddressOf());
CHECK(hr);
}
- ID3D11ShaderResourceView : 쉐이더가 읽을 수 있도록 GPU 리소스(텍스처, 버퍼 등)를 뷰형태로 표현
- WIC(Windows Imaging Component) : JPEG, PNG, BMP 등 다양한 포맷의 이미지를 읽기 위한 Windows 기본 라이브러리
2. ConstantBuffer
- CPU와 GPU를 잇는 다리 역할
- CPU가 매 프레임 계산한 데이터를 GPU 쉐이더로 넘겨주는 역할
D3D11_USAGE_DYNAMIC + D3D11_CPU_ACCESS_WRITE로 CPU가 직접 수정 가능
- Generic(T) 구조체를 그대로 GPU 버퍼에 복사 가능
#pragma once
template <typename T>
class ConstantBuffer
{
public:
ConstantBuffer(ComPtr<ID3D11Device> device, ComPtr<ID3D11DeviceContext> deviceContext)
: _device(device), _deviceContext(deviceContext)
{
}
~ConstantBuffer() {}
ComPtr<ID3D11Buffer> GetComPtr() { return _constantBuffer; }
void Create()
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.ByteWidth = sizeof(T);
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
HRESULT hr = _device->CreateBuffer(&desc, nullptr, _constantBuffer.GetAddressOf());
CHECK(hr);
}
void CopyData(const T& data)
{
D3D11_MAPPED_SUBRESOURCE subResource;
ZeroMemory(&subResource, sizeof(subResource));
_deviceContext->Map(_constantBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource);
::memcpy(subResource.pData, &data, sizeof(data));
_deviceContext->Unmap(_constantBuffer.Get(), 0);
}
private:
ComPtr<ID3D11Device> _device;
ComPtr<ID3D11DeviceContext> _deviceContext;
ComPtr<ID3D11Buffer> _constantBuffer;
};
- 상수버퍼 : 쉐이더가 매 프레임 사용하는 상수를 효율적으로 전달하기 위해
ID3D11Buffer를 D3D11_BIND_CONSTANT_BUFFER로 생성
- D3D11_USAGE_DYNAMIC + D3D11_CPU_ACCESS_WRITE : CPU에서 매 프레임 데이터를 덮어쓸 때 권장되는 조합 (기존 버퍼내용 무시 후 새 데이터로 갱신)
3. Shader
- 쉐이더 로드 및 컴파일 관리
.hlsl 파일을 읽어 DirectX 컴파일러(D3DCompileFromFile)로 쉐이더 컴파일
#pragma once
enum ShaderScope
{
SS_None = 0,
SS_VertexShader = (1 << 0),
SS_PixelShader = (1 << 1),
SS_Both = SS_VertexShader | SS_PixelShader
};
class Shader
{
public:
Shader(ComPtr<ID3D11Device> device);
virtual ~Shader();
virtual void Create(const wstring& path, const string& name, const string& version) abstract;
ComPtr<ID3DBlob> GetBlob() { return _blob; }
protected:
void LoadShaderFromFile(const wstring& path, const string& name, const string& version);
protected:
wstring _paht;
string _name;
ComPtr<ID3D11Device> _device;
ComPtr<ID3DBlob> _blob;
};
class VertexShader : public Shader
{
using Super = Shader;
public:
VertexShader(ComPtr<ID3D11Device> device);
~VertexShader();
ComPtr<ID3D11VertexShader> GetComPtr() { return _vertexShader; }
virtual void Create(const wstring& path, const string& name, const string& version) override;
protected:
ComPtr<ID3D11VertexShader> _vertexShader;
};
class PixelShader : public Shader
{
using Super = Shader;
public:
PixelShader(ComPtr<ID3D11Device> device);
~PixelShader();
ComPtr<ID3D11PixelShader> GetComPtr() { return _pixelShader; }
virtual void Create(const wstring& path, const string& name, const string& version) override;
protected:
ComPtr<ID3D11PixelShader> _pixelShader;
};
#include "pch.h"
#include "Shader.h"
Shader::Shader(ComPtr<ID3D11Device> device)
: _device(device)
{
}
Shader::~Shader()
{
}
void Shader::LoadShaderFromFile(const wstring& path, const string& name, const string& version)
{
_paht = path;
_name = name;
const uint32 compileFlag = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
HRESULT hr = ::D3DCompileFromFile(
path.c_str(),
nullptr,
D3D_COMPILE_STANDARD_FILE_INCLUDE,
name.c_str(),
version.c_str(),
compileFlag,
0,
_blob.GetAddressOf(),
nullptr);
CHECK(hr);
}
VertexShader::VertexShader(ComPtr<ID3D11Device> device)
: Super(device)
{
}
VertexShader::~VertexShader()
{
}
void VertexShader::Create(const wstring& path, const string& name, const string& version)
{
LoadShaderFromFile(path, name, version);
HRESULT hr = _device->CreateVertexShader(_blob->GetBufferPointer(), _blob->GetBufferSize(), nullptr, _vertexShader.GetAddressOf());
CHECK(hr);
}
PixelShader::PixelShader(ComPtr<ID3D11Device> device)
: Super(device)
{
}
PixelShader::~PixelShader()
{
}
void PixelShader::Create(const wstring& path, const string& name, const string& version)
{
LoadShaderFromFile(path, name, version);
HRESULT hr = _device->CreatePixelShader(_blob->GetBufferPointer(), _blob->GetBufferSize(), nullptr, _pixelShader.GetAddressOf());
CHECK(hr);
}
- D3DCompileFromFile() : .hlsl 파일을 컴파일하여 바이트코드(ID3DBlob)를 생성
ID3D11Device::CreateVertexShader() / CreatePixelShader() :바이트코드를 실제 GPU용 셰이더 객체로 생성
마무리
| 이름 | 설명 |
|---|
| Texture | 이미지를 GPU 리소스로 변환 (SRV 생성) |
| ConstantBuffer | CPU -> GPU 상수 데이터 전달 |
| Shader | HLSL 파일 로드 및 쉐이더 객체 생성 |
| VertexShader / PixelShader | 렌더링 파이프라인의 핵심 단계 구성 |