디시인사이드 갤러리

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

갤러리 본문 영역

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

∫ 2t dt=t²+c갤로그로 이동합니다. 2009.11.19 23:18:32
조회 766 추천 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/06/30 - -
AD 휴대폰 바꿀까? 특가 구매 찬스! 운영자 25/07/02 - -
271320 감사합니다 ㅠㅠ 성공해씁니다 [2] 안초심갤로그로 이동합니다. 11.09.11 48 0
271319 물론 대학이 전부는 아니지만 [5] 늅늅늅늅(180.71) 11.09.11 93 0
271318 이렇게 쓰면 10점만점중에 10점 줄거같음?? [6] 독담갤로그로 이동합니다. 11.09.11 102 0
271316 꿀레횽님 호..혹시 [4] 독담갤로그로 이동합니다. 11.09.11 54 0
271315 명령프롬프트 뜨고나서 바로꺼지는데 어케해야함 ..? [5] 안초심갤로그로 이동합니다. 11.09.11 82 0
271314 스택메모리, 힙메모리 개념좀 세워주세요 [6] 독담갤로그로 이동합니다. 11.09.11 110 0
271313 이거 좀 알려주세요... [12] 안초심갤로그로 이동합니다. 11.09.11 113 0
271312 VMware까는중 꿀레(14.33) 11.09.11 41 0
271311 너희듷 [3] 어떡해갤로그로 이동합니다. 11.09.11 61 0
271310 로또 시발 5등 ㅋㅋㅋㅋㅋㅋㅋ 독담갤로그로 이동합니다. 11.09.11 24 0
271308 독담 너 이색기는 봅니다. [1] 꿀레(14.33) 11.09.11 35 0
271306 이제야찾았네 三didas갤로그로 이동합니다. 11.09.11 39 0
271304 살 잘찌는 체질은 개발자 하면 안된다. [1] 쵸쵸(219.251) 11.09.11 72 0
271303 니들 월요일 되면 로또 꼭 사라. 독담갤로그로 이동합니다. 11.09.11 37 0
271302 스포2 = 콜옵4 [1] 쵸쵸(219.251) 11.09.11 37 0
271301 스포2 잘만들었다. [3] 쵸쵸(219.251) 11.09.11 47 0
271300 홈페이지 레이아웃여.. [7] ㅇㅇ(121.169) 11.09.11 84 0
271299 형들 궁금한거 잇어여 [6] 궁금(182.214) 11.09.11 54 0
271298 아 시발 졷됨 ㅋㅋㅋ 내동생이 똥쌋는데 변기막힘 [6] 독담갤로그로 이동합니다. 11.09.11 194 0
271297 살잘찌는인간들힘들겠다 [2] Agangs갤로그로 이동합니다. 11.09.11 57 0
271296 라면에 넣을게 없는데 [1] 로하로하알로하갤로그로 이동합니다. 11.09.10 34 0
271294 횽들 나 입갤했는데.. [10] 에헤헤헿갤로그로 이동합니다. 11.09.10 71 0
271293 딸기알밥님 웹프로그래머에여? [4] ㅇㅇ(121.169) 11.09.10 73 0
271292 자기공부질문말고 과제질문 [5] 三didas갤로그로 이동합니다. 11.09.10 65 0
271291 컴돌이 대학 어디임 ㅇㅇ 말좀 해바 그냥 [1] 로하로하알로하갤로그로 이동합니다. 11.09.10 68 0
271290 아시바...메인보드가나갔나 三didas갤로그로 이동합니다. 11.09.10 19 0
271289 명지대도 인서울임?? [8] 독담갤로그로 이동합니다. 11.09.10 125 0
271287 그거 뭐냐 NHN 에서 지들이 학원 만들어서 채용한다는거 독담갤로그로 이동합니다. 11.09.10 93 0
271286 이거 malloc 뒤에다가 +1은 왜하는거예용? [9] 독담갤로그로 이동합니다. 11.09.10 135 0
271285 회사에서 맨날 논다고 하기 뭐해서 자기발전 해야 되는거 짱나지 않냐??? [1] 허세강갤로그로 이동합니다. 11.09.10 77 0
271284 탑밴드보고 느끼는거 없냐? [2] 쵸쵸쵸(219.251) 11.09.10 36 0
271283 앞으로 4년동안 나를 보게될거야. [2] 독담갤로그로 이동합니다. 11.09.10 57 0
271282 컴돌이가 영어를 그렇게 잘 한다면 생각놀이갤로그로 이동합니다. 11.09.10 57 0
271281 도와주세요~ 메틴이라는게임 핵만드는중... [3] 메튄프로그램(118.128) 11.09.10 688 0
271280 젊어서 si가는것도 나쁘진않다. [1] 쵸쵸쵸(219.251) 11.09.10 103 0
271279 니들은 실력을 글케좋은데 인서울 못하냐??? [12] 컴돌이(180.227) 11.09.10 166 0
271278 내 친구 이야기 (122.34) 11.09.10 69 0
271276 이해가 안되용 도와줘요 횽들 ㅜㅜ [6] 독담갤로그로 이동합니다. 11.09.10 69 0
271275 프리랜서 프로그래머들은 무슨일을하나요 [3] 박구갤로그로 이동합니다. 11.09.10 169 0
271274 형들 사회생활할때 공익이 좀 마이너스 요소야? [2] ㅇㅇ(61.33) 11.09.10 85 0
271273 님들아 치과의사도 고급인력입니까? 131313(223.222) 11.09.10 37 0
271272 프리랜서 장비 질문 [2] ㅍㅍ(122.34) 11.09.10 89 0
271271 컴돌이 영어올리지말고 컴퓨터 언어 올려줘 그럼 해석해봄 [5] 131313(223.222) 11.09.10 70 0
271270 혹시 stable-marriage algorithm에 아는횽들있음?? [3] 살려줘횽들(119.203) 11.09.10 53 0
271269 드디어 알아냄 시발 ㅜㅜ [3] 독담갤로그로 이동합니다. 11.09.10 69 0
271268 나보다 영어 잘하는 것들이 이거 해석해봐라 ㅋㅋㅋ [11] 컴돌이(180.227) 11.09.10 142 0
271267 프로그래머에대한 자부심을 갖고있나요? [4] 박구갤로그로 이동합니다. 11.09.10 108 0
271266 컴똘똘이 어그로 글 어디갓냐 [3] 로하로하알로하갤로그로 이동합니다. 11.09.10 48 0
271265 프겔러들은 이런생각안해봤음? 나는 자주생각하는데 [1] 131313(223.222) 11.09.10 34 0
271264 형님들 진짜 조언좀 해주세여!!! [5] 광주지라(121.137) 11.09.10 54 0
뉴스 걸스데이 민아, 배우 온주완과 11월 결혼 디시트렌드 07.04
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2