본문 바로가기

Win32 api

Win32 api 강의 59 - 61화.

- Fade 코드 수정.

// CCamera.h
...
struct tCamEffectInfo
{
    CAM_EFFECT  eEffect;
    float       fDuration;
    float       fTimeAcc;
};

class CCamera
{
    SINGLETON(CCamera)
private:
    ...
    CTexture*       m_pVeilTex;         // 화면을 덮는 베일 텍스쳐.
    //CAM_EFFECT      m_eEffect;          // 카메라 효과.
    //float           m_fEffectDuration;  // 효과 지속 시간.
    //float           m_fEffectTimeAcc;   // 효과 시간 누적.

    queue<tCamEffectInfo> m_qEffectInfo;

public:
    ...
    inline void FadeIn(float duration)
    {
        assert(duration > 0.f);

        tCamEffectInfo effectInfo = {};
        effectInfo.eEffect = CAM_EFFECT::FADE_IN;
        effectInfo.fDuration = duration;
        effectInfo.fTimeAcc = 0.f;

        m_qEffectInfo.push(effectInfo);
    }
    inline void FadeOut(float duration)
    {
        assert(duration > 0.f);

        tCamEffectInfo effectInfo = {}; 
        effectInfo.eEffect = CAM_EFFECT::FADE_OUT;
        effectInfo.fDuration = duration;
        effectInfo.fTimeAcc = 0.f;

        m_qEffectInfo.push(effectInfo);
    }
    ...

 

기존 멤버 변수들을 구조체 tCamEffectInfo 에 묶고, 이걸 queue 자료구조에 보관.

Event Manager 에서 했던 것처럼 매 프레임마다 해당 queue 에 쌓인 effect 요청들을 처리해주면 됨.

// CCamera.cpp
...
void CCamera::render(HDC hDC)
{
    if (m_qEffectInfo.empty())
        return;
    tCamEffectInfo& effectInfo = m_qEffectInfo.front();

    effectInfo.fTimeAcc += DELTATIMEF;
    if (effectInfo.fTimeAcc > effectInfo.fDuration)
        effectInfo.fTimeAcc = effectInfo.fDuration;

    float alphaRatio = effectInfo.fTimeAcc / effectInfo.fDuration;
    BLENDFUNCTION func = {};
    func.BlendOp = AC_SRC_OVER;
    func.BlendFlags = 0;
    func.AlphaFormat = 0;

    switch (effectInfo.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);

    if(effectInfo.fTimeAcc >= effectInfo.fDuration)
    {
        m_qEffectInfo.pop();
    }
}

 

- 렌더링 최적화.

강의에서는 각 타일들을 인덱스 순서대로 좌표상에 배치되도록 구현했기 때문에, 카메라 시야 범위에서 보이는 타일들을 계산해서

해당되는 타일들만 render 함수를 호출할 수 있도록 별도의 render_tile 함수를 구현했음.

 

나는 일단 모든 오브젝트들에 카메라 밖인지 검사하는 함수를 추가해서 간단하게 렌더링 최적화를 적용함.

// CScene.cpp
...
void CScene::render(HDC hDC)
{
    for (UINT i = 0; i < (UINT)GROUP_TYPE::END; ++i)
    {
        vector<CObject*>::iterator iter = m_arrObj[i].begin();
        for (; iter != m_arrObj[i].end();)
        {
            ...
            if (obj->is_in_camera_view())
            {
                obj->render(hDC);
            }
            ++iter;
        }
    }
}

 

Scene 의 render 함수에서 모든 오브젝트 그룹에서 카메라 밖인지 체크하고 render 호출.

// CObject.h
class CObject
{
...
public:
    ...
    virtual void render(HDC hDC);

    // 오브젝트가 화면 밖에 있을 때 렌더링을 건너뛰기 위한 함수.
    virtual bool is_in_camera_view() const { return true; }
    ...

 

Object 클래스에 virtual 함수로 선언해주고, Tile 클래스에서 override 해준다.

// CTile.cpp
...
bool CTile::is_in_camera_view() const
{
    POINT resolution = CCore::GetInstance()->GetResolution();
    Vector2 pos = CCamera::GetInstance()->WorldToScreen(GetPos());
    Vector2 size = GetSize();
    if (pos.x + size.x < 0.f || pos.x > static_cast<float>(resolution.x)
        || pos.y + size.y < 0.f || pos.y > static_cast<float>(resolution.y))
    {
        return false;
    }
    return true;
}

 

 

실행해보면, fps 차이가 나긴 한다. 다만 현재 타일 사이즈를 너무 작게 하는 바람에, 화면에 그려지는 게 그냥 많기는 함.

 

타일들은 아무래도 타일맵이라는 클래스를 새로 만든 뒤, 타일맵 객체에서 한번에 그려주는 방식으로 만들어주는 것이 좋을 듯?

'Win32 api' 카테고리의 다른 글

Win32 api 강의 63화.  (0) 2025.10.01
Win32 api 강의 62화.  (0) 2025.09.30
Win32 api 강의 57 - 58화.  (0) 2025.09.29
Win32 api 강의 55 - 56화.  (0) 2025.09.29
Win32 api 강의 54화.  (0) 2025.09.27