삼각형 띄우기

ㅋㅋ·2022년 7월 14일
0

DirectX12강의

목록 보기
4/39

Root Signature

GPU내의 램을 사용할 수 있도록 함

void RootSignature::Init(ComPtr<ID3D12Device> device)
{
	D3D12_ROOT_SIGNATURE_DESC sigDesc = CD3DX12_ROOT_SIGNATURE_DESC(D3D12_DEFAULT);
	sigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;

	...
    
	::D3D12SerializeRootSignature(&sigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &blobSignature, &blobError);
	device->CreateRootSignature(0, blobSignature->GetBufferPointer(), blobSignature->GetBufferSize(), IID_PPV_ARGS(&_signature));
}

INPUT_ASSEMBLER_INPUT 모드로 root signature 생성

추후 다른 기능이 필요할 때 모드를 추가


Mesh

정점 정보들과 버퍼를 관리하는 클래스

정점은 위치와 색 정보로 이루어져 있음

void Mesh::Init(vector<Vertex>& vec)
{
	...

	D3D12_HEAP_PROPERTIES heapProperty = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
	D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(bufferSize);

	DEVICE->CreateCommittedResource(
		&heapProperty,
		D3D12_HEAP_FLAG_NONE,
		&desc,
		D3D12_RESOURCE_STATE_GENERIC_READ,
		nullptr,
		IID_PPV_ARGS(&_vertexBuffer));

	...
}

GPU 메모리에 정보를 업로드 할때 D3D12_HEAP_TYPE_UPLOAD 플래그로 정의

원칙적으로는 해당 플래그로 할당받은 메모리는 업로드만 하고 GPU가 사용하면 안됨

NORMAL 플래그로 GPU가 사용하는 공간이 하나 더 있어야 함

해당 구현은 업로드 메모리와 사용 메모리를 한 곳에서 진행

나무나 돌 같은 고정된 메쉬는 NORMAL 타입으로 지정하는게 더 빠르다고 함

UPLOAD 타입은 실시간으로 변하는 메쉬를 업로드 하는 용

void Mesh::Init(vector<Vertex>& vec)
{
	...

	void* vertexDataBuffer = nullptr;
	CD3DX12_RANGE readRange(0, 0);
	_vertexBuffer->Map(0, &readRange, &vertexDataBuffer);
	::memcpy(vertexDataBuffer, &vec[0], bufferSize);
	_vertexBuffer->Unmap(0, nullptr);

	_vertexBufferView.BufferLocation = _vertexBuffer->GetGPUVirtualAddress();
	_vertexBufferView.StrideInBytes = sizeof(Vertex);
	_vertexBufferView.SizeInBytes = bufferSize;
}

GPU 메모리 복사는 Map -> 복사 -> Unmap 순으로 이루어짐

void Mesh::Render()
{
	CMD_LIST->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	CMD_LIST->IASetVertexBuffers(0, 1, &_vertexBufferView);
	CMD_LIST->DrawInstanced(_vertexCount, 1, 0, 0);
}

정점 정보들이 D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST 플래그로 삼각형들이라는 것을 알려줌

렌더링은 엔진의 렌더링이 끝나기 전에 list에 요청 사항을 넣어두고

엔진이 그래픽카드로 요청할 때 넘어가도록 함


Shader

그래픽카드가 무엇을 해야할지 기술해둔 클래스(랜더링 파이프라인)

쉐이더는 보통 파일로 관리한다. (hlsl, hlsli (header))

void Shader::Init(const wstring& path)
{
	CreateVertexShader(path, "VS_Main", "vs_5_0");
	CreatePixelShader(path, "PS_Main", "ps_5_0");

	D3D12_INPUT_ELEMENT_DESC desc[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
	};

	...
}

vertex, pixel 쉐이더 사용하는데 함수명은 VS_Main, PS_Main이다.

VS_OUT VS_Main(VS_IN input)
{
    VS_OUT output = (VS_OUT)0;

    output.pos = float4(input.pos, 1.f);
    output.color = input.color;

    return output;
}

float4 PS_Main(VS_OUT input) : SV_Target
{
    return input.color;
}

vertex와 pixel 쉐이더에서 해야할 일을 쉐이더 파일에 구현

vertex 쉐이더에서 VS_IN 데이터가 들어와 VS_OUT으로 출력되고

pixel 쉐이더에서 VS_OUT 데이터가 입력이 들어오고 float4으로 출력

void Shader::CreateShader(const wstring& path, const string& name, const string& version, ComPtr<ID3DBlob>& blob, D3D12_SHADER_BYTECODE& shaderByteCode)
{
	...

	if (FAILED(::D3DCompileFromFile(path.c_str(), nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE
		, name.c_str(), version.c_str(), compileFlag, 0, &blob, &_errBlob)))
	{
		::MessageBoxA(nullptr, "Shader Create Failed !", nullptr, MB_OK);
	}

	shaderByteCode = { blob->GetBufferPointer(), blob->GetBufferSize() };
}

CreateShader 함수에서 쉐이더 파일을 파싱하여 해당 정보를 blob 포인터에 넣음

vector<Vertex> vec(3);
vec[0].pos = Vec3(0.f, 0.5f, 0.5f);
vec[0].color = Vec4(1.f, 0.f, 0.f, 1.f);
vec[1].pos = Vec3(0.5f, -0.5f, 0.5f);
vec[1].color = Vec4(0.f, 1.0f, 0.f, 1.f);
vec[2].pos = Vec3(-0.5f, -0.5f, 0.5f);
vec[2].color = Vec4(0.f, 0.f, 1.f, 1.f);
mesh->Init(vec);

임시로 삼각형을 위와 같이 만들어 테스트

화면상 중앙이 0,0 위와 오른쪽이 +방향인 좌표계

0개의 댓글