디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

적분시리즈: 1. 메세지 루프와 D3D 장치 만들기

∫ 2t dt=t²+c갤로그로 이동합니다. 2009.11.19 23:18:32
조회 770 추천 0 댓글 5


144119204B0550AF89026C
프로젝트를 하나 만들자. 내 프로젝트의 이름을 거창하게 MidiGalaxy라고 짓겠다.

게임의 가장 기초가 될 유일무이한 클래스 GGame 클래스를 만들겠다.
GGame 클래스는 전반적인 D3D장치와 메세지 루프를 관리할 것이다.

Direct3D를 사용하기 위해서는 \'d3dx9.h\'라는 헤더 파일이 필요하다.
그리고 \'d3d9.lib\'와 \'d3dx9d.lib\'라는 라이브러리 파일도 필요하다.
D3D 프로그래밍을 할때는 빼먹지 않고 반드시 추가하도록 하자.

GRET GGame::Create3DDevice(HWND hWnd)
{
    m_pd3d=Direct3DCreate9(D3D_SDK_VERSION);
    if(m_pd3d==NULL)return GRET_ERROR_NOD3D;
    D3DPRESENT_PARAMETERS d3dpp=_getdpp();
    if( FAILED(m_pd3d->CreateDevice(D3DADAPTER_DEFAULT, m_dev.d3ddt, hWnd,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_pd3dd)) )return GRET_ERROR_FAIL;
    if(FAILED( D3DXCreateSprite(m_pd3dd, &m_pspr) ))return GRET_ERROR_FAIL;
    m_dev.hwnd=hWnd;
    return 0;
}

D3D 장치를 생성하는 Create3DDevice함수이다.
Direct3D 장치를 생성하는 단계는 다음과 같다.
1. 먼저 Direct3DCreate9 함수를 호출하여 IDirect3D9 를 얻는다.
2. IDirect3D9의 CreateDevice 함수를 호출하여 IDirect3DDevice를 얻는다.

CreateDevice 함수를 호출할 때 우리가 만들 장치의 속성을 지정해준다.
GGame::_getdpp함수가 우리가 만들 장치의 속성을 구한다.
D3DPRESENT_PARAMETERS라는 구조체로 장치의 속성이 정의되는데
필드 이름만 봐도 무슨 역할을 하는지 쉽게 알 수 있다.

몇 가지 예를 들자면
BackBufferWidth : 백버퍼의 가로 길이
BackBufferHeight : 백버퍼의 세로 길이
BackBufferFormat :  백버퍼의 포맷
참 쉽죠?

다시 본론으로 돌아가서 Create3DDevice 함수에서는 D3D장치를 얻은 후에
ID3DXSprite까지 만들고 있다.
ID3DXSprite는 D3D에서 2D 출력을 간편하게 할 수 있도록 제공하는 인터페이스이다.
D3DXCreateSprite 함수를 통해 생성할 수 있다.

GRET GGame::MessageLoop()
{
    bool islost=false;
    MSG msg;
    if(m_pd3dd)OnCreate();
    while(1)
    {
        if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
        {
            if(msg.message==WM_QUIT)return 0;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            OnProc();
            if(islost)
            {
                if((!m_dev.fullscreen || m_activated) && Reset3DDevice()==0)
                {
                    islost=false;
                    ();
                }
            }
            else if(m_drawskip)
            {
                OnDrawSkip();
            }
            else
            {
                m_pd3dd->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(64,128,192), 1.f, 0);
                if( SUCCEEDED(m_pd3dd->BeginScene()) )
                {
                    m_pspr->Begin(D3DXSPRITE_ALPHABLEND);
                    OnDraw();
                    m_pspr->End();
                    m_pd3dd->EndScene();
                    if(m_pd3dd->Present(NULL, NULL, NULL, NULL)==D3DERR_DEVICELOST)
                    {
                        islost=true;
                        OnLost();
                    }
                }
            }
            OnPostProc();
            m_drawskip=false;
        }
    }
    return 0;
}
이것이 우리 게임을 작동시키는 기초가 될 메세지루프 부분이다.
일반 윈도우 프로그램 메세지루프에서는 GetMessage함수를 사용하지만, 게임용 메세지푸르에서는 PeekMessage함수를 사용한다.

두 함수의 차이점은
GetMessage함수는 큐에 메세지가 없으면 메세지가 들어올 때까지 계속 기다리지만,
PeekMessage함수는 큐에 메세지가 없으면 즉시 0을 리턴한다는 것이다.

