RenderHelper
- 렌더링 시 쉐이더로 넘겨줄 상수 버퍼 데이터 구조체들을 정의
- CameraData : 카메라의 View / Projection 행렬을 GPU에 넘기기 위한 구조체
- TransformData : 개별 오브젝트의 World 행렬을 넘기기 위한 구조체
- AnimationDAta : 스프라이트 시트 애니메이션을 위해 "텍스처 안에서 어느 영역을 자를지" 정보를 넘기는 구조제
#pragma once
struct CameraData
{
Matrix matView = Matrix::Identity;
Matrix matProjection = Matrix::Identity;
};
struct TransformData
{
Matrix matWorld = Matrix::Identity;
};
struct AnimationData
{
Vec2 spriteOffset;
Vec2 spriteSize;
Vec2 textureSize;
float useAnimation;
float padding;
};
RenderManager
- 한 프레임 렌더링 총괄 매니저
Graphics->RenderBegin()
→ 렌더타겟/뷰포트 클리어
PushCameraData()
→ 현재 카메라 View/Proj를 상수 버퍼에 복사
GatherRenderableObjects()
→ 씬 안에서 MeshRenderer가 붙어 있는 GameObject들만 모음
RenderObjects()
→ 각 오브젝트에 대해
Transform → World 행렬 상수버퍼
Animator → AnimationData 상수버퍼
Material/Shader/Texture → Pipeline에 세팅
Mesh → Vertex/IndexBuffer 바인딩
최종적으로 DrawIndexed() 호출
Graphics->RenderEnd()
→ 스왑체인 Present
RenderManager.h
#pragma once
#include "RenderHelper.h"
class RenderManager
{
public:
RenderManager(ComPtr<ID3D11Device> device, ComPtr<ID3D11DeviceContext> deviceContext);
void Init();
void Update(shared_ptr<Graphics> graphics);
private:
void PushCameraData();
void PushTransformData();
void PushAnimationData();
void GatherRenderableObjects();
void RenderObjects();
private:
ComPtr<ID3D11Device> _device;
ComPtr<ID3D11DeviceContext> _deviceContext;
shared_ptr<Pipeline> _pipeline;
private:
CameraData _cameraData;
shared_ptr<ConstantBuffer<CameraData>> _cameraBuffer;
TransformData _transformData;
shared_ptr<ConstantBuffer<TransformData>> _transformBuffer;
AnimationData _animationData;
shared_ptr<ConstantBuffer<AnimationData>> _animationBuffer;
private:
shared_ptr<RasterizerState> _rasterizerState;
shared_ptr<SamplerState> _samplerState;
shared_ptr<BlendState> _blendState;
vector<shared_ptr<GameObject>> _renderObjects;
};
RenderManager.cpp
#include "pch.h"
#include "RenderManager.h"
#include "Pipeline.h"
#include "MeshRenderer.h"
#include "Camera.h"
#include "Game.h"
#include "SceneManager.h"
#include "Scene.h"
#include "Mesh.h"
#include "Animator.h"
RenderManager::RenderManager(ComPtr<ID3D11Device> device, ComPtr<ID3D11DeviceContext> deviceContext)
:_device(device), _deviceContext(deviceContext)
{
}
void RenderManager::Init()
{
_pipeline = make_shared<Pipeline>(_deviceContext);
_transformBuffer = make_shared<ConstantBuffer<TransformData>>(_device, _deviceContext);
_transformBuffer->Create();
_cameraBuffer = make_shared<ConstantBuffer<CameraData>>(_device, _deviceContext);
_cameraBuffer->Create();
_animationBuffer = make_shared<ConstantBuffer<AnimationData>>(_device, _deviceContext);
_animationBuffer->Create();
_rasterizerState = make_shared<RasterizerState>(_device);
_rasterizerState->Create();
_blendState = make_shared<BlendState>(_device);
_blendState->Create();
_samplerState = make_shared<SamplerState>(_device);
_samplerState->Create();
}
void RenderManager::Update(shared_ptr<Graphics> graphics)
{
graphics->RenderBegin();
PushCameraData();
GatherRenderableObjects();
RenderObjects();
graphics->RenderEnd();
}
void RenderManager::PushCameraData()
{
_cameraData.matView = Camera::S_MatView;
_cameraData.matProjection = Camera::S_MatProjection;
_cameraBuffer->CopyData(_cameraData);
}
void RenderManager::PushTransformData()
{
_transformBuffer->CopyData(_transformData);
}
void RenderManager::PushAnimationData()
{
_animationBuffer->CopyData(_animationData);
}
void RenderManager::GatherRenderableObjects()
{
_renderObjects.clear();
auto& gameObjects = SCENE->GetActiveScene()->GetGameObjects();
for (const shared_ptr<GameObject>& gameObject : gameObjects)
{
shared_ptr<MeshRenderer> meshRenderer = gameObject->GetMeshRenderer();
if (meshRenderer)
{
_renderObjects.push_back(gameObject);
}
}
}
void RenderManager::RenderObjects()
{
for (const shared_ptr<GameObject>& gameObject : _renderObjects)
{
shared_ptr<MeshRenderer> meshRenderer = gameObject->GetMeshRenderer();
if (meshRenderer == nullptr)
continue;
shared_ptr<Transform> transform = gameObject->GetTransform();
if (transform == nullptr)
continue;
_transformData.matWorld = transform->GetWorldMatrix();
PushTransformData();
shared_ptr<Animator> animator = gameObject->GetAnimator();
if (animator)
{
const Keyframe& keyframe = animator->GetCurrentKeyframe();
_animationData.spriteOffset = keyframe.offset;
_animationData.spriteSize = keyframe.size;
_animationData.textureSize = animator->GetCurrentAnimation()->GetTextureSize();
_animationData.useAnimation = 1.f;
PushAnimationData();
_pipeline->SetConstantBuffer(2, SS_VertexShader, _animationBuffer);
_pipeline->SetTexture(0, SS_PixelShader, animator->GetCurrentAnimation()->GetTexture());
}
else
{
_animationData.spriteOffset = Vec2(0.f, 0.f);
_animationData.spriteSize = Vec2(0.f,0.f);
_animationData.textureSize = Vec2(0.f, 0.f);
_animationData.useAnimation = 0.f;
PushAnimationData();
_pipeline->SetConstantBuffer(2, SS_VertexShader, _animationBuffer);
_pipeline->SetTexture(0, SS_PixelShader, meshRenderer->GetTexture());
}
PipelineInfo info;
info.inputLayout = meshRenderer->GetInputLayout();
info.vertexShader = meshRenderer->GetVertexShader();
info.pixelShader = meshRenderer->GetPixelShader();
info.rasterizerState = _rasterizerState;
info.blendState = _blendState;
_pipeline->UpdatePipeline(info);
_pipeline->SetVertexBuffer(meshRenderer->GetMesh()->GetVertexBuffer());
_pipeline->SetIndexBuffer(meshRenderer->GetMesh()->GetIndexBuffer());
_pipeline->SetConstantBuffer(0, SS_VertexShader, _cameraBuffer);
_pipeline->SetConstantBuffer(1, SS_VertexShader, _transformBuffer);
_pipeline->SetSamplerState(0, SS_PixelShader, _samplerState);
_pipeline->DrawIndexed(meshRenderer->GetMesh()->GetIndexBuffer()->GetCount(), 0, 0);
}
}