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

      게임 개발자 유정룡

      포트폴리오

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

DirectX11 공부 12일차(Renderer)

13 Jun 2021

Reading time ~2 minutes

Renderer

지금까지 만들었던 프로젝트는 Actor클래스에 랜더링 해주는 함수가 있다.

각 액터마다 다른 랜더링을 하려면, 처음에 Actor클래스를 선언할때 변수를 넣어줘야 하지만, Renderer만 따로 빼서 담당하게 하면 좀 더 유지보수가 용이해지기 때문에 빼준다.

이번 클래스에서 렌더링 해주는 부분과, Rasterizer와 BlendState의 설정을 담당해주는 부분 그리고, 언급한 부분 이외의 부분을 관리해주는 부분으로 나눈다.

RendererTypes.h

#pragma once
#include "stdafx.h"

enum class RenderableType : uint
{
	Opaque,
	Camera,
};

enum class RasterizerStateType : uint
{
	Cull_Back_Solid,
	Cull_Front_Solid,
	Cull_None_Solid,
	Cull_Back_Wireframe,
	Cull_Front_Wireframe,
	Cull_None_Wireframe,
};

enum class BlendStateType : uint
{
	Disabled,
	Alpha
};

일단 레스터라이저 단계와 블렌드 스테이트에서 사용할 enumclass를 만들어 정리를 해주자

ISubsystem.h

#pragma once

#include "Core/Subsystem/ISubsystem.h"
#include "RendererConstantBuffers.h"
#include "RendererTypes.h"

class Renderer final : public ISubsystem
{
public:
	Renderer(class Context* const context);
	~Renderer();

	bool Initialize() override;
	void Update() override;

	void UpdateRenderables(class Scene* const scene);

private:
	void CreateConstantBuffers();
	void CreateRasterizerStates();
	void CreateBlendStates();

	void UpdateCameraBuffer();
	void UpdateObjectBuffer();

private:
	class Graphics* graphics = nullptr;
	class CameraComponent* camera = nullptr;
	std::shared_ptr<class D3D11_Pipeline> pipeline;

	CAMERA_DATA cpu_camera_buffer;
	std::shared_ptr<class D3D11_ConstantBuffer> gpu_camera_buffer;

	TRANSFORM_DATA cpu_object_buffer;
	std::shared_ptr<class D3D11_ConstantBuffer> gpu_object_buffer;

/* RanererPasses.cpp */
private:
	void PassMain();

/* RanererResources.cpp */
private:
	std::map<RasterizerStateType, std::shared_ptr<class D3D11_RasterizerState>> rasterizers;
	std::map<BlendStateType, std::shared_ptr<class D3D11_BlendState>> blend_states;

	std::unordered_map<RenderableType, std::vector<class Actor*>> renderables;
};

PassMain()은 RendererPasses에서,

RenderableType은 RanererResources 에서 구현

RendererResource.cpp

#include "stdafx.h"
#include "Renderer.h"

void Renderer::CreateConstantBuffers()
{
	gpu_camera_buffer = std::make_shared<D3D11_ConstantBuffer>(graphics);
	gpu_camera_buffer->Create<CAMERA_DATA>();

	gpu_object_buffer = std::make_shared<D3D11_ConstantBuffer>(graphics);
	gpu_object_buffer->Create<TRANSFORM_DATA>();
}

void Renderer::CreateRasterizerStates()
{
	rasterizers[RasterizerStateType::Cull_Back_Solid] = std::make_shared<D3D11_RasterizerState>(graphics);
	rasterizers[RasterizerStateType::Cull_Back_Solid]->Create(D3D11_CULL_BACK, D3D11_FILL_SOLID);

	rasterizers[RasterizerStateType::Cull_Front_Solid] = std::make_shared<D3D11_RasterizerState>(graphics);
	rasterizers[RasterizerStateType::Cull_Front_Solid]->Create(D3D11_CULL_FRONT, D3D11_FILL_SOLID);

	rasterizers[RasterizerStateType::Cull_None_Solid] = std::make_shared<D3D11_RasterizerState>(graphics);
	rasterizers[RasterizerStateType::Cull_None_Solid]->Create(D3D11_CULL_NONE, D3D11_FILL_SOLID);

	rasterizers[RasterizerStateType::Cull_Back_Wireframe] = std::make_shared<D3D11_RasterizerState>(graphics);
	rasterizers[RasterizerStateType::Cull_Back_Wireframe]->Create(D3D11_CULL_BACK, D3D11_FILL_WIREFRAME);

	rasterizers[RasterizerStateType::Cull_Front_Wireframe] = std::make_shared<D3D11_RasterizerState>(graphics);
	rasterizers[RasterizerStateType::Cull_Front_Wireframe]->Create(D3D11_CULL_FRONT, D3D11_FILL_WIREFRAME);

	rasterizers[RasterizerStateType::Cull_None_Wireframe] = std::make_shared<D3D11_RasterizerState>(graphics);
	rasterizers[RasterizerStateType::Cull_None_Wireframe]->Create(D3D11_CULL_NONE, D3D11_FILL_WIREFRAME);
}

