디시인사이드 갤러리

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

갤러리 본문 영역

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

∫ 2t dt=t²+c갤로그로 이동합니다. 2009.11.19 23:18:32
조회 768 추천 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/06 - -
AD 프로게이머가 될테야!! 운영자 25/10/01 - -
공지 프로그래밍 갤러리 이용 안내 [96] 운영자 20.09.28 47790 65
2895191 이재명이 대통령된 후로 공산주의 같은 정책을 못 펼치는구나 ㅎㅎ 나르시갤로그로 이동합니다. 15:01 12 0
2895190 현 정부 경제 정책을 시스템 아키텍처 관점에서 보니 드는 생각 나르시갤로그로 이동합니다. 14:58 14 0
2895189 주가, 환율 착시 효과 나르시갤로그로 이동합니다. 14:47 22 0
2895188 일본 지진때문에 정상화 당하고 있네 [2] 루도그담당(58.239) 14:14 37 0
2895187 앱히키는 씨발놈임 프갤러(118.235) 13:52 16 0
2895185 자료구조를 직접 구현할 일은 별로 없긴 하지만 개념은 중요함 [3] 프갤러(223.39) 13:38 56 0
2895184 스프링 같은 씹좆좆쓰지말고 [2] 루도그담당(58.239) 13:36 39 0
2895183 웹하는데 리액트 앱 라우터 방법도 모르면서 [2] ㅆㅇㅆ찡갤로그로 이동합니다. 13:28 40 0
2895182 C 공부세팅 완 [7] ㅇㅇ갤로그로 이동합니다. 13:27 43 0
2895181 딥시크 야무진데? [3] ㅇㅇ갤로그로 이동합니다. 13:19 30 0
2895180 항상 느끼지만 호기심을 가지는 건 좋다만 그 호기심을 타인에게 강요를 [5] ㅆㅇㅆ(124.216) 13:10 46 0
2895179 예전에 대학원서 리눅스 배울때 느꼈지만 리눅스의 공짜는 공짜는 아님 ㅆㅇㅆ(124.216) 13:05 31 0
2895178 자료구조 거의 쓸 데 없긴하지. 쓸데 있다는 애들은 저수준 하는애들이고 [2] ㅆㅇㅆ(124.216) 13:02 45 0
2895177 IPEA 정보처리기사협회 전산실 면접보러오라는데 프갤러(220.65) 12:33 19 0
2895176 자료구조란걸 배웠는데 그래서 뭐 어쩌란거고 제가 뭘 배운건가요?? [4] ㅇㅇ(223.38) 12:23 50 0
2895175 짱깨들이 관광으로 한국에 도움이 된다고? [2] ♥덩냥이♥갤로그로 이동합니다. 12:22 21 0
2895174 넷플릭스도 유튜브 정도의 검색기능이 없군요 [2] 헬마스터갤로그로 이동합니다. 12:19 18 0
2895172 요즘 리눅스 데스크톱은 오히려 능지가 떨어지는거같음 [4] 파란빤스갤로그로 이동합니다. 11:55 36 0
2895168 극우추적단을 알아보쟈⭐+ ♥덩냥이♥갤로그로 이동합니다. 11:22 29 0
2895167 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ [2] ♥덩냥이♥갤로그로 이동합니다. 11:14 33 0
2895160 아잇씨팔 또 쓰레기 같은 타입스크립트 보려니 속이 울렁거립니다. 프갤러(218.154) 09:03 37 0
2895159 대추 ㅇㅅㅇ [1] 헤르 미온느갤로그로 이동합니다. 08:55 25 0
2895158 태연 ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 08:53 26 1
2895157 아침부터 움직이니까 속이 안좋네요 프갤러(218.154) 08:52 18 0
2895156 하루 한 번 헤르미온느 찬양 [2] 헤르 미온느갤로그로 이동합니다. 08:52 37 0
2895154 ai 를 무시하는 사람과 의존하는 사람 모두 위험합니다 [4] 프갤러(223.39) 07:36 55 1
2895151 오오 마인드 적페 브레이버갤로그로 이동합니다. 05:05 24 0
2895149 우리은행에 통합된 민족계열 동일은행 발명도둑잡기(118.216) 02:58 18 0
2895147 77개 해외 무관사무실 68% 도청 등 보안장비 미흡 발명도둑잡기(118.216) 02:40 20 0
2895146 박혁거세 [1] 발명도둑잡기(118.216) 02:37 62 0
2895145 Z-A 일주일 기다리자 꽃길 포켓몬스터레전드 Z-A... 오늘 저녘이면 넥도리아2025(220.74) 02:14 19 0
2895143 피크민 아기 발명도둑잡기(118.216) 02:00 17 0
2895142 아 개씨발 모기 [2] ♥덩냥이♥갤로그로 이동합니다. 01:51 80 0
2895141 트레이더로 20조 번 러시아 수학자 발명도둑잡기(118.216) 01:50 25 0
2895134 오늘 출근 하시는 분 부자 되실 듯 발명도둑잡기(118.216) 01:25 25 0
2895124 음악 책과 SAT 점수 [3] 발명도둑잡기(118.216) 01:10 36 0
2895122 안예은 AHN YE EUN - 열 달 아흐레 1009 [1] 발명도둑잡기(118.216) 00:37 27 0
2895121 노시계도 놀란 찢시계 논란 ㄷㅅㄷ [1] ♥덩냥이♥갤로그로 이동합니다. 00:36 36 0
2895120 23억 로또 당첨되고 실제 사용처 정리해봤음... [1] ㅇㅇ(223.38) 00:36 44 0
2895118 murmulator 발명도둑잡기(118.216) 00:05 17 0
2895116 PICO-56 65c02 컴퓨터 발명도둑잡기(118.216) 00:04 18 0
2895114 라스베리파이 피코로 286 만들기 발명도둑잡기(118.216) 00:02 26 0
2895111 주 4.5일제를 왜 반대하는거임? [1] 야옹아저씨갤로그로 이동합니다. 10.09 54 1
2895110 성소수자는 미인계에 약한 것 같아 보인다. [1] 발명도둑잡기(118.216) 10.09 44 0
2895108 글 쓰고 자거 싶은데.. 이미 체력이.. [2] ♥덩냥이♥갤로그로 이동합니다. 10.09 84 0
2895107 오랜만에 왔는데 갤이 더 씹창이 나있구나 [5] 아스카영원히사랑해갤로그로 이동합니다. 10.09 71 1
2895106 날벌레들은 모기약으로 안 죽넹.. [3] ♥덩냥이♥갤로그로 이동합니다. 10.09 84 0
2895099 [냥덩칼럼] 삶은 죽음으로 시작된다 [5] ♥덩냥이♥갤로그로 이동합니다. 10.09 88 0
2895096 한투증 api 웹소켓 자꾸 데이터 보내다가 마는데 [3] 밀우갤로그로 이동합니다. 10.09 45 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

디시미디어

디시이슈

1/2