-
[DirectX] 7. Vertex Buffer(버텍스 버퍼)/Index Buffer(인덱스 버퍼)Game Development/DirectX 2024. 9. 10. 08:53
이번 글에서는 Vertex Buffer와 Index Buffer에 대해서 알아보고, 구현해보도록하겠습니다.
먼저 VertexBuffer와 Index Buffer에 대해서 설명하자면,
Vertex Buffer는 정점에 대한 정보들을 저장한 버퍼이고,
Index Buffer는 Vertex Buffer에 있는 정점을 종류별로 인덱싱한 뒤, 인덱스 데이터를 보관하는 버퍼입니다.
그럼 이제 Vertex Buffer와 Index Buffer를 구현해보도록 하겠습니다.
// VertexBuffer.h #pragma once #include <d3d11.h> #include <wrl.h> using Microsoft::WRL::ComPtr; class VertexBuffer { public: bool Init(ID3D11Device* device, void* data, int count, int elementByteWidth); void Bind(ID3D11DeviceContext* deviceContext); int Count() { return count; } unsigned int ElementByteWidth() { return elementByteWidth; } private: int count; unsigned int elementByteWidth; ComPtr<ID3D11Buffer> buffer; };
// VertexBuffer.cpp #include "VertexBuffer.h" bool VertexBuffer::Init(ID3D11Device* device, void* data, int count, int elementByteWidth) { this->count = count; this->elementByteWidth = elementByteWidth; // 버퍼 정보를 Vertex Buffer에 대한 것으로 설정 D3D11_BUFFER_DESC vertexBufferDesc; ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc)); vertexBufferDesc.ByteWidth = this->elementByteWidth * this->count; vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = 0; vertexBufferDesc.MiscFlags = 0; vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT; D3D11_SUBRESOURCE_DATA vertexBufferData; ZeroMemory(&vertexBufferData, sizeof(vertexBufferData)); vertexBufferData.pSysMem = data; // VertexBuffer 생성 HRESULT result = device->CreateBuffer( &vertexBufferDesc, &vertexBufferData, buffer.GetAddressOf() ); if (FAILED(result)) { MessageBox(nullptr, L"버텍스 버퍼 생성 실패", L"오류", 0); return false; } return true; } void VertexBuffer::Bind(ID3D11DeviceContext* deviceContext) { unsigned int stride = elementByteWidth; unsigned int offset = 0; // 정점 버퍼 배열을 입력 어셈블러 단계에서 바인딩 deviceContext->IASetVertexBuffers(0, 1, buffer.GetAddressOf(), &stride, &offset); }
// IndexBuffer.h #pragma once #include <d3d11.h> #include <wrl.h> using Microsoft::WRL::ComPtr; class IndexBuffer { public: bool Init(ID3D11Device* device, void* data, int count); void Bind(ID3D11DeviceContext* deviceContext); int Count() { return count; } private: int count; ComPtr<ID3D11Buffer> buffer; };
// IndexBuffer.cpp #include "IndexBuffer.h" bool IndexBuffer::Init(ID3D11Device* device, void* data, int count) { this->count = count; // 버퍼 정보를 Index Buffer에 대한 것으로 설정 D3D11_BUFFER_DESC indexBufferDesc; ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc)); indexBufferDesc.ByteWidth = sizeof(unsigned int) * this->count; indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; indexBufferDesc.CPUAccessFlags = 0; indexBufferDesc.MiscFlags = 0; indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; // 데이터 담기 D3D11_SUBRESOURCE_DATA indexBufferData; ZeroMemory(&indexBufferData, sizeof(indexBufferData)); indexBufferData.pSysMem = data; // 인덱스 버퍼 생성 HRESULT result = device->CreateBuffer( &indexBufferDesc, &indexBufferData, buffer.GetAddressOf() ); if (FAILED(result)) { MessageBox(nullptr, L"인덱스 버퍼 생성 실패", L"오류", 0); return false; } return true; } void IndexBuffer::Bind(ID3D11DeviceContext* deviceContext) { // 인덱스 버퍼 배열을 입력 어셈블러 단계에서 바인딩 deviceContext->IASetIndexBuffer(buffer.Get(), DXGI_FORMAT_R32_UINT, 0); }
이렇게 해서 버퍼들을 생성하는 것은 구현을 하였는데,
그럼 이제 이 버퍼들에 데이터를 넣어 주어야 합니다.
저번 글에서 ResourceLoader 클래스에 LoadModel() 메서드에서 Vertex 정보를 뽑아내는 것은 만들었습니다.
이제 여기에 다가 인덱스 버퍼에 넣을 데이터를 얻는 것을 넣어주겠습니다.
// ResourceLoader.h ... class ResourceLoader { public: ... static void LoadModel(std::string filename, std::vector<Vertex>* vertices, std::vector<unsigned int>* indices); static void LoadModel(std::string filename, std::vector<VertexUV>* vertices, std::vector<unsigned int>* indices); ... private: ... };
// ResourceLoader.cpp void ResourceLoader::LoadModel(std::string filename, std::vector<Vertex>* vertices, std::vector<unsigned int>* indices) { ... if (scene != nullptr) { for (int i = 0; i < scene->mNumMeshes; i++) { const aiMesh* mesh = scene->mMeshes[i]; ... for (unsigned int i = 0; i < mesh->mNumFaces; i++) { const aiFace& face = mesh->mFaces[i]; indices->push_back(face.mIndices[0]); indices->push_back(face.mIndices[1]); indices->push_back(face.mIndices[2]); } } } else { MessageBox(nullptr, L"모델 로드 실패", L"오류", 0); throw std::exception("모델 로드 실패"); } } void ResourceLoader::LoadModel(std::string filename, std::vector<VertexUV>* vertices, std::vector<unsigned int>* indices) { ... if (scene != nullptr) { for (int i = 0; i < scene->mNumMeshes; i++) { const aiMesh* mesh = scene->mMeshes[i]; ... for (unsigned int i = 0; i < mesh->mNumFaces; i++) { const aiFace& face = mesh->mFaces[i]; indices->push_back(face.mIndices[0]); indices->push_back(face.mIndices[1]); indices->push_back(face.mIndices[2]); } } } else { MessageBox(nullptr, L"모델 로드 실패", L"오류", 0); throw std::exception("모델 로드 실패"); } }
이렇게 해서 Index 데이터를 뽑아오는 것도 완성하였습니다.
이 데이터를 바인딩하고, 적용하는 것은 다음 글에서 카메라를 만들면서 같이 하도록 하겠습니다.
읽어주셔서 감사합니다.
'Game Development > DirectX' 카테고리의 다른 글
[DirectX] 8. 카메라 제작 (0) 2024.09.18 [DirectX] 6. 3D 모델 띄우기 (1) 2024.09.09 [DirectX] 5. 텍스처 입히기 (1) 2024.09.08 [DirectX] 4. 삼각형 띄우기 (0) 2024.06.26 [DirectX] 3-4. Matrix4 클래스 제작 (0) 2024.06.21