- Alpha blend 사용.
// CPlayer.cpp
...
void CPlayer::render(HDC hDC)
{
// 컴포넌트 렌더링 호출.
// component_render(hDC);
CTexture* pTexture = CResourceMgr::GetInstance()->
LoadTexture(L"Player", L"texture\\Player.bmp");
if (pTexture)
{
Vector2 pos = CCamera::GetInstance()->WorldToScreen(GetPos());
float width = static_cast<float>(pTexture->GetWidth());
float height = static_cast<float>(pTexture->GetHeight());
BLENDFUNCTION bf = {};
bf.BlendOp = AC_SRC_OVER;
bf.SourceConstantAlpha = 127; // 0 ~ 255
bf.AlphaFormat = AC_SRC_ALPHA;
bf.BlendFlags = 0;
AlphaBlend(hDC,
static_cast<int>(pos.x - width / 2.f),
static_cast<int>(pos.y - height / 2.f),
static_cast<int>(width),
static_cast<int>(height),
pTexture->GetDC(),
0,
0,
static_cast<int>(width),
static_cast<int>(height),
bf);
}
}
테스트로 사용해보기 위해 기존 component_render 를 주석 처리.
AlphaBlend 함수를 통해 기존 렌더링에서 투명도를 적용할 수 있음.
// define.h
...
enum class GROUP_TYPE
{
DEFAULT,
TILE,
MONSTER,
PLAYER,
...
역시 테스트를 위해 잠깐 렌더링 순서를 변경해주고 실행해보면

간단하게 50% 투명 처리된 이미지를 확인 가능함.
그림판으로 만든 이미지라 배경의 흰색도 alpah 값이 1 이라 조금 이상하게 나오긴 하지만...
- Back buffer 수정.
// CCore.h
...
class CCore
{
SINGLETON(CCore)
private:
HWND m_hWnd; // 메인 윈도우 핸들.
POINT m_ptResolution; // 화면 해상도.
HDC m_hDC; // 디바이스 컨텍스트 핸들.
//HBITMAP m_hBitBack; // Back Buffer
//HDC m_hDCBack; // Back Buffer용 DC
CTexture* m_pTexBackBuffer; // Back Buffer용 텍스쳐.
기존에 back buffer 용 멤버 변수들을 Texture 객체 하나로 관리하도록 수정.
// CCore.cpp
...
int CCore::init(HWND _hWnd, POINT _ptResolution)
{
...
//m_hBitBack = CreateCompatibleBitmap(m_hDC, m_ptResolution.x, m_ptResolution.y);
//m_hDCBack = CreateCompatibleDC(m_hDC);
//HBITMAP hDefaultBit = (HBITMAP)SelectObject(m_hDCBack, m_hBitBack);
//DeleteObject(hDefaultBit);
// 이중 버퍼링을 위한 Back Buffer 생성.
m_pTexBackBuffer = CResourceMgr::GetInstance()->CreateTexture(
L"BackBuffer", m_ptResolution.x, m_ptResolution.y);
...
void CCore::render()
{
// 이전 화면 지우기
HDC hDCBack = m_pTexBackBuffer->GetDC();
Rectangle(hDCBack
, -1, -1, m_ptResolution.x + 1, m_ptResolution.y + 1);
//Rectangle(m_hDCBack, -1, -1, m_ptResolution.x + 1, m_ptResolution.y + 1);
CSceneMgr::GetInstance()->render(hDCBack);
BitBlt(m_hDC,
0, 0, m_ptResolution.x, m_ptResolution.y,
hDCBack,
0, 0,
SRCCOPY);
...
기존에 HBITMAP, HDC 두 개를 Texture 클래스에서 다 가지고 있으므로 대체 가능함.
// CTexture.cpp
...
void CTexture::Create(UINT _iWidth, UINT _iHeight)
{
m_hBitmap = (HBITMAP)CreateCompatibleBitmap(
CCore::GetInstance()->GetMainDC(), _iWidth, _iHeight);
assert(m_hBitmap && "CTexture::Create : CreateCompatibleBitmap Failed");
m_hDC = CreateCompatibleDC(CCore::GetInstance()->GetMainDC());
HBITMAP hPrevBit = (HBITMAP)SelectObject(m_hDC, m_hBitmap);
DeleteObject(hPrevBit);
GetObject(m_hBitmap, sizeof(BITMAP), &m_tBitInfo);
}
// CResourceMgr.cpp
...
CTexture* CResourceMgr::CreateTexture(const wstring& _strKey, UINT _iWidth, UINT _iHeight)
{
map<wstring, CResource*>::iterator iter = m_mapResources.find(_strKey);
if (iter != m_mapResources.end())
{
return dynamic_cast<CTexture*>(iter->second);
}
CTexture* pTexture = new CTexture();
pTexture->SetKey(_strKey);
pTexture->SetRelativePath(L"");
pTexture->Create(_iWidth, _iHeight);
m_mapResources.insert(make_pair(_strKey, pTexture));
return pTexture;
}
Texture 와 Resouce Manager 클래스에도 Create 관련된 함수를 만들어줌. 기존의 Load~ 함수 체계와 유사하다.
단지 실제 파일이 아니라 임의로 만든 것이므로 path 값도 없음.
- Fade 효과 구현.
// CCamera.h
...
enum class CAM_EFFECT
{
NONE,
FADE_IN,
FADE_OUT,
END
};
class CCamera
{
SINGLETON(CCamera)
private:
...
CAM_EFFECT m_eEffect; // 카메라 효과.
CTexture* m_pVeilTex; // 화면을 덮는 베일 텍스쳐.
float m_fEffectDuration; // 효과 지속 시간.
float m_fEffectTimeAcc; // 효과 시간 누적.
public:
...
inline void FadeIn(float duration)
{
assert(duration > 0.f);
m_eEffect = CAM_EFFECT::FADE_IN;
m_fEffectDuration = duration;
m_fEffectTimeAcc = 0.f;
}
inline void FadeOut(float duration)
{
assert(duration > 0.f);
m_eEffect = CAM_EFFECT::FADE_OUT;
m_fEffectDuration = duration;
m_fEffectTimeAcc = 0.f;
}
public:
void init();
void update();
void render(HDC hDC);
};
간단하다. 입력된 시간만큼 Fade 효과를 넣어줌. 이를 위해 카메라도 Texture 를 가지게 해줌.
// CCamera.cpp
...
void CCamera::init()
{
POINT resolution = CCore::GetInstance()->GetResolution();
m_pVeilTex = CResourceMgr::GetInstance()->CreateTexture(
L"CameraVeil", resolution.x, resolution.y);
SetPosition(Vector2(resolution.x / 2.0f, resolution.y / 2.0f));
}
먼저 init 함수에서 해상도를 입력받고 빈 텍스쳐를
Resource Manager 의 CreateTexture 함수를 통해 만들어준다. Core 의 back buffer 용 텍스쳐처럼 크기 정보만 있는 빈 껍데기 비트맵 텍스쳐가 만들어짐.
// CCamera.cpp
...
void CCamera::render(HDC hDC)
{
m_fEffectTimeAcc += DELTATIMEF;
if (m_fEffectTimeAcc > m_fEffectDuration)
m_fEffectTimeAcc = m_fEffectDuration;
float alphaRatio = m_fEffectTimeAcc / m_fEffectDuration;
BLENDFUNCTION func = {};
func.BlendOp = AC_SRC_OVER;
func.BlendFlags = 0;
func.AlphaFormat = 0;
switch (m_eEffect)
{
case CAM_EFFECT::NONE:
break;
case CAM_EFFECT::FADE_IN:
alphaRatio = 1.f - alphaRatio;
break;
case CAM_EFFECT::FADE_OUT:
case CAM_EFFECT::END:
default:
break;
}
func.SourceConstantAlpha = static_cast<BYTE>(255.f * alphaRatio);
AlphaBlend(hDC, 0, 0,
m_pVeilTex->GetWidth(), m_pVeilTex->GetHeight(),
m_pVeilTex->GetDC(), 0, 0,
m_pVeilTex->GetWidth(), m_pVeilTex->GetHeight(),
func);
}
Fade out 은 in 의 반대니까 생략하자.
그냥 프레임마다 delta time 값 더하면서
입력받은 주기, duration 값의 몇 퍼센트 진행됐는지 비율을 계산하고
그에 맞게 BLENDFUNCTION 의 alpha 값을 0 ~ 255 사이의 값으로 조절해주면 끝.
'Win32 api' 카테고리의 다른 글
| Win32 api 강의 62화. (0) | 2025.09.30 |
|---|---|
| Win32 api 강의 59 - 61화. (0) | 2025.09.30 |
| Win32 api 강의 55 - 56화. (0) | 2025.09.29 |
| Win32 api 강의 54화. (0) | 2025.09.27 |
| Win32 api 강의 53화. (0) | 2025.09.26 |