• Home
  • About
    • 게임 개발자 유정룡 photo

      게임 개발자 유정룡

      포트폴리오

    • Learn More
    • Email
    • Github
    • Bitbucket
  • Projects
    • All Projects
    • All Tags

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을 보내는 변수를 보면 전부 주소값으로 보내는 것을 볼 수 있다.



DirectX Share Tweet +1