[DX] RenderManager

vector·2025년 11월 17일

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:	
	// Camera
	CameraData _cameraData;
	shared_ptr<ConstantBuffer<CameraData>> _cameraBuffer;

	// SRT
	TransformData _transformData;
	shared_ptr<ConstantBuffer<TransformData>> _transformBuffer;

	// Animation
	AnimationData _animationData;
	shared_ptr<ConstantBuffer<AnimationData>> _animationBuffer;

private:
	shared_ptr<RasterizerState> _rasterizerState;	// RAS
	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);

	// ConstantBuffer 생성 (World)
	_transformBuffer = make_shared<ConstantBuffer<TransformData>>(_device, _deviceContext);
	_transformBuffer->Create();

	// ConstantBuffer 생성 (Camera)
	_cameraBuffer = make_shared<ConstantBuffer<CameraData>>(_device, _deviceContext);
	_cameraBuffer->Create();

	// ConstantBuffer 생성 (Animation)
	_animationBuffer = make_shared<ConstantBuffer<AnimationData>>(_device, _deviceContext);
	_animationBuffer->Create();



	// RasterizerState 생성
	_rasterizerState = make_shared<RasterizerState>(_device);
	_rasterizerState->Create();
	// BlendState 생성
	_blendState = make_shared<BlendState>(_device);
	_blendState->Create();
	// SamplerState 생성
	_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);
	// 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;

		// SRT
		_transformData.matWorld = transform->GetWorldMatrix();
		PushTransformData();
		// 현재는 버퍼를 한개만 사용하기에 복사하고 넘어가는 부분에서 시간이 조금 걸리는 게 비효율적이지만
		// DX12에서는 이걸 더 효율적으로 만들기 위한 기능들이 있다.


		// Animation
		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);

		// IA
		_pipeline->SetVertexBuffer(meshRenderer->GetMesh()->GetVertexBuffer());
		_pipeline->SetIndexBuffer(meshRenderer->GetMesh()->GetIndexBuffer());
		// VS
		_pipeline->SetConstantBuffer(0, SS_VertexShader, _cameraBuffer);
		_pipeline->SetConstantBuffer(1, SS_VertexShader, _transformBuffer);
		//_pipeline->SetTexture(0, SS_PixelShader, meshRenderer->GetTexture());
		_pipeline->SetSamplerState(0, SS_PixelShader, _samplerState);
		_pipeline->DrawIndexed(meshRenderer->GetMesh()->GetIndexBuffer()->GetCount(), 0, 0);
	}
}
profile
게임 클라이언트 프로그래머 준비중 (공부 및 기록용)

0개의 댓글