1. 포트폴리오 영상
2. 로고 셰이더 효과
DirectX 시작 후 처음으로 적용한 효과입니다 !
해당 효과를 처리하기 위해 필요한 값으로는 '비율'이 필요했습니다.
if (input.vUV.x <= g_ratio)
{
float4 color = smoothstep(float4(0.f, 0.f, 0.f, 0.f), float4(1.f, 1.f, 1.f, 1.f),
(g_ratio - input.vUV.x) + 0.3f);
output.vTarget0 = g_DiffuseTex.Sample(g_DiffuseSmp, input.vUV) * color;
}
HLSL에서 제공되는 함수인 smoothstop() 함수를 사용했으며
uv.x 값에 제한을 걸어 좌측서부터 서서히 밝아지는 효과를 구현했습니다.
3. 데이터 파일(xml) 읽어오기 및 데이터 파일 첨부파일 추가
실제 게임에서 사용되는 데이터들을 xml 형태로 저장하여 게임 플레이에 읽어온 데이터 값을 적용시키는 작업 !
위 데이터 파일들이 이번 포트폴리오를 작업함에 있어서 사용되는 데이터 파일들이다.
파일을 읽어오는데 있어서 사용되는 외부 라이브러리(lib)인 'tinyxml2'를 사용하였다.
(tinyxml2 사용 방법은 별도로 설명하지 않겠다.)
void CTitleScene::RunResLoadThread()
{
m_pThread->Awake();
// .Xml 파일 읽기
// > 텍스처
m_pThread->SetLoadType(eLoadType::LT_TEXTURE);
string fileName = "../Bin/Data/TextureData.xml";
m_pThread->ReadXmlData(fileName, "Texture");
// > 사운드
m_pThread->SetLoadType(eLoadType::LT_SOUND);
fileName = "../Bin/Data/SoundData.xml";
m_pThread->ReadXmlData(fileName, "Sound");
// > 캐릭터
{
// 충돌체 크기
m_pThread->SetLoadType(eLoadType::LT_COLLISION);
fileName = "../Bin/Data/CharacterColliderSize.xml";
m_pThread->ReadXmlData(fileName, "Collider");
// 애니메이션 프레임별 시간
m_pThread->SetLoadType(eLoadType::LT_ANIFRAME);
fileName = "../Bin/Data/CharacterAniFrameData.xml";
m_pThread->ReadXmlData(fileName, "CharacterAniFrame");
}
}
위 코드는 xml 데이터 파일을 읽어오는 코드이며, 내부적으로 데이터를 저장하지만 데이터를 읽어오는 코드까지만 :)
4. 스레드(Thread)와 Command Pattern
이 부분에 대하여 글을 쓰기가 가장 까다롭다 !
읽어들인 데이터를 실제 스레드를 돌려서 각 데이터 매니저에 저장한다.
결과론적으로 먼저 얘기하면 "스레드에서 커맨드 패턴을 활용하여 데이터 저장" 방식을 사용하여 데이터를 저장
4-1. 스레드에서 데이터 파일 저장
말 그대로 단일 스레드를 만들어서 스레드에서 읽어들인 데이터를 저장한다.
이 방식에는 의도하지 않은 문제가 발생했는데 ... 정확하게 무슨 현상인지 용어를 알 수 없지만
스레드가 실행되는 중 다른 행동에 대하여 너무 버벅거림이 심하다는 문제가 발생했다.
이를 정확한 용어로 얘기할 수 없지만..(사실 잊어버렸다 ㅜㅜ..)
이 문제에 대하여 검색결과 '작업 큐(Queue)'를 이용하여 해당 문제를 해결할 수 있다고 한다.
4-2. 스레드에서 커맨드 패턴을 활용하여 데이터 저장
커맨드(Command)를 컨트롤할 수 있는 CommandControl 클래스 생성한다.
이후 Control 객체가 작업 큐를 통하여 처리해야 할 일을 가져와서 하나씩 처리하게 되는 방식이다.
- Command Control
→ Queue(작업 큐)
→ Texture Data[0] → 처리 -> Sound Data[0] → 처리 →
CollisionSize Data[0] → 처리 → Animation Frame Time Data[2] → 처리 끝 !
→ Texture Data[1] → 처리 -> Sound Data[1] → 처리 →
CollisionSize Data[1] → 처리 → Animation Frame Time Data[1] → 처리 끝 !
위와 같은 처리 방식으로 진행되며, 이를 풀어서 얘기하면 각 인덱스의 처리가 끝나면
다음 인덱스의 객체가 커맨드 작업 큐로 들어가며 이를 스레드에서 다시 처리하는 방식이다.
미흡하지만 아래 코드가 ResLoadThread 스레드 클래스에서 커맨드 패턴(Command Pattern)을 이용한 코드다 !
void CResLoadThread::execute()
{
if (m_pTitleSceneComp == nullptr)
{
return;
}
// CommandControl 클래스 멤버변수인 ResCommand*(m_pTextureCommand, m_pSoundCommand) 등록
// 해당 ResCommand* 객체로 ResCommand 클래스내 연결된 멤버 함수를 호출하여 실제 리소스를 로드한다.
static int textureIndex = 0;
static int soundIndex = 0;
static int collisionIndex = 0;
static int aniFrameIndex = 0;
// 텍스처 파일 로드
if (textureIndex < (int)m_vecTextureResCommand.size())
{
CResCommand* pTextureCommand = m_vecTextureResCommand[textureIndex++];
m_pCommandControl->SetTextureCommand(pTextureCommand);
bool isTextureLoad = m_pCommandControl->TextureFileLoad();
if (isTextureLoad == true)
{
m_resLoadCount++;
return;
}
else
{
tassert(true);
}
}
// 사운드 파일 로드
if (soundIndex < (int)m_vecSoundResCommand.size())
{
CResCommand* pSoundCommand = m_vecSoundResCommand[soundIndex++];
m_pCommandControl->SetSoundCommand(pSoundCommand);
bool isSoundLoad = m_pCommandControl->SoundFileLoad();
if (isSoundLoad == true)
{
m_resLoadCount++;
return;
}
else
{
tassert(true);
}
}
// 캐릭터 충돌체 파일 로드
if (collisionIndex < (int)m_vecPlayerCollision.size())
{
PPlayerCollisionSize pPlayerCollision = m_vecPlayerCollision[collisionIndex++];
if (m_pCommandControl->CollisionFileLoad(pPlayerCollision) == true)
{
m_resLoadCount++;
return;
}
}
// 캐릭터 애니메이션 프레임
if (aniFrameIndex < (int)m_vecPlayerAniFrame.size())
{
PAnimationFrameInfo pPlayerCollision = m_vecPlayerAniFrame[aniFrameIndex++];
if (m_pCommandControl->AnimFrameFileLoad(pPlayerCollision) == true)
{
m_resLoadCount++;
return;
}
}
}
로고 이미지 출처 : http://www.thisisgame.com/webzine/community/tboard/?n=243758&board=38