게임 프로그램은 메세지가 있던 없던 상관없이 늘 일정한 속도로 매초에 수십개의 프레임을 처리해야 한다. 그러므로 GetMessage함수 대신에 PeekMessage함수를 쓸 수 밖에 없다.

메세지가 없을 경우에는 첫번째 else부분으로 들어온다. 먼저 OnProc함수를 호출한다. OnProc함수에서는 매 프레임마다 처리해야할 것들을 처리한다.

만약 장치를 잃은 상태라면(islost가 참이라면) Reset3DDevice를 호출해, 장치를 복구하려고 한다. 만약 장치복구에성공했다면 함수를 호출한다. 함수에서는 장치가 복구되었을때, 해야할 것들을 처리한다.

그리기를 생략한다면(m_drawskip이 참이라면) OnDrawSkip을 호출한다. 종종 부하가 걸려서 초당 프레임 횟수를 맞추지 못할 때가 있다. 그럴때는 과감하게 그리기를 생략하고, 다음 프레임으로 넘어가야 한다.

그리기를 생략하지 않았고, 장치도 정상적이라면 그리기는 것을 시작한다.
D3D의 기본적인 그리기과정은 다음과 같다.
1. IDirect3DDevice9::Clear로 화면을 깨끗이 지운다.
2. IDirect3DDevice9::BeginScene으로 그리기를 시작한다.
3. 열심히 그린다.
4. IDirect3DDevice9::EndScene으로 그리기를 마친다.
5. IDirect3DDevice9::Present로 그린 것을 화면으로 전송한다.

먼저 IDirect3DDevice9::Clear함수를 사용하여서 화면을 깨끗이 지워준다.
세 번째 인자로 색깔을 지정해 줄 수 있다. 색깔을 지정해 줄때는 D3DCOLOR_XRGB나 D3DCOLOR_ARGB 매크로를 사용하면 편리하다.

그 다음 IDirect3DDevice9::BeginScene함수를 호출해서 그리기를 시작한다.
함수가 실패했다면 그릴수가 없으므로 넘어간다.

이제 그리기를 시작하자.
ID3DXSprite 인터페이스를 2D그리기를 쉽게 할수있게 도와준다고 했다.
ID3DXSprite를 이용해 화면에 2D를 그리려면 몇가지 해야할 일이 있다.
1. ID3DXSprite::Begin함수를 호출해서 그리기를 시작한다.
2. 열심히 그린다.
3. ID3DXSprite::End로 그리기를 마친다.
단, 이 모든 과정은 IDirect3DDevice9의 BeginScene과 EndScene사이에서 들어가야한다.

ID3DXSprite::Begin함수의 인자로 넘겨준 D3DXSPRITE_ALPHABLEND는 그리기할때 알파블렌딩을 사용할 것임을 뜻한다.
OnDraw함수에서는 화면에 그리는 일을 담당한다.

IDirect3DDevice9::EndScene을 호출하여 그리기를 마무리하고,
IDirect3DDevice9::Present를 호출하여 화면에 전송을 한다.
단 이 때 몇가지 문제가 발생할 수 있다. 가끔 장치를 잃어버리는 경우가 있다. 이 때는 장치를 이용하던 것들을 잠시 해제해놓고, 장치를 복구한 뒤, 다시 복구시켜야 한다.
OnLost함수에서는 장치를 사용하는 것들을 해제하는 일을 담당한다.

그리고 그리기를 마치고 OnPostProc함수를 호출한다. OnPostProc함수는 그리기후 뒷처리를 담당한다.

void GGame::OnLost()
{
    m_pspr->OnLostDevice();
}

