DirectX11에서 IndexBuffer와 UV 좌표를 활용한 사각형 출력 및 텍스처 매핑 시스템 구축
사각형은 실제로 삼각형 2개로 구성되며, 삼각형 하나당 정점이 3개씩 필요하므로 총 6개의 정점이 필요하다.
하지만 같은 정점을 중복해서 메모리에 넣는 건 비효율적이다.
→ 이때 필요한 것이 IndexBuffer.
정점(Vertex)은 4개만 정의하고,
삼각형 2개를 구성하기 위한 인덱스만 따로 정의하여 메모리를 절약할 수 있다.
Sample() 함수를 통해 input.uv 위치의 픽셀 색상을 추출한다.Vertex에 UV 좌표 추가 VS_INPUT, VS_OUTPUT, PS) DirectXTex 라이브러리 사용 (LoadFromWICFile, CreateShaderResourceView) | 용어 | 설명 |
|---|---|
| IndexBuffer | 정점을 재사용하여 삼각형을 구성하는 인덱스 배열 |
| UV 좌표 | 텍스처 좌표계, 보통 (0,0)~(1,1) 사이 값 |
| TEXCOORD | 셰이더에서 UV 값을 전달하는 세마틱 |
| Texture2D | HLSL에서 텍스처 객체를 나타내는 타입 |
| SamplerState | 텍스처 보간/샘플링 방식 정의 객체 |
| ShaderResourceView (SRV) | GPU의 텍스처 리소스를 셰이더에서 접근하게 해주는 인터페이스 |
| register(t0), register(s0) | 텍스처 및 샘플러의 바인딩 위치 |
_vertices.resize(4);
_vertices[0].position = Vec3(-0.5f, -0.5f, 0.f); _vertices[0].uv = Vec2(0.f, 1.f);
_vertices[1].position = Vec3(-0.5f, 0.5f, 0.f); _vertices[1].uv = Vec2(0.f, 0.f);
_vertices[2].position = Vec3(0.5f, -0.5f, 0.f); _vertices[2].uv = Vec2(1.f, 1.f);
_vertices[3].position = Vec3(0.5f, 0.5f, 0.f); _vertices[3].uv = Vec2(1.f, 0.f);
_indices = { 0, 1, 2, 2, 1, 3 };
D3D11_BUFFER_DESC desc = {};
desc.Usage = D3D11_USAGE_IMMUTABLE;
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
desc.ByteWidth = sizeof(uint32) * _indices.size();
D3D11_SUBRESOURCE_DATA data = {};
data.pSysMem = _indices.data();
HRESULT hr = _device->CreateBuffer(&desc, &data, _indexBuffer.GetAddressOf());
CHECK(hr);
IMMUTABLE) IndexBuffer를 생성하고 바인딩._deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset);
_deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);
_deviceContext->IASetInputLayout(_inputLayout.Get());
_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
_deviceContext->DrawIndexed(_indices.size(), 0, 0);
DrawIndexed()로 인덱스 기반 렌더링.struct Vertex
{
Vec3 position;
Vec2 uv;
};
Color는 제거하고, uv 추가.D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
Vec3(position)이 12바이트이기 때문.struct VS_INPUT
{
float4 position : POSITION;
float2 uv : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD;
};
VS_OUTPUT VS(VS_INPUT input)
{
VS_OUTPUT output;
output.position = input.position;
output.uv = input.uv;
return output;
}
Texture2D texture0 : register(t0);
SamplerState sampler0 : register(s0);
float4 PS(VS_OUTPUT input) : SV_Target
{
float4 color = texture0.Sample(sampler0, input.uv);
return color;
}
register(t0), register(s0)로 바인딩한 텍스처와 샘플러를 통해 UV 위치에서 픽셀 추출.ComPtr<ID3D11ShaderResourceView> _shaderResourceView = nullptr;
void Game::CreateSRV()
{
DirectX::TexMetadata md;
DirectX::ScratchImage img;
HRESULT hr = ::LoadFromWICFile(L"cat.png", WIC_FLAGS_NONE, &md, img);
CHECK(hr);
hr = ::CreateShaderResourceView(
_device.Get(), img.GetImages(), img.GetImageCount(),
md, _shaderResourceView.GetAddressOf());
CHECK(hr);
}
DirectXTex 라이브러리로 텍스처 로딩 후 SRV 생성._deviceContext->PSSetShader(_pixelShader.Get(), nullptr, 0);
_deviceContext->PSSetShaderResources(0, 1, _shaderResourceView.GetAddressOf());
t0에 텍스처가 바인딩된다.✅ IndexBuffer를 활용하면 정점 재사용이 가능해져 메모리 최적화에 큰 도움이 된다.
✅ UV 좌표는 텍스처 맵핑의 기본이며, 이미지의 (0,0)~(1,1) 사이 좌표계를 기반으로 한다.
✅ HLSL Shader와 InputLayout 간의 세마틱 이름은 반드시 정확하게 일치해야 한다.
✅ Shader에서 텍스처 색상을 추출하려면 Sample() 함수를 통해 UV 좌표 기반 샘플링이 필요하다.
✅ 텍스처를 GPU에 연결하려면 SRV를 생성하고, PSSetShaderResources()로 바인딩해야 한다.
✅ DirectX11의 렌더링 파이프라인은 Input Assembler → Vertex Shader → Rasterizer → Pixel Shader → Output Merger 단계로 구성되며, 각각에 맞는 자원 설정이 필요하다.
✅ 추후 다중 텍스처 처리, 머티리얼 시스템, 셰이더 조건 분기 등으로 확장할 수 있다.