RenderManager는 Init 시점에 특정 쉐이더와 관련된 ConstantBuffer를 초기화해. 그런데 쉐이더가 바뀌면 이전 상태가 날아가버려. 즉, 여러 개의 쉐이더를 동시에 쓰는 상황에 적합하지 않았어.
LightDesc, MaterialDesc 같은 정보는 오브젝트마다 다를 수 있어. 그런데 RenderManager는 이걸 전역으로 들고 있다 보니, 각기 다른 데이터를 사용하는 오브젝트에 대해 정확한 처리가 어려워졌지.
모든 ConstantBuffer들을 Shader 내부로 옮긴다. 즉, 각 Shader가 자신이 필요로 하는 버퍼만 관리하고, 필요할 때만 생성해서 사용하는 방식으로 변경하는 거야.
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());
}
BindShaderDesc.h로 변경하고, 구조체 정의만 남긴다.RenderManager가 전역 상태를 관리하는 유틸처럼 되어 있었기 때문에, 각 객체나 쉐이더가 개별적으로 관리하도록 책임 분리를 해준 거야.
Shader에 데이터를 밀어넣는 주체가 분산되다 보니, 카메라나 라이트처럼 전역에서 사용되는 요소를 어디서든 접근 가능하게 만들 필요가 있었지.
Scene 클래스에 다음 함수 추가:
unordered_set<shared_ptr<GameObject>> GetObjects();
shared_ptr<GameObject> GetCamera();
shared_ptr<GameObject> GetLight();
// GlobalData
_shader->PushGlobalData(Camera::S_MatView, Camera::S_MatProjection);
// LightData
auto lightObj = SCENE->GetCurrentScene()->GetLight();
if (lightObj)
_shader->PushLightData(lightObj->GetLight()->GetLightDesc());
이제 Shader에 직접 데이터를 전달하고, 필요한 버퍼가 없다면 Shader가 알아서 만든다.
| 이전 구조 | 개선 구조 |
|---|---|
| RenderManager가 모든 Shader 상태 관리 | 각 Shader가 자신 상태 독립적으로 관리 |
| 전역 공유 → 충돌 가능성 | Shader 별 개별 관리 → 충돌 없음 |
| 항상 모든 버퍼 생성 | 필요한 시점에만 생성 (캐시 방식) |
| 구조체, 로직이 혼재 | Shader, Desc 명확하게 분리됨 |
| 확장성 부족 | 다양한 Shader 자유롭게 사용 가능 |