void GGame::()
{
    m_pspr->Device();
}
OnLost함수와 함수이다.
ID3DXSprite와 같은 인터페이스는 IDirect3DDevice9장치를 이용한다. 그러므로 장치를 잃어버렸을 경우에는OnLostDevice를 호출하여 해제하고, 장치를 복구했을 때는 Device를 호출하여 다시 원상복구시킨다.
D3D에서 이처럼 장치를 잃었을 때와 복구했을때 특별히 처리를 해주어야하는 것들이 있는데, 그들은 모두 OnLostDevice와Device 함수를 가지고 있다. 그러니까 이런 함수를 가지고 있는 놈들은 장치를 잃었을때, 복구했을때 이 함수들을꼭 호출해줘야한다.

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
/*
그저그런 기본적인 윈도우 생성코드들은 생략
*/
    RegisterClassEx(&wcex);
    g_hInst = hInstance;
    g_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, 804, 695, NULL, NULL, hInstance, NULL);
    if (!g_hWnd) return FALSE;
    ShowWindow(g_hWnd, nCmdShow);
    UpdateWindow(g_hWnd);

    GGame &game=*GGame::GetInstance();
   
    game.m_dev.d3ddt=D3DDEVTYPE_HAL;
    game.m_dev.fullscreen=true;
    game.m_dev.backformat=D3DFMT_A8R8G8B8;
    game.m_dev.d3dse=D3DSWAPEFFECT_DISCARD;
    game.m_dev.buffercount=2;
    game.m_dev.width=800;
    game.m_dev.height=600;
    game.m_dev.stencilformat=D3DFMT_UNKNOWN;
    game.Create3DDevice(g_hWnd);
    game.MessageLoop();
    return 0;
}
메인 함수 부분이다. 윈도우를 생성한뒤 GGame클래스를 얻어서 장치를 생성하고 있다.
여기서 중요한 점.
GGame클래스는 이 프로그램 전체에서 단 하나만 생성되어야 한다.
이럴 경우 GGame클래스의 생성자를 protected나 private로 설정하면, GGame클래스 외부에서는 GGame인스턴스를 생성할 수 없게 된다. 그리고 static 함수로 GetInstance함수를 만들어 놓아서 유일한 인스턴스를 반환하게한다. 이렇게 하면 프로그램 전체 어디서에서도 GetInstance함수를 통해서 유일한 인스턴스를 얻을수 있게 된다. 흔히 이런것을 가리켜 싱글턴(Singleton)패턴이라고 한다.

추천 비추천

0

고정닉 0

0

