오늘은 기존에 사용하던 RenderManager 코드를 수정해주자.

지금은 쉐이더가 달라지면 기존에 있던 부분이 날라가는 문제점이 있다. 이 문제를 해결해주기 위하여 코드를 공용으로

모아두고 필요한 부분만 사용하지만 그것을 물체마다 할 수 있게 만들어주면 된다.

그렇게 하기위하여 쉐이더 클래스에 이 부분 코드를 넣어주고 데이터를 밀어넣는 부분에 만약에 버퍼가 없다면 버퍼를 

생성하고초기화하는 부분도 같이 넣어주자.

Shader.h

#pragma once
#include "Pass.h"
#include "Technique.h"
#include "BindShaderDesc.h"

class Shader
{

public:

	void PushGlobalData(const Matrix& view, const Matrix& projection);
	void PushTransformData(const TransformDesc& desc);
	void PushLightData(const LightDesc& desc);
	void PushMaterialData(const MaterialDesc& desc);
	void PushBoneData(const BoneDesc& desc);
	void PushKeyframeData(const KeyframeDesc& desc);
	void PushTweenData(const InstancedTweenDesc& desc);

private:
	//프레임마다 한번만 세팅
	GlobalDesc _globalDesc;
	shared_ptr<ConstantBuffer<GlobalDesc>> _globalBuffer;
	//정보넘겨주기
	ComPtr<ID3DX11EffectConstantBuffer> _globalEffectBuffer;


	TransformDesc _transformDesc;
	shared_ptr<ConstantBuffer<TransformDesc>> _transformBuffer;
	//정보넘겨주기
	ComPtr<ID3DX11EffectConstantBuffer> _transformEffectBuffer;

	LightDesc _lightDesc;
	shared_ptr<ConstantBuffer<LightDesc>> _lightBuffer;
	ComPtr<ID3DX11EffectConstantBuffer> _lightEffectBuffer;

	MaterialDesc _materialDesc;
	shared_ptr<ConstantBuffer<MaterialDesc>> _materialBuffer;
	ComPtr<ID3DX11EffectConstantBuffer> _materialEffectBuffer;

	BoneDesc _boneDesc;
	shared_ptr<ConstantBuffer<BoneDesc>> _boneBuffer;
	ComPtr<ID3DX11EffectConstantBuffer> _boneEffectBuffer;

	KeyframeDesc _keyframeDesc;
	shared_ptr<ConstantBuffer<KeyframeDesc>> _keyframeBuffer;
	ComPtr<ID3DX11EffectConstantBuffer> _keyframeEffectBuffer;

	InstancedTweenDesc _tweenDesc;
	shared_ptr<ConstantBuffer<InstancedTweenDesc>> _tweenBuffer;
	ComPtr<ID3DX11EffectConstantBuffer> _tweenEffectBuffer;

};

Shader.cpp

void Shader::PushGlobalData(const Matrix& view, const Matrix& projection)
{
	if (_globalEffectBuffer == nullptr)
	{
		_globalBuffer = make_shared<ConstantBuffer<GlobalDesc>>();
		_globalBuffer->Create();
		_globalEffectBuffer = GetConstantBuffer("GlobalBuffer");
	}

	_globalDesc.V = view;
	_globalDesc.P = projection;
	_globalDesc.VP = view * projection;
	_globalDesc.VInv = view.Invert();
	_globalBuffer->CopyData(_globalDesc);
	_globalEffectBuffer->SetConstantBuffer(_globalBuffer->GetComPtr().Get());
}

void Shader::PushTransformData(const TransformDesc& desc)
{
	if (_transformEffectBuffer == nullptr)
	{
		_transformBuffer = make_shared<ConstantBuffer<TransformDesc>>();
		_transformBuffer->Create();
		_transformEffectBuffer = GetConstantBuffer("TransformBuffer");
	}

	_transformDesc = desc;
	_transformBuffer->CopyData(_transformDesc);
	_transformEffectBuffer->SetConstantBuffer(_transformBuffer->GetComPtr().Get());
}

