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();
}
}
}
직접적으로 렌더링 해주는 부분이다.
갖고 있는거 복붙하는 형태이다…