DirectX11 공부 4일차(Wrapping Class - VertexBuffer, IndexBuffer, InputLayer)
04 Jun 2021
Reading time ~3 minutes
Wrapping Class - VertexBuffer
이젠 VertexBuffer 뤠핑 할 순서이다.
D3D11_VertexBuffer.h
#pragma once
class D3D11_VertexBuffer final
{
public:
D3D11_VertexBuffer(class Graphics* graphics);
~D3D11_VertexBuffer();
ID3D11Buffer* GetResource() const { return buffer; }
const uint& GetStride() { return stride; }
const uint& GetOffset() { return offset; }
const uint& GetCount() { return count; }
template<typename T>
void Create(const std::vector<T>& vertices, const D3D11_USAGE& usage = D3D11_USAGE_IMMUTABLE);
void Clear();
private:
ID3D11Device* device = nullptr;
ID3D11Buffer* buffer = nullptr;
uint stride = 0;
uint offset = 0;
uint count = 0;
};
template<typename T>
inline void D3D11_VertexBuffer::Create(const std::vector<T>& vertices, const D3D11_USAGE& usage)
{
stride = sizeof(T);
count = static_cast<uint>(vertices.size());
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.ByteWidth = stride * count;
desc.Usage = usage;
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
switch (usage)
{
case D3D11_USAGE_DEFAULT:
case D3D11_USAGE_IMMUTABLE:
desc.CPUAccessFlags = 0;
break;
case D3D11_USAGE_DYNAMIC:
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
break;
case D3D11_USAGE_STAGING:
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
break;
default:
break;
}
D3D11_SUBRESOURCE_DATA sub_data;
ZeroMemory(&sub_data, sizeof(D3D11_SUBRESOURCE_DATA));
sub_data.pSysMem = vertices.data();
HRESULT hr = device->CreateBuffer(&desc, &sub_data, &buffer);
assert(SUCCEEDED(hr));
}
VertexColor와 VertexTexture 이 두개의 버퍼를 만들수 있도록 템플릿 사용
뭐 나머지는 전에 사용했던 변수들 넣은거라 큰 차이점은 없다.
D3D11_VertexBuffer.cpp
#include "stdafx.h"
#include "D3D11_VertexBuffer.h"
D3D11_VertexBuffer::D3D11_VertexBuffer(Graphics* graphics)
{
device = graphics->GetDevice();
}
D3D11_VertexBuffer::~D3D11_VertexBuffer()
{
Clear();
}
void D3D11_VertexBuffer::Clear()
{
SAFE_RELEASE(buffer);
stride = 0;
offset = 0;
count = 0;
}
Wrapping Class - IndexBuffer
위에 VertexBuffer와 큰 차이는 없지만,
템플릿을 사용할 필요가 없기 때문에 사용을 안했다.
D3D11_VertexBuffer.h
#pragma once
class D3D11_VertexBuffer final
{
public:
D3D11_VertexBuffer(class Graphics* graphics);
~D3D11_VertexBuffer();
ID3D11Buffer* GetResource() const { return buffer; }
const uint& GetStride() { return stride; }
const uint& GetOffset() { return offset; }
const uint& GetCount() { return count; }
template<typename T>
void Create(const std::vector<T>& vertices, const D3D11_USAGE& usage = D3D11_USAGE_IMMUTABLE);
void Clear();
private:
ID3D11Device* device = nullptr;
ID3D11Buffer* buffer = nullptr;
uint stride = 0;
uint offset = 0;
uint count = 0;
};
template<typename T>
inline void D3D11_VertexBuffer::Create(const std::vector<T>& vertices, const D3D11_USAGE& usage)
{
stride = sizeof(T);
count = static_cast<uint>(vertices.size());
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.ByteWidth = stride * count;
desc.Usage = usage;
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
switch (usage)
{
case D3D11_USAGE_DEFAULT:
case D3D11_USAGE_IMMUTABLE:
desc.CPUAccessFlags = 0;
break;
case D3D11_USAGE_DYNAMIC:
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
break;
case D3D11_USAGE_STAGING:
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
break;
default:
break;
}
D3D11_SUBRESOURCE_DATA sub_data;
ZeroMemory(&sub_data, sizeof(D3D11_SUBRESOURCE_DATA));
sub_data.pSysMem = vertices.data();
HRESULT hr = device->CreateBuffer(&desc, &sub_data, &buffer);
assert(SUCCEEDED(hr));
}
D3D11_VertexBuffer.cpp
#include "stdafx.h"
#include "D3D11_VertexBuffer.h"
D3D11_VertexBuffer::D3D11_VertexBuffer(Graphics* graphics)
{
device = graphics->GetDevice();
}
D3D11_VertexBuffer::~D3D11_VertexBuffer()
{
Clear();
}
void D3D11_VertexBuffer::Clear()
{
SAFE_RELEASE(buffer);
stride = 0;
offset = 0;
count = 0;
}
Wrapping Class - InputLayer
InputLayer.h
#pragma once
class D3D11_InputLayout final
{
public:
D3D11_InputLayout(class Graphics* graphics);
~D3D11_InputLayout();
ID3D11InputLayout* GetResource() const { return input_layout; }
void Create(D3D11_INPUT_ELEMENT_DESC* descs, const uint& count, ID3DBlob* blop);
void Clear();
private:
ID3D11Device* device = nullptr;
ID3D11InputLayout* input_layout = nullptr;
};
InputLayer.cpp
#include "stdafx.h"
#include "D3D11_InputLayout.h"
D3D11_InputLayout::D3D11_InputLayout(Graphics* graphics)
{
device = graphics->GetDevice();
}
D3D11_InputLayout::~D3D11_InputLayout()
{
Clear();
}
void D3D11_InputLayout::Create(D3D11_INPUT_ELEMENT_DESC* descs, const uint& count, ID3DBlob* blob)
{
if (descs == nullptr || count == 0 || blob == nullptr)
{
assert(false);
}
HRESULT hr = device->CreateInputLayout
(
descs,
count,
blob->GetBufferPointer(),
blob->GetBufferSize(),
&input_layout
);
assert(SUCCEEDED(hr));
}
void D3D11_InputLayout::Clear()
{
SAFE_RELEASE(input_layout);
}
Execute에서 큰 차이점은 없지만,
void Execute::Render()
{
uint stride = sizeof(D3D11_VertexTexture);
uint offset = 0;
graphics->Begin();
{
// IA
ID3D11Buffer* bffers[] = { vertex_buffer->GetResource() };
graphics->GetDeviceContext()->IASetVertexBuffers(0, 1, bffers, &vertex_buffer->GetStride(), &vertex_buffer->GetOffset());
graphics->GetDeviceContext()->IASetIndexBuffer(index_buffer->GetResource(), DXGI_FORMAT_R32_UINT, index_buffer->GetOffset());
graphics->GetDeviceContext()->IASetInputLayout(input_layout->GetResource());
graphics->GetDeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// VS // 정점 개수만큼 호출
graphics->GetDeviceContext()->VSSetShader(vertex_shader, nullptr, 0);
graphics->GetDeviceContext()->VSSetConstantBuffers(0, 1, &gpu_buffer); // StartSlot - hlsl코드에서 buffer를 등록할 때 입력했던 버퍼 번호를 나타낸다.
// RS
graphics->GetDeviceContext()->RSSetState(rasterizer_state);
// PS
graphics->GetDeviceContext()->PSSetShader(pixel_shader, nullptr, 0);
graphics->GetDeviceContext()->PSSetShaderResources(0, 1, &shader_resource);
graphics->GetDeviceContext()->PSSetSamplers(0, 1, &sampler_state);
//OM
graphics->GetDeviceContext()->OMSetBlendState(blend_state, nullptr, 0xffffffff);
graphics->GetDeviceContext()->DrawIndexed(6, 0, 0);
}
graphics->End();
}
뭔가 이상한 점이 있다 왜 버퍼를 새로 생성했는지다.
이것은 c++에서 l-Value r-Value 때문인데
이 영상이 진짜 도움이 많이 되었다. 그래서 위에 count나 offset을 보내는 변수를 보면 전부 주소값으로 보내는 것을 볼 수 있다.