void Shader::PushLightData(const LightDesc& desc)
{
	if (_lightEffectBuffer == nullptr)
	{
		_lightBuffer = make_shared<ConstantBuffer<LightDesc>>();
		_lightBuffer->Create();
		_lightEffectBuffer = GetConstantBuffer("LightBuffer");
	}

	_lightDesc = desc;
	_lightBuffer->CopyData(_lightDesc);
	_lightEffectBuffer->SetConstantBuffer(_lightBuffer->GetComPtr().Get());
}

void Shader::PushMaterialData(const MaterialDesc& desc)
{
	if (_materialEffectBuffer == nullptr)
	{
		_materialBuffer = make_shared<ConstantBuffer<MaterialDesc>>();
		_materialBuffer->Create();
		_materialEffectBuffer = GetConstantBuffer("MaterialBuffer");
	}

	_materialDesc = desc;
	_materialBuffer->CopyData(_materialDesc);
	_materialEffectBuffer->SetConstantBuffer(_materialBuffer->GetComPtr().Get());
}

void Shader::PushBoneData(const BoneDesc& desc)
{
	if (_boneEffectBuffer == nullptr)
	{
		_boneBuffer = make_shared<ConstantBuffer<BoneDesc>>();
		_boneBuffer->Create();
		_boneEffectBuffer = GetConstantBuffer("BoneBuffer");
	}

	_boneDesc = desc;
	_boneBuffer->CopyData(_boneDesc);
	_boneEffectBuffer->SetConstantBuffer(_boneBuffer->GetComPtr().Get());
}

void Shader::PushKeyframeData(const KeyframeDesc& desc)
{
	if (_keyframeEffectBuffer == nullptr)
	{
		_keyframeBuffer = make_shared<ConstantBuffer<KeyframeDesc>>();
		_keyframeBuffer->Create();
		_keyframeEffectBuffer = GetConstantBuffer("KeyframeBuffer");
	}

	_keyframeDesc = desc;
	_keyframeBuffer->CopyData(_keyframeDesc);
	_keyframeEffectBuffer->SetConstantBuffer(_keyframeBuffer->GetComPtr().Get());
}

void Shader::PushTweenData(const InstancedTweenDesc& desc)
{
	if (_transformEffectBuffer == nullptr)
	{
		_tweenBuffer = make_shared<ConstantBuffer<InstancedTweenDesc>>();
		_tweenBuffer->Create();
		_tweenEffectBuffer = GetConstantBuffer("TweenBuffer");
	}

	_tweenDesc = desc;
	_tweenBuffer->CopyData(_tweenDesc);
	_tweenEffectBuffer->SetConstantBuffer(_tweenBuffer->GetComPtr().Get());
}

이렇게 수정해주고 RenderManager는 필요한 구조체만 남기고 없애주자. 그리고 이름을 BindShaderDesc로 바꿔주자. 그리고 RenderManager가 없어진부분을 이제 shader쪽에서 가져오거나 주석처리를 해주도록하자. 

BindShaderDesc.h

#pragma once
#include "ConstantBuffer.h"

class Shader;

struct GlobalDesc
{
	Matrix V = Matrix::Identity;
	Matrix P = Matrix::Identity;
	Matrix VP = Matrix::Identity;
	Matrix VInv = Matrix::Identity;
};

struct TransformDesc
{
	Matrix W = Matrix::Identity;
};

//Light
struct LightDesc
{
	Color ambient = Color(1.f, 1.f, 1.f, 1.f);
	Color diffuse = Color(1.f, 1.f, 1.f, 1.f);
	Color specular = Color(1.f, 1.f, 1.f, 1.f);
	Color emissive = Color(1.f, 1.f, 1.f, 1.f);

	Vec3 direction;
	float padding0;
};

struct MaterialDesc
{
	Color ambient = Color(0.f, 0.f, 0.f, 1.f);
	Color diffuse = Color(1.f, 1.f, 1.f, 1.f);
	Color specular = Color(0.f, 0.f, 0.f, 1.f);
	Color emissive = Color(0.f, 0.f, 0.f, 1.f);
};


//Bone 개수
#define MAX_MODEL_TRANSFORMS 250
#define MAX_MODEL_KEYFRAMES 500
#define MAX_MODEL_INSTANCE 500

struct BoneDesc
{
	Matrix transforms[MAX_MODEL_TRANSFORMS];
};

