36. 이미지의 투명 처리
*** 공부 방법 ***
1. 코딩을 해야 하는 부분은 첫 부분에 변수나 함수, 메소드에 대한 선언이 코드블럭으로 표시되어 있다. //ex) MakeFunction(); 2. 코드블럭 하단에는 해당 선언에 대한 구현 로직이 작성되어 있다. 처
hyrule.tistory.com
- 애니메이션을 잘 보면, 텍스처가 그려지는 사각형 부분이 아예 덮히는 것을 확인할 수 있다.
그리고 싶은 부분(테두리) 바깥은 투명하게 처리해야되는 게 맞지 않을까?
- .bmp 이미지 파일은 투명 데이터를 가지고 있지 않지만, 우리는 '특정 색깔을 정해서' 그 색을 출력하지 않을 수 있다.
-- 이를 '컬러 키' 방식이라고 한다.
CF) 이외에도 투명을 처리하는 방식은 '블렌딩' 방식이 존재한다.
- 일단 출력되지 않을 색깔을 정해야 하는데, 일반적으로 '마젠타(R255 G0 B255)' 색상이 많이 쓰이는 편이다. 색상이 쨍해서 잘 쓰이지 않는 색상이기 때문이다.
- 그림판에서 양동이 툴로 사용하지 않는 부분에 마젠타 색상을 부어놓자.
[사전 지식]
COLORREF ColorKey = RGB(255, 0, 255);
- COLORREF: unsigned int 타입
- RGB(R, G, B): RGB값을 지정해주는 매크로
TransparentBlt(hDC, (int)RenderLT.x, (int)RenderLT.y,
(int)m_Size.x, (int)m_Size.y, m_Texture->GetDC(),
0, 0, (int)m_Size.x, (int)m_Size.y, m_Texture->GetColorKey());
1번: HDC
2,3번: 그릴 위치
4,5번: 그릴 사이즈
6,7번: 메모리 DC
8,9번: 이미지에서 뽑아올 시작점 -> 스프라이트에서 사용함. 지금은 스프라이트가 아니므로 0, 0
10, 11번: 이미지에서 뽑아올 시작점으로부터 얼마 만큼 그릴것인지
12번: 컬러키 지정
- 사용하지 않을 색상을 정했으면, ImageInfo 구조체도 해당 색상을 표시하지 않기 위해 RGB값을 들고 있어야 한다.
- 해당 변수를 구조체에 추가한다.
-- EnableColorKey: 컬러키를 사용할지 말지 여부를 bool타입으로 저장하는 변수. 기본값 false
-- ColorKey: 컬러키 색을 저장하는 COLORREF 변수. 기본값 마젠타
struct ImageInfo
{
HDC hMemDC;
HBITMAP hBmp;
HBITMAP hPrevBmp;
BITMAP BmpInfo;
COLORREF ColorKey;
bool ColorKeyEnable;
ImageInfo() :
hMemDC(0),
hBmp(0),
hPrevBmp(0),
BmpInfo{},
ColorKey(RGB(255, 0, 255)),
ColorKeyEnable(false)
{
}
~ImageInfo()
{
// 도구를 원래대로 돌려준다.
SelectObject(hMemDC, hPrevBmp);
DeleteObject(hBmp);
DeleteDC(hMemDC);
}
};
<CTexture::SetColorKey()>
- 컬러 키를 지정해주는 메소드.
- R, G, B 값을 unsigned char로 받고, vector의 인덱스를 int로 받는다.
-- R = 255, G = 0, B = 255, index = -1로 기본값을 지정해 준다.
-- -1 이외의 숫자가 들어오면 해당 인덱스의 ImageInfo만 설정해준다.
<CTexture::GetColorKey()>
- 인덱스를 인자로 전달하여 컬러키값을 얻어온다. 기본값 0(애니메이션 없이 파일 하나일 떄 자동으로 출력되도록)
<CTexture::GetEnableColorKey()>
- 인덱스를 인자로 전달하여 컬러키 기능 활성화 여부를 얻어온다. 기본값 0
** GetDC() 메소드도 기본값을 0으로 해준다. 지난번에 기본값을 주지 않았었음.
- 이 메소드들을 CTextureManager, CResourceManager, CSceneResource, CGameObject에서도 쓸 수 있게 해준다.
-- CGameObject -> CSceneResource -> CResourceManager -> CTextureManager -> CTexture
//Texture.h
public:
HDC GetDC(int index = 0) const
{
return m_vecImageInfo[index]->hMemDC;
}
void SetColorKey(unsigned char r = 255,
unsigned char g = 0,
unsigned char b = 255,
int index = -1);
COLORREF GetColorKey(int index = 0) const
{
return m_vecImageInfo[index]->ColorKey;
}
bool GetColorKeyEnable(int index = 0) const
{
return m_vecImageInfo[index]->ColorKeyEnable;
}
//Texture.cpp
void CTexture::SetColorKey(unsigned char r, unsigned char g, unsigned char b, int index)
{
if (index != -1)
{
m_vecImageInfo[index]->ColorKey = RGB(r, g, b);
m_vecImageInfo[index]->ColorKeyEnable = true;
}
else
{
size_t size = m_vecImageInfo.size();
for (size_t i = 0; i < size; ++i)
{
m_vecImageInfo[i]->ColorKey = RGB(r, g, b);
m_vecImageInfo[i]->ColorKeyEnable = true;
}
}
}
- 그럼 이제 CGameObject에서 SetTexture() 메소드를 통해 텍스처를 설정하고 나서
SetColorKey() 메소드를 호출하면 컬러키를 사용하도록 설정된다.
bool CMonster::Init(CGameObject* Obj)
{
SetTexture("Monster", TEXT("pepe.bmp"));
//인자를 넣지 않으면, 자동으로 마젠타 색상으로 컬러키를 설정한다.
//애니메이션일 경우, 모든 애니메이션 프레임에 대해 마젠타 색상을 컬러키로 지정해준다.
SetColorKey();
//...
//오브젝트의 사이즈와 이미지의 사이즈를 일치시켜 주자.
SetSize(150.f, 133.f);