이전 포스팅에서 VertexBuffer를 만들어서 건네줬는데 그 이외에 IndexBuffer도 있다.
IndexBuffer에 대해 알아보자.
IndexBuffer
만약 우리가 사각형을 화면에 띄운다고 해보자.
그러면 정점이 몇개가 필요할까? 4개가 아닌 6개가 필요하다. 그 이유는 삼각형 단위로 이루어져있기 때문이다.
그런데 지금 당장만 생각해도 되게 비 효율적일것 같다는 생각이 든다. 아무리 삼각형 단위로 계산한다고 해도 정말 큰 에셋이라면 정점이 수만가지가 될텐데 그걸 다 계산하기 쉽지않을 것이다.
그래서 이럴경우를 대비해 정점마다 넘버링(인덱스)를 추가해서 관리하는 것이 IndexBuffer이다.
사각형을 한번 만들어보자.
필드에 정점을 아래와 같이 인덱스를 매기자.
1 3
0 2
즉 012 / 123 두 개의 삼각형을 만든다는 것이다.
vector<uint32> _indices;
ComPtr<ID3D11Buffer> _indexBuffer = nullptr;
void Game::CreateGeometry()
{
// VertextData
{
_vertices.resize(4);
// 1 3
// 0 2
_vertices[0].position = Vec3(-0.5f, -0.5f, 0);
_vertices[0].color = Color(1.f, 0.f, 0.f, 1.f);
_vertices[1].position = Vec3(-0.5f, 0.5f, 0);
_vertices[1].color = Color(1.f, 0.f, 0.f, 1.f);
_vertices[2].position = Vec3(0.5f, -0.5f, 0);
_vertices[2].color = Color(1.f, 0.f, 1.f, 1.f);
_vertices[3].position = Vec3(0.5f, 0.5f, 0);
_vertices[3].color = Color(1.f, 0.f, 0.f, 1.f);
}
// VectexBuffer
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
// GPU read only
desc.Usage = D3D11_USAGE_IMMUTABLE;
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.ByteWidth = (uint32)(sizeof(Vertex) * _vertices.size());
D3D11_SUBRESOURCE_DATA data;
ZeroMemory(&data, sizeof(data));
data.pSysMem = _vertices.data();
HRESULT hr = _device->CreateBuffer(&desc, &data, _vertexBuffer.GetAddressOf());
CHECK(hr);
}
// Index
{
_indices = { 0,1,2,2,1,3 };
}
// IndexBuffer
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Usage = D3D11_USAGE_IMMUTABLE;
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
desc.ByteWidth = (uint32)(sizeof(uint32) * _indices.size());
D3D11_SUBRESOURCE_DATA data;
ZeroMemory(&data, sizeof(data));
data.pSysMem = _indices.data();
HRESULT hr = _device->CreateBuffer(&desc, &data, _indexBuffer.GetAddressOf());
CHECK(hr);
}
}
깔끔하게 그려진걸 볼 수 있다.
vertexBuffer보다 indexBuffer의 장점은 넘겨주는 정점의 개수를 줄일 수 있어서 메모리 측면에서 절약할 수 있다는 점이다.
특정 이미지 띄우기
특정 이미지를 띄우기 위해서는 UV좌표에 대해 알아야 한다. uv는 텍스처 이미지를 3차원 공간애 맵핑하기 위한 2차원 공간에서의 좌표를 의미한다.
비율이라고 이해하면 된다. 특정 텍스처를 현재 화면에 띄울때, 얼마만큼의 비율을 차지하냐는 의미이다.
이미지의 크기가 얼마나 크던 작던, 최소는 0, 0이고 최대 좌표는 1, 1의 좌표를 가진다.
이를 객체에 이미지를 씌울 때는 0과 1에 입히려는 이미지의 크기로 나눈 비율을 대입하여 이미지를 출력한다.
기존에 작성한 Vertex 구조체에서 color를 삭제하고 Vec2 uv를 추가한다. 그리고 사각형의 uv를 수정한다.
struct Vertex
{
Vec3 position;
//Color color;
Vec2 uv;
};
struct VS_INPUT
{
float4 position : POSITION;
//float4 color : COLOR;
float2 uv : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : SV_POSITION;
//float4 color : COLOR;
float2 uv : TEXCOORD;
};
// IA - VS - RS - PS - OM
// 그중 VS
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;
}
기존에 있던 쉐이더도 텍스처를 띄우기 위해 수정해준다.
ShaderResourceView를 추가해서 Skeleton파일을 가져온다.
void Game::CreateSRV()
{
DirectX::TexMetadata md;
DirectX::ScratchImage img;
HRESULT hr = ::LoadFromWICFile(L"Skeleton.png", WIC_FLAGS_NONE, &md, img);
CHECK(hr);
hr = ::CreateShaderResourceView(_device.Get(), img.GetImages(), img.GetImageCount(), md, _shaderResourceView.GetAddressOf());
CHECK(hr);
}
렌더하는 부분에 ShaderResourceView를 추가해주면 그림이 정상적으로 출력된다.
'C++ > DirectX 11' 카테고리의 다른 글
[DirectX] 프레임워크 제작기 - Graphics, IA, Geomotry (1) | 2024.09.02 |
---|---|
[DirectX] 행렬 - SRT 변환 행렬과 좌표계 변환 행렬 및 예제 (0) | 2024.08.31 |
[DirectX] DirectX 11 입문하기 - Constant Buffer와 State (0) | 2024.08.29 |
[DirectX] DirectX 11 입문하기 - 장치 초기화와 삼각형 띄우기 (0) | 2024.08.28 |
[DirectX] DirectX 11 입문하기 - 그래픽스 OT, 기본 프레임 워크 (0) | 2024.08.27 |