//Animation
struct KeyframeDesc
{
	int32 animIndex = 0;
	uint32 currFrame = 0;
	uint32 nextFrame = 0;
	float ratio = 0.f;
	float sumTime = 0.f;
	float speed = 1.f;
	Vec2 padding;
};

struct TweenDesc
{
	TweenDesc()
	{
		curr.animIndex = 0;
		next.animIndex = -1;
	}

	void ClearNextAnim()
	{
		next.animIndex = -1;
		next.currFrame = 0;
		next.nextFrame = 0;
		next.sumTime = 0;
		tweenSumTime = 0;
		tweenRatio = 0;
	}

	float tweenDuration = 1.0f;
	float tweenRatio = 0.f;
	float tweenSumTime = 0.f;
	float padding = 0.f;
	KeyframeDesc curr;
	KeyframeDesc next;
};

struct InstancedTweenDesc
{
	TweenDesc tweens[MAX_MODEL_INSTANCE];
};

이렇게 바꿔주고 주석처리해준 Light와 Camera부분은 따로 관리주어야하는데 이 부분은 Scene쪽에서 관리해주도록 

하자. RenderInstancing 부분이 있는 매쉬, 모델, 모델애니메이터에서  빛과 카메라 부분을 업데이트해주도록 하자. 일단 카메라와 빛의 개수 하나라고 가정하자. 이것은 나중에 직교투영하는 UI카메라를 구현할 때는 고쳐주어야 한다. 

Scene.h

#pragma once


class Scene
{
public:
	virtual void Start();
	virtual void Update();
	virtual void LateUpdate();
	
	//추가
	virtual void Add(shared_ptr<GameObject> object);
	//제거
	virtual void Remove(shared_ptr<GameObject> object);

	
	unordered_set<shared_ptr<GameObject>> GetObjects() { return _objects; }
	//일단 하나라고 가정하고 제일 처음꺼 가져오기
	shared_ptr<GameObject> GetCamera() { return _cameras.empty() ? nullptr : *_cameras.begin(); }
	shared_ptr<GameObject> GetLight() { return _lights.empty() ? nullptr : *_lights.begin(); }

private:
	//물체를 가지고있는 추가 삭제 편하지만 순회에는 안좋다 검색활용
	unordered_set<shared_ptr<GameObject>> _objects;
	//카메라
	unordered_set<shared_ptr<GameObject>> _cameras;
	//빛
	unordered_set<shared_ptr<GameObject>> _lights;
};

ModelRenderer.cpp

void ModelRenderer::RenderInstancing(shared_ptr<class InstancingBuffer>& buffer)
{
	if (_model == nullptr)
		return;

	// GlobalData
	_shader->PushGlobalData(Camera::S_MatView, Camera::S_MatProjection);

	// Light
	auto lightObj = SCENE->GetCurrentScene()->GetLight();
	if (lightObj)
		_shader->PushLightData(lightObj->GetLight()->GetLightDesc());

	//Bones -> shader
	BoneDesc boneDesc;

	const uint32 boneCount = _model->GetBoneCount();

	for (uint32 i = 0; i < boneCount; i++)
	{
		shared_ptr<ModelBone> bone = _model->GetBoneByIndex(i);
		boneDesc.transforms[i] = bone->transform;
	}
	_shader->PushBoneData(boneDesc);

	//부품
	const auto& meshes = _model->GetMeshes();
	for (auto& mesh : meshes)
	{
		if (mesh->material)
			mesh->material->Update();

		//BoneIndex
		_shader->GetScalar("BoneIndex")->SetInt(mesh->boneIndex);

		//IA
		mesh->vertexBuffer->PushData();
		mesh->indexBuffer->PushData();

		//World position 넣어주기
		buffer->PushData();

		_shader->DrawIndexedInstanced(0, _pass, mesh->indexBuffer->GetCount(), buffer->GetCount());

	}
}

고쳐준 다음 컴파일해주고 Client부분에 오류가 나는 부분을 수정해주자.

이렇게해주면 이제 다시 정상적으로 작동하는 것을 볼 수 있다. 

 

이제 이렇게 해주는 것으로 우리가 여러가지 쉐이더를 사용할 수 있게 되었다.

+ Recent posts