원본 첨부파일 1

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 며느리, 사위되면 시댁, 처가에 잘할 것 같은 스타 운영자 25/10/13 - -
AD iPad Pro 사전예약!! 운영자 25/10/17 - -
공지 프로그래밍 갤러리 이용 안내 [96] 운영자 20.09.28 48034 65
2897098 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ ♥덩냥이♥갤로그로 이동합니다. 19:32 0 0
2897097 강민호 어디로 가려낭 [3] ♥덩냥이♥갤로그로 이동합니다. 19:18 12 0
2897096 박병호는 은퇴해야하지 않낭 ♥덩냥이♥갤로그로 이동합니다. 19:15 7 0
2897095 문동주는 아무리봐도 지리넹 ㄷㅅㄷ ♥덩냥이♥갤로그로 이동합니다. 19:13 5 0
2897094 칰아섭은 아무리 봐도 어색하넹 ㅋㅅㅋ ♥덩냥이♥갤로그로 이동합니다. 19:10 5 0
2897093 눈동자속의 faraway 남자 커버 배구공(119.202) 19:06 8 0
2897092 기아는 양현종 은퇴하면 더 안볼듯? ♥덩냥이♥갤로그로 이동합니다. 18:55 6 0
2897091 한화끼니까 존나 꿀잼 ㅋㅅㅋ ♥덩냥이♥갤로그로 이동합니다. 18:54 8 0
2897089 작년은 편파판정으로 기아가 너무 쉽게 이겨서 노잼이엇음 ♥덩냥이♥갤로그로 이동합니다. 18:52 8 0
2897088 미운 사내 배구공(119.202) 18:49 14 0
2897086 나도 10키로만 빼고 싶다 ㅇㅅㅇ [4] ㅇㅅㅇ(1.216) 18:35 27 0
2897085 돌진만과돌경문 ㅋㅅㅋ ♥덩냥이♥갤로그로 이동합니다. 18:30 12 0
2897084 야구 맛잇당 맛잇어 ㅋㅅㅋ [3] ♥덩냥이♥갤로그로 이동합니다. 18:22 17 0
2897083 소켓 섹션 만들었다. 프갤러(121.172) 18:11 16 0
2897082 이런차 타고싶당 [1] 프갤러(175.197) 18:09 19 0
2897081 아시발 nvim으로 이제 코드에디팅 하는디 좋네 ㅇㅇ갤로그로 이동합니다. 18:01 15 0
2897080 야구 미쳤노ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ ♥덩냥이♥갤로그로 이동합니다. 17:40 28 0
2897079 회사 코드에 러스트 몰래 심어넣을 브랜치 이름 추천좀 [5] 프갤러(122.32) 17:24 41 1
2897078 [대한민국] 대한민국이 간첩들을 대하는 자세 프갤러(121.172) 17:11 15 0
2897077 R 프로그래밍 과제 도와주실 분 구합니다 [3] 가즈아(119.70) 16:47 57 0
2897076 좀 이해가 안가노 exe 로 만들면 60짜리를 웹으로 해서 [5] ㅆㅇㅆ(124.216) 16:42 63 0
2897075 학교 성적 5~6등급이면 요즘은 건동홍은감 류류(118.235) 16:41 21 0
2897074 C++ will never die. C++ 은 절대 죽지 않는다. 프갤러(59.16) 16:14 25 0
2897073 [애니뉴스] 문화 콘텐츠의 중심 프갤러(121.172) 15:51 15 1
2897072 그냥 코드가 테스트 통과하면 쓰는거고 못하면 [6] ㅆㅇㅆ(124.216) 15:46 84 0
2897071 고등학생 개발자 고민 [5] 프갤러(220.123) 15:43 77 0
2897070 사법부는 대한민국의 모든 남성들에게 피해보상금을 지불해야 된다 프갤러(121.172) 15:28 18 0
2897069 여자아이 응딩이 만지고 싶음 [1] 류류(118.235) 15:26 34 0
2897068 지금 듣는 노래인데 어떰? ㅁㅁ갤로그로 이동합니다. 15:13 14 0
2897067 교수 연락올때마다 씨발 심장이 덜컥 내려앉는데 이거 사랑이냐? [6] ㅆㅇㅆ(124.216) 15:13 79 0
2897066 오늘 학생 앞에서 쿼드트리 직접 구현하다가 존나 버벅대서 쪽팔렸음ㅋㅋㅋ [2] ㅆㅇㅆ(124.216) 15:09 58 0
2897065 밥벌이를 위해 개발하다 보면 [4] chironpractor갤로그로 이동합니다. 15:05 56 0
2897063 자기 개발 안하는 개발자는 없어졌으면 좋겠다 [4] 프갤러(183.109) 14:19 77 0
2897062 파워 교체 했습니다. 2009년 파워 넥도리아20252024(220.74) 14:18 13 0
2897061 'XX 꼭 배워야 함?' 이러는거는 '수학 꼭 배워야함?'으로 치환 가능 [2] 박민준갤로그로 이동합니다. 14:12 61 1
2897060 인생에 되는 일도 없고, 더이상 기대할 일조차 없다. [1] ㅇㅇ(223.39) 14:08 28 0
2897059 ㅇㅅㅇ [2] ♥덩냥이♥갤로그로 이동합니다. 14:02 29 0
2897058 나는 인간 코드도 안 믿고 ai코드도 안 믿고 [2] ㅆㅇㅆ(124.216) 13:49 47 0
2897057 웹에서 SI빼고 내수용 엔터프라이즈향 빼면 남는 업체는 한줌임 [4] 박민준갤로그로 이동합니다. 13:49 70 0
2897056 임베디드는 오래 살아남을 것 같긴 함 [2] 에이도비갤로그로 이동합니다. 13:48 49 0
2897055 나는 바이브 코딩 솔직히 못미더움 [1] 프갤러(176.227) 13:37 64 0
2897054 AI에 대체되는게 불안하면 임베디드도 할만함 [5] 박민준갤로그로 이동합니다. 13:31 70 0
2897053 직원으로서 코딩의 길은 가성비 낮다고 생각해 [13] chironpractor갤로그로 이동합니다. 13:08 136 0
2897052 요기요 개발자 주말에 쉼? [1] ㅇㅇ(211.234) 12:59 50 0
2897051 웹개발은 다 뒤진거 같고 [3] 프갤러(211.234) 12:49 96 0
2897050 AI 맹신, 무식하면 용감하다. [2] 프갤러(59.16) 12:40 74 0
2897048 바이브 코딩 하니까 약간 자괴감 오네 [2] ㅇㅇ갤로그로 이동합니다. 12:17 74 0
2897047 [자바스크립트] Array에서 특정 요소를 제거하는 코드 프갤러(121.172) 11:47 36 0
2897046 그냥 기획이나 마케팅만 할거면 데싸는 안배워도 됨? [13] 프갤러(121.175) 11:14 101 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

디시미디어

디시이슈

1/2