*** 공부 방법 ***
1. 코딩을 해야 하는 부분은 첫 부분에 변수나 함수, 메소드에 대한 선언이 코드블럭으로 표시되어 있다. //ex) MakeFunction(); 2. 코드블럭 하단에는 해당 선언에 대한 구현 로직이 작성되어 있다. 처
hyrule.tistory.com
- 텍스처 자원 관리를 효율적으로 하기 위해서, 씬에서도 텍스처 목록을 들고 있도록 한다.
-- 새 씬이 로드되면서 텍스처를 등록할 때 만약 기존 텍스처가 존재하면,
해당 텍스처의 주소만 받아오고 로드를 하지 않아도 된다. 등록되어있지 않은 텍스처만 새로 로드한다.
-- 새 씬의 로드가 완료되었으면, 기존 씬은 메모리에서 제거한다. 이 때, 새 씬에서 사용하지 않는 텍스처는 메모리에서 제거해 줌으로써 메모리를 효율적으로 관리할 수 있게 된다.
class CSceneResource
- Include/Scene 폴더에 소스파일을 저장한다.
- 씬의 하위 필터로 Resource를 만들고 이 필터 안에 놓는다.
- 오직 CScene에서만 접근할 수 있도록 허용하고, 나머지 접근은 다 틀어막는다.
- 나머지 코드는 CResourceManager의 기능과 동일하므로 해당 코드를 복사해서 수정한다.
//코드 수정, 변경
CRef::Release()
- 해당 메소드의 반환 타입을 void->int로 변경하고,
로직 수행 후 남아있는 Reference count를 반환하도록 해 준다.
CRef::GetRefCount()
- 현재 남아있는 Reference Count를 확인할 수 있는 메소드를 하나 생성한다.
- 바로 밑에서 사용할 예정
CTextureManager::ReleaseTexture()
- 이름(문자열)을 인자로 받아서, m_mapTexture에서 탐색한 후,
해당 CTexture이 존재하면 CRef::Release() 메소드를 호출한다.
- 해당 메소드는 CSceneResource에서 호출하기 위한 용도이다.
-- 씬이 전환될 때, 새 씬을 로드하고, 기존 씬을 제거하게 되면
기존 씬이 들고 있던 CSceneResource에서는 소멸자가 호출되고,
소멸자에서는 '사용하고 있던 텍스처 목록'을 순회하면서
해당 텍스처를 CTextureManager이 들고 있는 '텍스처 목록'에서 제거 요청을 보낸다.
- 그럼 제거 요청을 받은 CTextureManager에서는 해당 텍스처의 RefCount를 확인하고(GetRefCount() 메소드),
- 그럼 위 예시에서의 a, b와 같이 RefCount가 1만 남아있는 텍스처들을 제거하는 구조이다.
void CTextureManager::ReleaseTexture(const std::string& Name)
{
auto iter = m_mapTexture.find(Name);
if (iter == m_mapTexture.end())
return;
if (iter->second->GetRefCount() == 1)
m_mapTexture.erase(iter);
}
CSceneResource::FindTexture()
- CSceneResoruce가 들고 있는 m_mapTexture에서 CTexture를 찾아서 반환한다.
CTexture* CSceneResource::FindTexture(const std::string& Name)
{
auto iter = m_mapTexture.find(Name);
if (iter == m_mapTexture.end())
return nullptr;
return iter->second;
}
CSceneResource::LoadTexture()
CSceneResource::LoadTextureFullPath()
- 해당 메소드를 CTextureManager과 같이 만들어주어야 한다.
- 단일 텍스처를 넣을 때,
유니코드 문자 집합으로 여러 이미지를 한꺼번에 넣을 때,
멀티바이트 문자 집합으로 여러 이미지를 한꺼번에 넣을 떄 총 3가지 경우의 수를 생각하여 각각 만들어야 한다.
//SceneResource.cpp
//선언: private
bool CSceneResource::LoadTexture(const std::string& Name, const TCHAR* FileName,
const std::string& PathName)
{
if (FindTexture(Name))
return false;
if (!CResourceManager::GetInst()->LoadTexture(Name, FileName, PathName))
return false;
CTexture* Texture = CResourceManager::GetInst()->FindTexture(Name);
m_mapTexture.insert(std::make_pair(Name, Texture));
return true;
}
bool CSceneResource::LoadTextureFullPath(const std::string& Name,
const TCHAR* FullPath)
{
if (FindTexture(Name))
return false;
if (!CResourceManager::GetInst()->LoadTextureFullPath(Name, FullPath))
return false;
CTexture* Texture = CResourceManager::GetInst()->FindTexture(Name);
m_mapTexture.insert(std::make_pair(Name, Texture));
return true;
}
#ifdef UNICODE
bool CSceneResource::LoadTexture(const std::string& Name,
const std::vector<std::wstring>& vecFileName, const std::string& PathName)
{
if (FindTexture(Name))
return false;
if (!CResourceManager::GetInst()->LoadTexture(Name, vecFileName, PathName))
return false;
CTexture* Texture = CResourceManager::GetInst()->FindTexture(Name);
m_mapTexture.insert(std::make_pair(Name, Texture));
return true;
}
bool CSceneResource::LoadTextureFullPath(const std::string& Name,
const std::vector<std::wstring>& vecFullPath)
{
if (FindTexture(Name))
return false;
if (!CResourceManager::GetInst()->LoadTextureFullPath(Name, vecFullPath))
return false;
CTexture* Texture = CResourceManager::GetInst()->FindTexture(Name);
m_mapTexture.insert(std::make_pair(Name, Texture));
return true;
}
#else
bool CSceneResource::LoadTexture(const std::string& Name,
const std::vector<std::string>& vecFileName, const std::string& PathName)
{
if (FindTexture(Name))
return false;
if (!CResourceManager::GetInst()->LoadTexture(Name, vecFileName, PathName))
return false;
CTexture* Texture = CResourceManager::GetInst()->FindTexture(Name);
m_mapTexture.insert(std::make_pair(Name, Texture));
return true;
}
bool CSceneResource::LoadTextureFullPath(const std::string& Name,
const std::vector<std::string>& vecFullPath)
{
if (FindTexture(Name))
return false;
if (!CResourceManager::GetInst()->LoadTextureFullPath(Name, vecFullPath))
return false;
CTexture* Texture = CResourceManager::GetInst()->FindTexture(Name);
m_mapTexture.insert(std::make_pair(Name, Texture));
return true;
}
#endif
- 이제 CScene에서는 이 CSceneResource를 동적 할당하고, 주소를 들고 있게 해준다.(삭제 필수!!)
- 필요할 때 해당 CSceneResource의 주소를 얻어올 수 있는 GetSceneResource도 만들어준다.
//Scene.h
class CSceneResource* GetSceneResource() const
{
return m_Resource;
}
//Scene.cpp
CScene::CScene()
{
m_Resource = new CSceneResource;
}
CScene::~CScene()
{
//...기존코드...//
SAFE_DELETE(m_Resource);
}
CGameObject::SetTexture()
CGameObject::SetTextureFullPath()
- 기존의 CGameObject::SetTexture() 메소드도 분할해서 여러가지 방법으로 생성할 수 있는 루트를 만들어준다.
1. 기존에 존재하는 텍스처를 이름을 통해 주소를 받아옴
2. 아예 텍스처 주소를 받아서 등록
3. 이름과 텍스처 파일명, 텍스처 파일이 있는 주소를 받아 LoadTexture() 메소드를 통해 아예 로드
4. 이름과 텍스처 파일의 완벽한 주소(FullPath)를 받아 LoadTextureFullPath() 메소드를 통해 로드
-> 모든 과정은 각각 로드 과정이 끝나면 m_Texture 변수에 FindTexture() 메소드를 통해 텍스처 주소를 받아놓아준다.
--> 이렇게 해주면 혹시나 이미 등록된 텍스처가 있어서 로드를 하지 않았더라도 기존 존재하는 텍스처 주소를 받아올 수가 있다.
* 물론 여기도 #ifdef를 활용한 예외 처리를 해주어야 한다.
- 이제 텍스처 로딩이 더 쉬워졌다.
- 텍스처를 쓰고자 하는 CGameObject에서 필요한 때에 CGameObject::SetTexture() 메소드를 로드해주기만 하면 되기 때문이다.
bool CMonster::Init(CGameObject* Obj)
{
CCharacter::Init(Obj);
SetTexture("Monster", TEXT("pepe.bmp"));
//...이외의 코드...//
}
- 이제는 딱 한 줄만 등록해 놓는 것으로
'WIN32API FrameWork > 한단계씩 직접 구현' 카테고리의 다른 글
36. 이미지의 투명 처리 (0) | 2022.05.25 |
---|---|
35. 더블 버퍼링 (0) | 2022.05.25 |
33. 이미지의 애니메이션화를 위한 준비 (0) | 2022.05.25 |
32. 이미지 등의 리소스 관리자 (0) | 2022.05.24 |
31. 이미지 로딩을 위한 준비 - 경로 관리자 (0) | 2022.05.24 |