void Renderer::CreateBlendStates()
{
	blend_states[BlendStateType::Disabled] = std::make_shared<D3D11_BlendState>(graphics);
	blend_states[BlendStateType::Disabled]->Create(false);

	blend_states[BlendStateType::Alpha] = std::make_shared<D3D11_BlendState>(graphics);
	blend_states[BlendStateType::Alpha]->Create(true);
}

미리 정의해준다. 이렇게 하면 나중에 새로 생성할때 문제가 되지만, 지금 말고 나중에 처리하자

Renderer.cpp

bool Renderer::Initialize()
{
	graphics = context->GetSubsystem<Graphics>();
	graphics->CreateBackBuffer(static_cast<uint>(Settings::Get().GetWidth()), static_cast<uint>(Settings::Get().GetHeight()));

	pipeline = std::make_shared<class D3D11_Pipeline>(context->GetSubsystem<Graphics>());

	CreateConstantBuffers();
	CreateRasterizerStates();
	CreateBlendStates();

	return true;
}

void Renderer::Update()
{
	if (!camera)
	{
		return;
	}

	D3DXMatrixTranspose(&cpu_camera_buffer.view, &camera->GetView());
	D3DXMatrixTranspose(&cpu_camera_buffer.projection, &camera->GetProjection());
	UpdateCameraBuffer();

	graphics->Begin();
	PassMain();
	graphics->End();
}

void Renderer::UpdateRenderables(Scene* const scene)
{
	std::vector<std::shared_ptr<class Actor>> actors = scene->GetActors();
	if (actors.empty())
	{
		return;
	}

	for (const auto& actor : actors)
	{
		std::shared_ptr<CameraComponent> camera_component = actor->GetComponent<CameraComponent>();
		std::shared_ptr<MeshRendererComponent> mesh_renderer_component = actor->GetComponent<MeshRendererComponent>();

		if (camera_component)
		{
			renderables[RenderableType::Camera].emplace_back(actor.get());
			camera = camera_component.get();
		}

		if (mesh_renderer_component)
		{
			renderables[RenderableType::Opaque].emplace_back(actor.get());
		}
	}
}

void Renderer::UpdateCameraBuffer()
{
	CAMERA_DATA* buffer = gpu_camera_buffer->Map<CAMERA_DATA>();
	*buffer = cpu_camera_buffer;
	gpu_camera_buffer->UnMap();
}

void Renderer::UpdateObjectBuffer()
{
	TRANSFORM_DATA* buffer = gpu_object_buffer->Map<TRANSFORM_DATA>();
	*buffer = cpu_object_buffer;
	gpu_object_buffer->UnMap();
}

원래 있던 소스를 갖고 복붙하자!

RendererPasses.cpp

#include "stdafx.h"
#include "Renderer.h"
#include "Scene/Scene.h"
#include "Scene/Actor.h"
#include "Scene/Component/CameraComponent.h"
#include "Scene/Component/MeshRendererComponent.h"
#include "Scene/Component/Transform.h"

void Renderer::PassMain()
{
	std::vector<class Actor*> actors = renderables[RenderableType::Opaque];
	if (actors.empty())
	{
		return;
	}

	for (const auto& actor : actors)
	{
		std::shared_ptr<MeshRendererComponent> renderable = actor->GetComponent<MeshRendererComponent>();
		if (!renderable) 
		{
			continue;
		}

		Transform* transform = actor->GetTransform_Row();
		if (!transform)
		{
			continue;
		}

		D3D11_PipelineState pipeline_state;
		pipeline_state.input_layout = renderable->GetInputLayout().get();
		pipeline_state.primitive_topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
		pipeline_state.vertex_shader = renderable->GetVertexShader().get();
		pipeline_state.pixel_shader = renderable->GetPixelShader().get();
		pipeline_state.rasterizer_state = rasterizers[RasterizerStateType::Cull_Back_Wireframe].get();
		pipeline_state.blend_state = blend_states[BlendStateType::Alpha].get();

		if (pipeline->Begin(pipeline_state))
		{
			pipeline->SetVertexBuffer(renderable->GetVertexBuffer().get());
			pipeline->SetIndexBuffer(renderable->GetIndexBuffer().get());

			D3DXMATRIX temp = transform->GetWorldMatrix();
			D3DXMatrixTranspose(&cpu_object_buffer.world, &temp);
			UpdateObjectBuffer();

			pipeline->SetConstantBuffer(0, ShaderScope_VS, gpu_camera_buffer.get());
			pipeline->SetConstantBuffer(1, ShaderScope_VS, gpu_object_buffer.get());
			pipeline->DrawIndexed
			(
				renderable->GetIndexBuffer()->GetCount(), 
				renderable->GetIndexBuffer()->GetOffset(), 
				renderable->GetVertexBuffer()->GetOffset()
			);
			pipeline->End();
		}
	}
}

직접적으로 렌더링 해주는 부분이다.

갖고 있는거 복붙하는 형태이다…



DirectX Share Tweet +1