본문 바로가기

Win32 api

Win32 api 강의 57 - 58화.

- 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